aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Kconfig15
-rw-r--r--drivers/acpi/Makefile3
-rw-r--r--drivers/acpi/ac.c4
-rw-r--r--drivers/acpi/acpi_memhotplug.c11
-rw-r--r--drivers/acpi/asus_acpi.c227
-rw-r--r--drivers/acpi/battery.c4
-rw-r--r--drivers/acpi/bay.c411
-rw-r--r--drivers/acpi/bus.c78
-rw-r--r--drivers/acpi/button.c9
-rw-r--r--drivers/acpi/cm_sbs.c8
-rw-r--r--drivers/acpi/container.c4
-rw-r--r--drivers/acpi/debug.c2
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c3
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c83
-rw-r--r--drivers/acpi/dispatcher/dsobject.c62
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c2
-rw-r--r--drivers/acpi/dispatcher/dswexec.c12
-rw-r--r--drivers/acpi/dock.c388
-rw-r--r--drivers/acpi/ec.c400
-rw-r--r--drivers/acpi/executer/exconfig.c123
-rw-r--r--drivers/acpi/executer/exconvrt.c32
-rw-r--r--drivers/acpi/executer/exdump.c87
-rw-r--r--drivers/acpi/executer/exmisc.c14
-rw-r--r--drivers/acpi/executer/exoparg1.c26
-rw-r--r--drivers/acpi/executer/exoparg2.c4
-rw-r--r--drivers/acpi/executer/exresnte.c16
-rw-r--r--drivers/acpi/executer/exresolv.c60
-rw-r--r--drivers/acpi/executer/exresop.c50
-rw-r--r--drivers/acpi/executer/exstore.c61
-rw-r--r--drivers/acpi/executer/exstoren.c3
-rw-r--r--drivers/acpi/fan.c6
-rw-r--r--drivers/acpi/hardware/hwsleep.c44
-rw-r--r--drivers/acpi/namespace/Makefile2
-rw-r--r--drivers/acpi/namespace/nsdump.c5
-rw-r--r--drivers/acpi/namespace/nseval.c73
-rw-r--r--drivers/acpi/namespace/nsnames.c7
-rw-r--r--drivers/acpi/namespace/nspredef.c900
-rw-r--r--drivers/acpi/namespace/nssearch.c2
-rw-r--r--drivers/acpi/namespace/nsxfeval.c78
-rw-r--r--drivers/acpi/namespace/nsxfname.c5
-rw-r--r--drivers/acpi/numa.c2
-rw-r--r--drivers/acpi/osl.c55
-rw-r--r--drivers/acpi/parser/psloop.c2
-rw-r--r--drivers/acpi/parser/psparse.c32
-rw-r--r--drivers/acpi/pci_link.c6
-rw-r--r--drivers/acpi/pci_root.c4
-rw-r--r--drivers/acpi/pci_slot.c12
-rw-r--r--drivers/acpi/power.c74
-rw-r--r--drivers/acpi/processor_core.c6
-rw-r--r--drivers/acpi/processor_idle.c1
-rw-r--r--drivers/acpi/processor_perflib.c35
-rw-r--r--drivers/acpi/processor_throttling.c12
-rw-r--r--drivers/acpi/reboot.c25
-rw-r--r--drivers/acpi/resources/rscalc.c5
-rw-r--r--drivers/acpi/resources/rscreate.c10
-rw-r--r--drivers/acpi/sbs.c4
-rw-r--r--drivers/acpi/sbshc.c6
-rw-r--r--drivers/acpi/scan.c90
-rw-r--r--drivers/acpi/sleep/main.c68
-rw-r--r--drivers/acpi/sleep/proc.c18
-rw-r--r--drivers/acpi/system.c5
-rw-r--r--drivers/acpi/tables/tbfadt.c32
-rw-r--r--drivers/acpi/tables/tbinstal.c61
-rw-r--r--drivers/acpi/thermal.c57
-rw-r--r--drivers/acpi/toshiba_acpi.c4
-rw-r--r--drivers/acpi/utilities/utalloc.c53
-rw-r--r--drivers/acpi/utilities/utcopy.c29
-rw-r--r--drivers/acpi/utilities/utdelete.c12
-rw-r--r--drivers/acpi/utilities/utglobal.c52
-rw-r--r--drivers/acpi/utilities/utmisc.c9
-rw-r--r--drivers/acpi/utilities/utobject.c15
-rw-r--r--drivers/acpi/utilities/utxface.c7
-rw-r--r--drivers/acpi/utils.c4
-rw-r--r--drivers/acpi/video.c60
-rw-r--r--drivers/acpi/wmi.c49
-rw-r--r--drivers/ata/libata-acpi.c135
-rw-r--r--drivers/ata/libata-core.c68
-rw-r--r--drivers/ata/libata-eh.c26
-rw-r--r--drivers/ata/libata-scsi.c14
-rw-r--r--drivers/ata/libata-sff.c11
-rw-r--r--drivers/ata/libata.h19
-rw-r--r--drivers/ata/sata_via.c35
-rw-r--r--drivers/base/memory.c4
-rw-r--r--drivers/base/node.c69
-rw-r--r--drivers/block/DAC960.c6
-rw-r--r--drivers/block/amiflop.c46
-rw-r--r--drivers/block/aoe/aoeblk.c14
-rw-r--r--drivers/block/ataflop.c37
-rw-r--r--drivers/block/brd.c5
-rw-r--r--drivers/block/cciss.c71
-rw-r--r--drivers/block/cpqarray.c28
-rw-r--r--drivers/block/floppy.c54
-rw-r--r--drivers/block/loop.c59
-rw-r--r--drivers/block/nbd.c30
-rw-r--r--drivers/block/paride/pcd.c21
-rw-r--r--drivers/block/paride/pd.c14
-rw-r--r--drivers/block/paride/pf.c22
-rw-r--r--drivers/block/paride/pt.c2
-rw-r--r--drivers/block/pktcdvd.c56
-rw-r--r--drivers/block/swim3.c32
-rw-r--r--drivers/block/ub.c22
-rw-r--r--drivers/block/viodasd.c10
-rw-r--r--drivers/block/virtio_blk.c8
-rw-r--r--drivers/block/xd.c4
-rw-r--r--drivers/block/xd.h2
-rw-r--r--drivers/block/xen-blkfront.c15
-rw-r--r--drivers/block/xsysace.c11
-rw-r--r--drivers/block/z2ram.c7
-rw-r--r--drivers/cdrom/cdrom.c23
-rw-r--r--drivers/cdrom/gdrom.c14
-rw-r--r--drivers/cdrom/viocd.c21
-rw-r--r--drivers/char/agp/ali-agp.c2
-rw-r--r--drivers/char/agp/amd64-agp.c2
-rw-r--r--drivers/char/agp/ati-agp.c2
-rw-r--r--drivers/char/agp/backend.c2
-rw-r--r--drivers/char/agp/intel-agp.c2
-rw-r--r--drivers/char/agp/nvidia-agp.c2
-rw-r--r--drivers/char/agp/parisc-agp.c4
-rw-r--r--drivers/char/agp/via-agp.c2
-rw-r--r--drivers/char/amiserial.c6
-rw-r--r--drivers/char/ds1286.c34
-rw-r--r--drivers/char/ds1302.c24
-rw-r--r--drivers/char/epca.c6
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hvc_console.c86
-rw-r--r--drivers/char/hvc_console.h12
-rw-r--r--drivers/char/hvc_irq.c5
-rw-r--r--drivers/char/hvc_iseries.c1
-rw-r--r--drivers/char/hvc_vio.c1
-rw-r--r--drivers/char/hvc_xen.c1
-rw-r--r--drivers/char/ip27-rtc.c24
-rw-r--r--drivers/char/nvram.c6
-rw-r--r--drivers/char/pc8736x_gpio.c11
-rw-r--r--drivers/char/random.c36
-rw-r--r--drivers/char/raw.c8
-rw-r--r--drivers/char/rtc.c40
-rw-r--r--drivers/char/sx.c6
-rw-r--r--drivers/char/sysrq.c2
-rw-r--r--drivers/char/tpm/tpm.c2
-rw-r--r--drivers/char/tty_port.c2
-rw-r--r--drivers/char/virtio_console.c1
-rw-r--r--drivers/char/vr41xx_giu.c2
-rw-r--r--drivers/clocksource/acpi_pm.c7
-rw-r--r--drivers/cpuidle/cpuidle.c16
-rw-r--r--drivers/dma/Kconfig10
-rw-r--r--drivers/dma/dmatest.c7
-rw-r--r--drivers/dma/fsldma.c270
-rw-r--r--drivers/dma/fsldma.h1
-rw-r--r--drivers/dma/ioat_dma.c8
-rw-r--r--drivers/edac/cell_edac.c2
-rw-r--r--drivers/firmware/iscsi_ibft.c1
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpiolib.c6
-rw-r--r--drivers/gpio/twl4030-gpio.c521
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/drm_drawable.c15
-rw-r--r--drivers/gpu/drm/drm_ioc32.c34
-rw-r--r--drivers/gpu/drm/drm_irq.c5
-rw-r--r--drivers/gpu/drm/drm_lock.c2
-rw-r--r--drivers/gpu/drm/drm_proc.c4
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h10
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c62
-rw-r--r--drivers/gpu/drm/i915/i915_gem_proc.c15
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c277
-rw-r--r--drivers/hid/Kconfig2
-rw-r--r--drivers/hid/hid-apple.c63
-rw-r--r--drivers/hid/hid-core.c43
-rw-r--r--drivers/hid/hid-gyration.c4
-rw-r--r--drivers/hid/hid-ids.h5
-rw-r--r--drivers/hid/hid-lg.c5
-rw-r--r--drivers/hid/hid-sony.c44
-rw-r--r--drivers/hid/hidraw.c3
-rw-r--r--drivers/hid/usbhid/hid-core.c3
-rw-r--r--drivers/hid/usbhid/hiddev.c3
-rw-r--r--drivers/hwmon/abituguru3.c30
-rw-r--r--drivers/hwmon/adt7473.c29
-rw-r--r--drivers/hwmon/applesmc.c109
-rw-r--r--drivers/hwmon/hwmon-vid.c1
-rw-r--r--drivers/hwmon/lm90.c52
-rw-r--r--drivers/hwmon/pc87360.c248
-rw-r--r--drivers/hwmon/w83781d.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c21
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-amd756.c5
-rw-r--r--drivers/i2c/busses/i2c-cpm.c1
-rw-r--r--drivers/i2c/busses/i2c-elektor.c3
-rw-r--r--drivers/i2c/busses/i2c-hydra.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c3
-rw-r--r--drivers/i2c/busses/i2c-viapro.c5
-rw-r--r--drivers/i2c/chips/Kconfig2
-rw-r--r--drivers/i2c/chips/Makefile3
-rw-r--r--drivers/i2c/chips/at24.c1
-rw-r--r--drivers/i2c/chips/ds1682.c1
-rw-r--r--drivers/i2c/chips/menelaus.c34
-rw-r--r--drivers/i2c/i2c-core.c3
-rw-r--r--drivers/ide/Kconfig98
-rw-r--r--drivers/ide/Makefile103
-rw-r--r--drivers/ide/aec62xx.c (renamed from drivers/ide/pci/aec62xx.c)0
-rw-r--r--drivers/ide/ali14xx.c (renamed from drivers/ide/legacy/ali14xx.c)0
-rw-r--r--drivers/ide/alim15x3.c (renamed from drivers/ide/pci/alim15x3.c)0
-rw-r--r--drivers/ide/amd74xx.c (renamed from drivers/ide/pci/amd74xx.c)0
-rw-r--r--drivers/ide/arm/Makefile10
-rw-r--r--drivers/ide/atiixp.c (renamed from drivers/ide/pci/atiixp.c)0
-rw-r--r--drivers/ide/au1xxx-ide.c (renamed from drivers/ide/mips/au1xxx-ide.c)0
-rw-r--r--drivers/ide/buddha.c (renamed from drivers/ide/legacy/buddha.c)0
-rw-r--r--drivers/ide/cmd640.c (renamed from drivers/ide/pci/cmd640.c)0
-rw-r--r--drivers/ide/cmd64x.c (renamed from drivers/ide/pci/cmd64x.c)0
-rw-r--r--drivers/ide/cs5520.c (renamed from drivers/ide/pci/cs5520.c)0
-rw-r--r--drivers/ide/cs5530.c (renamed from drivers/ide/pci/cs5530.c)0
-rw-r--r--drivers/ide/cs5535.c (renamed from drivers/ide/pci/cs5535.c)0
-rw-r--r--drivers/ide/cy82c693.c (renamed from drivers/ide/pci/cy82c693.c)0
-rw-r--r--drivers/ide/delkin_cb.c (renamed from drivers/ide/pci/delkin_cb.c)63
-rw-r--r--drivers/ide/dtc2278.c (renamed from drivers/ide/legacy/dtc2278.c)0
-rw-r--r--drivers/ide/falconide.c (renamed from drivers/ide/legacy/falconide.c)0
-rw-r--r--drivers/ide/gayle.c (renamed from drivers/ide/legacy/gayle.c)0
-rw-r--r--drivers/ide/h8300/Makefile2
-rw-r--r--drivers/ide/hpt366.c (renamed from drivers/ide/pci/hpt366.c)35
-rw-r--r--drivers/ide/ht6560b.c (renamed from drivers/ide/legacy/ht6560b.c)0
-rw-r--r--drivers/ide/icside.c (renamed from drivers/ide/arm/icside.c)4
-rw-r--r--drivers/ide/ide-4drives.c (renamed from drivers/ide/legacy/ide-4drives.c)0
-rw-r--r--drivers/ide/ide-atapi.c2
-rw-r--r--drivers/ide/ide-cd.c84
-rw-r--r--drivers/ide/ide-cd_ioctl.c8
-rw-r--r--drivers/ide/ide-cs.c (renamed from drivers/ide/legacy/ide-cs.c)0
-rw-r--r--drivers/ide/ide-disk.c390
-rw-r--r--drivers/ide/ide-disk.h21
-rw-r--r--drivers/ide/ide-disk_ioctl.c7
-rw-r--r--drivers/ide/ide-disk_proc.c2
-rw-r--r--drivers/ide/ide-dma-sff.c2
-rw-r--r--drivers/ide/ide-floppy.c357
-rw-r--r--drivers/ide/ide-floppy.h41
-rw-r--r--drivers/ide/ide-floppy_ioctl.c36
-rw-r--r--drivers/ide/ide-floppy_proc.c2
-rw-r--r--drivers/ide/ide-gd.c396
-rw-r--r--drivers/ide/ide-gd.h44
-rw-r--r--drivers/ide/ide-h8300.c (renamed from drivers/ide/h8300/ide-h8300.c)0
-rw-r--r--drivers/ide/ide-ioctls.c3
-rw-r--r--drivers/ide/ide-iops.c2
-rw-r--r--drivers/ide/ide-pci-generic.c (renamed from drivers/ide/pci/generic.c)0
-rw-r--r--drivers/ide/ide-probe.c1
-rw-r--r--drivers/ide/ide-proc.c6
-rw-r--r--drivers/ide/ide-tape.c33
-rw-r--r--drivers/ide/ide_arm.c (renamed from drivers/ide/arm/ide_arm.c)0
-rw-r--r--drivers/ide/ide_platform.c (renamed from drivers/ide/legacy/ide_platform.c)0
-rw-r--r--drivers/ide/it8213.c (renamed from drivers/ide/pci/it8213.c)0
-rw-r--r--drivers/ide/it821x.c (renamed from drivers/ide/pci/it821x.c)0
-rw-r--r--drivers/ide/jmicron.c (renamed from drivers/ide/pci/jmicron.c)0
-rw-r--r--drivers/ide/legacy/Makefile25
-rw-r--r--drivers/ide/macide.c (renamed from drivers/ide/legacy/macide.c)0
-rw-r--r--drivers/ide/mips/Makefile3
-rw-r--r--drivers/ide/ns87415.c (renamed from drivers/ide/pci/ns87415.c)0
-rw-r--r--drivers/ide/opti621.c (renamed from drivers/ide/pci/opti621.c)0
-rw-r--r--drivers/ide/palm_bk3710.c (renamed from drivers/ide/arm/palm_bk3710.c)0
-rw-r--r--drivers/ide/pci/Makefile44
-rw-r--r--drivers/ide/pci/hpt34x.c193
-rw-r--r--drivers/ide/pdc202xx_new.c (renamed from drivers/ide/pci/pdc202xx_new.c)0
-rw-r--r--drivers/ide/pdc202xx_old.c (renamed from drivers/ide/pci/pdc202xx_old.c)0
-rw-r--r--drivers/ide/piix.c (renamed from drivers/ide/pci/piix.c)0
-rw-r--r--drivers/ide/pmac.c (renamed from drivers/ide/ppc/pmac.c)0
-rw-r--r--drivers/ide/ppc/Makefile2
-rw-r--r--drivers/ide/q40ide.c (renamed from drivers/ide/legacy/q40ide.c)0
-rw-r--r--drivers/ide/qd65xx.c (renamed from drivers/ide/legacy/qd65xx.c)0
-rw-r--r--drivers/ide/qd65xx.h (renamed from drivers/ide/legacy/qd65xx.h)0
-rw-r--r--drivers/ide/rapide.c (renamed from drivers/ide/arm/rapide.c)4
-rw-r--r--drivers/ide/rz1000.c (renamed from drivers/ide/pci/rz1000.c)0
-rw-r--r--drivers/ide/sc1200.c (renamed from drivers/ide/pci/sc1200.c)0
-rw-r--r--drivers/ide/scc_pata.c (renamed from drivers/ide/pci/scc_pata.c)14
-rw-r--r--drivers/ide/serverworks.c (renamed from drivers/ide/pci/serverworks.c)0
-rw-r--r--drivers/ide/sgiioc4.c (renamed from drivers/ide/pci/sgiioc4.c)73
-rw-r--r--drivers/ide/siimage.c (renamed from drivers/ide/pci/siimage.c)2
-rw-r--r--drivers/ide/sis5513.c (renamed from drivers/ide/pci/sis5513.c)0
-rw-r--r--drivers/ide/sl82c105.c (renamed from drivers/ide/pci/sl82c105.c)0
-rw-r--r--drivers/ide/slc90e66.c (renamed from drivers/ide/pci/slc90e66.c)0
-rw-r--r--drivers/ide/tc86c001.c (renamed from drivers/ide/pci/tc86c001.c)0
-rw-r--r--drivers/ide/triflex.c (renamed from drivers/ide/pci/triflex.c)0
-rw-r--r--drivers/ide/trm290.c (renamed from drivers/ide/pci/trm290.c)0
-rw-r--r--drivers/ide/tx4938ide.c310
-rw-r--r--drivers/ide/tx4939ide.c754
-rw-r--r--drivers/ide/umc8672.c (renamed from drivers/ide/legacy/umc8672.c)0
-rw-r--r--drivers/ide/via82cxxx.c (renamed from drivers/ide/pci/via82cxxx.c)0
-rw-r--r--drivers/idle/Kconfig17
-rw-r--r--drivers/idle/Makefile2
-rw-r--r--drivers/idle/i7300_idle.c609
-rw-r--r--drivers/infiniband/core/cm.c2
-rw-r--r--drivers/infiniband/core/mad.c14
-rw-r--r--drivers/infiniband/core/ucma.c4
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c83
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c10
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c6
-rw-r--r--drivers/infiniband/hw/mlx4/main.c11
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c21
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c9
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c67
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c4
-rw-r--r--drivers/input/touchscreen/Kconfig8
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c2
-rw-r--r--drivers/leds/Kconfig27
-rw-r--r--drivers/leds/Makefile4
-rw-r--r--drivers/leds/led-class.c12
-rw-r--r--drivers/leds/leds-ams-delta.c20
-rw-r--r--drivers/leds/leds-cm-x270.c124
-rw-r--r--drivers/leds/leds-da903x.c175
-rw-r--r--drivers/leds/leds-hp-disk.c156
-rw-r--r--drivers/leds/leds-hp6xx.c2
-rw-r--r--drivers/leds/leds-pca955x.c2
-rw-r--r--drivers/leds/leds-wrap.c5
-rw-r--r--drivers/leds/ledtrig-backlight.c110
-rw-r--r--drivers/leds/ledtrig-timer.c8
-rw-r--r--drivers/md/Makefile2
-rw-r--r--drivers/md/dm-crypt.c56
-rw-r--r--drivers/md/dm-delay.c3
-rw-r--r--drivers/md/dm-exception-store.c108
-rw-r--r--drivers/md/dm-io.c2
-rw-r--r--drivers/md/dm-ioctl.c4
-rw-r--r--drivers/md/dm-kcopyd.c14
-rw-r--r--drivers/md/dm-linear.c15
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-mpath.c17
-rw-r--r--drivers/md/dm-path-selector.c3
-rw-r--r--drivers/md/dm-raid1.c791
-rw-r--r--drivers/md/dm-region-hash.c704
-rw-r--r--drivers/md/dm-round-robin.c3
-rw-r--r--drivers/md/dm-snap.c11
-rw-r--r--drivers/md/dm-snap.h5
-rw-r--r--drivers/md/dm-stripe.c6
-rw-r--r--drivers/md/dm-table.c37
-rw-r--r--drivers/md/dm-zero.c2
-rw-r--r--drivers/md/dm.c76
-rw-r--r--drivers/md/dm.h9
-rw-r--r--drivers/md/md.c20
-rw-r--r--drivers/media/common/saa7146_fops.c4
-rw-r--r--drivers/media/common/saa7146_video.c12
-rw-r--r--drivers/media/dvb/frontends/s5h1411.c84
-rw-r--r--drivers/media/dvb/frontends/s5h1411.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110.c2
-rw-r--r--drivers/media/radio/dsbr100.c62
-rw-r--r--drivers/media/radio/radio-mr800.c5
-rw-r--r--drivers/media/video/arv.c2
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c6
-rw-r--r--drivers/media/video/c-qcam.c2
-rw-r--r--drivers/media/video/cafe_ccic.c4
-rw-r--r--drivers/media/video/cpia.c6
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c2
-rw-r--r--drivers/media/video/cx18/cx18-driver.c11
-rw-r--r--drivers/media/video/cx18/cx18-driver.h1
-rw-r--r--drivers/media/video/cx18/cx18-io.h4
-rw-r--r--drivers/media/video/cx18/cx18-streams.c36
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c2
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c2
-rw-r--r--drivers/media/video/cx88/cx88-cards.c4
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c11
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c2
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c15
-rw-r--r--drivers/media/video/cx88/cx88-video.c6
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c2
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c24
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c12
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c13
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.h3
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c4
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c17
-rw-r--r--drivers/media/video/pwc/pwc-if.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c6
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c2
-rw-r--r--drivers/media/video/se401.c2
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c24
-rw-r--r--drivers/media/video/stk-webcam.c4
-rw-r--r--drivers/media/video/stv680.c3
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c2
-rw-r--r--drivers/media/video/usbvideo/vicam.c3
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c2
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c12
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c12
-rw-r--r--drivers/media/video/v4l1-compat.c221
-rw-r--r--drivers/media/video/v4l2-int-device.c5
-rw-r--r--drivers/media/video/v4l2-ioctl.c19
-rw-r--r--drivers/media/video/videobuf-dvb.c52
-rw-r--r--drivers/media/video/vivi.c6
-rw-r--r--drivers/media/video/w9968cf.c16
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c24
-rw-r--r--drivers/media/video/zr364xx.c2
-rw-r--r--drivers/memstick/core/mspro_block.c10
-rw-r--r--drivers/message/fusion/mptscsih.c3
-rw-r--r--drivers/message/i2o/i2o_block.c13
-rw-r--r--drivers/mfd/Kconfig16
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/asic3.c4
-rw-r--r--drivers/mfd/da903x.c563
-rw-r--r--drivers/mfd/htc-egpio.c4
-rw-r--r--drivers/mfd/mfd-core.c15
-rw-r--r--drivers/mfd/sm501.c31
-rw-r--r--drivers/mfd/t7l66xb.c40
-rw-r--r--drivers/mfd/tc6387xb.c47
-rw-r--r--drivers/mfd/tc6393xb.c296
-rw-r--r--drivers/mfd/twl4030-core.c806
-rw-r--r--drivers/mfd/twl4030-irq.c743
-rw-r--r--drivers/mfd/wm8350-core.c7
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/acer-wmi.c225
-rw-r--r--drivers/misc/asus-laptop.c17
-rw-r--r--drivers/misc/eeepc-laptop.c232
-rw-r--r--drivers/misc/fujitsu-laptop.c135
-rw-r--r--drivers/misc/hp-wmi.c1
-rw-r--r--drivers/misc/intel_menlow.c31
-rw-r--r--drivers/misc/panasonic-laptop.c767
-rw-r--r--drivers/misc/sony-laptop.c2
-rw-r--r--drivers/misc/thinkpad_acpi.c65
-rw-r--r--drivers/mmc/card/block.c13
-rw-r--r--drivers/mmc/card/queue.c1
-rw-r--r--drivers/mmc/host/s3cmci.c210
-rw-r--r--drivers/mmc/host/s3cmci.h6
-rw-r--r--drivers/mtd/Kconfig5
-rw-r--r--drivers/mtd/chips/Kconfig4
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c71
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c52
-rw-r--r--drivers/mtd/chips/cfi_probe.c58
-rw-r--r--drivers/mtd/chips/cfi_util.c66
-rw-r--r--drivers/mtd/chips/gen_probe.c2
-rw-r--r--drivers/mtd/cmdlinepart.c1
-rw-r--r--drivers/mtd/devices/Kconfig21
-rw-r--r--drivers/mtd/devices/block2mtd.c4
-rw-r--r--drivers/mtd/devices/m25p80.c138
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c214
-rw-r--r--drivers/mtd/inftlcore.c5
-rw-r--r--drivers/mtd/maps/Kconfig33
-rw-r--r--drivers/mtd/maps/Makefile4
-rw-r--r--drivers/mtd/maps/ebony.c163
-rw-r--r--drivers/mtd/maps/ocotea.c154
-rw-r--r--drivers/mtd/maps/omap-toto-flash.c133
-rw-r--r--drivers/mtd/maps/pci.c18
-rw-r--r--drivers/mtd/maps/physmap_of.c3
-rw-r--r--drivers/mtd/maps/walnut.c122
-rw-r--r--drivers/mtd/mtd_blkdevs.c24
-rw-r--r--drivers/mtd/mtdchar.c14
-rw-r--r--drivers/mtd/mtdconcat.c4
-rw-r--r--drivers/mtd/mtdoops.c42
-rw-r--r--drivers/mtd/mtdpart.c4
-rw-r--r--drivers/mtd/nand/Kconfig42
-rw-r--r--drivers/mtd/nand/Makefile4
-rw-r--r--drivers/mtd/nand/atmel_nand.c58
-rw-r--r--drivers/mtd/nand/cs553x_nand.c2
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c3
-rw-r--r--drivers/mtd/nand/fsl_upm.c68
-rw-r--r--drivers/mtd/nand/gpio.c375
-rw-r--r--drivers/mtd/nand/mxc_nand.c1077
-rw-r--r--drivers/mtd/nand/nand_base.c16
-rw-r--r--drivers/mtd/nand/nand_ecc.c554
-rw-r--r--drivers/mtd/nand/nandsim.c1
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c147
-rw-r--r--drivers/mtd/nand/sh_flctl.c878
-rw-r--r--drivers/mtd/nand/toto.c206
-rw-r--r--drivers/mtd/ofpart.c1
-rw-r--r--drivers/mtd/onenand/Kconfig8
-rw-r--r--drivers/mtd/onenand/Makefile1
-rw-r--r--drivers/mtd/onenand/omap2.c802
-rw-r--r--drivers/mtd/onenand/onenand_base.c2
-rw-r--r--drivers/mtd/ssfdc.c3
-rw-r--r--drivers/mtd/ubi/cdev.c6
-rw-r--r--drivers/mtd/ubi/scan.c2
-rw-r--r--drivers/mtd/ubi/vtbl.c4
-rw-r--r--drivers/net/3c59x.c4
-rw-r--r--drivers/net/8139cp.c5
-rw-r--r--drivers/net/8139too.c5
-rw-r--r--drivers/net/Kconfig24
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/ax88796.c6
-rw-r--r--drivers/net/bonding/bond_main.c16
-rw-r--r--drivers/net/cxgb3/l2t.c1
-rw-r--r--drivers/net/dm9000.c9
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c25
-rw-r--r--drivers/net/ehea/ehea_qmr.c131
-rw-r--r--drivers/net/ehea/ehea_qmr.h2
-rw-r--r--drivers/net/fec_mpc52xx.c18
-rw-r--r--drivers/net/fec_mpc52xx_phy.c55
-rw-r--r--drivers/net/gianfar.c24
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c4
-rw-r--r--drivers/net/hamradio/scc.c6
-rw-r--r--drivers/net/ibm_newemac/core.c10
-rw-r--r--drivers/net/ibm_newemac/mal.c15
-rw-r--r--drivers/net/igb/igb_main.c60
-rw-r--r--drivers/net/mlx4/Makefile7
-rw-r--r--drivers/net/mlx4/alloc.c97
-rw-r--r--drivers/net/mlx4/cq.c2
-rw-r--r--drivers/net/mlx4/en_cq.c146
-rw-r--r--drivers/net/mlx4/en_main.c254
-rw-r--r--drivers/net/mlx4/en_netdev.c1088
-rw-r--r--drivers/net/mlx4/en_params.c480
-rw-r--r--drivers/net/mlx4/en_port.c261
-rw-r--r--drivers/net/mlx4/en_port.h570
-rw-r--r--drivers/net/mlx4/en_resources.c96
-rw-r--r--drivers/net/mlx4/en_rx.c1080
-rw-r--r--drivers/net/mlx4/en_tx.c820
-rw-r--r--drivers/net/mlx4/eq.c2
-rw-r--r--drivers/net/mlx4/fw.c20
-rw-r--r--drivers/net/mlx4/fw.h7
-rw-r--r--drivers/net/mlx4/main.c287
-rw-r--r--drivers/net/mlx4/mcg.c4
-rw-r--r--drivers/net/mlx4/mlx4.h45
-rw-r--r--drivers/net/mlx4/mlx4_en.h561
-rw-r--r--drivers/net/mlx4/mr.c2
-rw-r--r--drivers/net/mlx4/pd.c4
-rw-r--r--drivers/net/mlx4/port.c282
-rw-r--r--drivers/net/mlx4/qp.c81
-rw-r--r--drivers/net/mlx4/srq.c2
-rw-r--r--drivers/net/myri10ge/myri10ge.c6
-rw-r--r--drivers/net/qlge/qlge.h5
-rw-r--r--drivers/net/qlge/qlge_main.c89
-rw-r--r--drivers/net/r8169.c74
-rw-r--r--drivers/net/sh_eth.c5
-rw-r--r--drivers/net/sis190.c1
-rw-r--r--drivers/net/smc911x.c38
-rw-r--r--drivers/net/smc911x.h6
-rw-r--r--drivers/net/usb/pegasus.c4
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/net/wireless/ath5k/base.c27
-rw-r--r--drivers/net/wireless/ath5k/base.h3
-rw-r--r--drivers/net/wireless/orinoco.c42
-rw-r--r--drivers/net/wireless/p54/p54common.c28
-rw-r--r--drivers/net/xtsonic.c319
-rw-r--r--drivers/of/of_i2c.c2
-rw-r--r--drivers/of/of_spi.c2
-rw-r--r--drivers/oprofile/buffer_sync.c41
-rw-r--r--drivers/oprofile/buffer_sync.h4
-rw-r--r--drivers/oprofile/cpu_buffer.c106
-rw-r--r--drivers/oprofile/cpu_buffer.h12
-rw-r--r--drivers/oprofile/event_buffer.c34
-rw-r--r--drivers/oprofile/event_buffer.h17
-rw-r--r--drivers/oprofile/oprof.c26
-rw-r--r--drivers/oprofile/oprof.h12
-rw-r--r--drivers/oprofile/oprofile_files.c36
-rw-r--r--drivers/oprofile/oprofile_stats.c24
-rw-r--r--drivers/oprofile/oprofile_stats.h10
-rw-r--r--drivers/oprofile/oprofilefs.c78
-rw-r--r--drivers/oprofile/timer_int.c4
-rw-r--r--drivers/parisc/ccio-dma.c43
-rw-r--r--drivers/parisc/dino.c6
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/eisa_eeprom.c2
-rw-r--r--drivers/parisc/gsc.c12
-rw-r--r--drivers/parisc/iosapic.c4
-rw-r--r--drivers/parisc/superio.c4
-rw-r--r--drivers/parport/parport_pc.c20
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/pci/bus.c7
-rw-r--r--drivers/pci/dmar.c176
-rw-r--r--drivers/pci/hotplug/acpiphp.h9
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c32
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c20
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c4
-rw-r--r--drivers/pci/hotplug/cpci_hotplug.h6
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c75
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c4
-rw-r--r--drivers/pci/hotplug/cpqphp.h13
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c45
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c2
-rw-r--r--drivers/pci/hotplug/fakephp.c26
-rw-r--r--drivers/pci/hotplug/ibmphp.h5
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c111
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c78
-rw-r--r--drivers/pci/hotplug/pciehp.h26
-rw-r--r--drivers/pci/hotplug/pciehp_core.c107
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c144
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c253
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c35
-rw-r--r--drivers/pci/hotplug/rpaphp.h4
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c4
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c10
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c22
-rw-r--r--drivers/pci/hotplug/shpchp.h31
-rw-r--r--drivers/pci/hotplug/shpchp_core.c80
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c158
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c113
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c36
-rw-r--r--drivers/pci/htirq.c3
-rw-r--r--drivers/pci/intel-iommu.c254
-rw-r--r--drivers/pci/intr_remapping.c139
-rw-r--r--drivers/pci/irq.c60
-rw-r--r--drivers/pci/msi.c31
-rw-r--r--drivers/pci/pci-acpi.c88
-rw-r--r--drivers/pci/pci-driver.c21
-rw-r--r--drivers/pci/pci-sysfs.c241
-rw-r--r--drivers/pci/pci.c202
-rw-r--r--drivers/pci/pci.h28
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c6
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c47
-rw-r--r--drivers/pci/pcie/aspm.c6
-rw-r--r--drivers/pci/pcie/portdrv.h1
-rw-r--r--drivers/pci/pcie/portdrv_core.c23
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pci/probe.c150
-rw-r--r--drivers/pci/quirks.c187
-rw-r--r--drivers/pci/remove.c11
-rw-r--r--drivers/pci/rom.c6
-rw-r--r--drivers/pci/search.c9
-rw-r--r--drivers/pci/setup-bus.c17
-rw-r--r--drivers/pci/setup-res.c42
-rw-r--r--drivers/pci/slot.c170
-rw-r--r--drivers/pcmcia/Makefile2
-rw-r--r--drivers/pcmcia/at91_cf.c2
-rw-r--r--drivers/pcmcia/hd64465_ss.c12
-rw-r--r--drivers/pcmcia/vrc4171_card.c2
-rw-r--r--drivers/pnp/Kconfig20
-rw-r--r--drivers/pnp/Makefile4
-rw-r--r--drivers/pnp/base.h10
-rw-r--r--drivers/pnp/core.c29
-rw-r--r--drivers/pnp/driver.c4
-rw-r--r--drivers/pnp/isapnp/Makefile4
-rw-r--r--drivers/pnp/isapnp/core.c12
-rw-r--r--drivers/pnp/manager.c34
-rw-r--r--drivers/pnp/pnpacpi/Makefile4
-rw-r--r--drivers/pnp/pnpacpi/core.c16
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c43
-rw-r--r--drivers/pnp/pnpbios/Makefile4
-rw-r--r--drivers/pnp/pnpbios/core.c4
-rw-r--r--drivers/pnp/pnpbios/rsparser.c18
-rw-r--r--drivers/pnp/quirks.c5
-rw-r--r--drivers/pnp/resource.c12
-rw-r--r--drivers/pnp/support.c14
-rw-r--r--drivers/power/Kconfig8
-rw-r--r--drivers/power/Makefile3
-rw-r--r--drivers/power/bq27x00_battery.c381
-rw-r--r--drivers/power/pda_power.c11
-rw-r--r--drivers/power/power_supply_core.c25
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/ps3/ps3av.c16
-rw-r--r--drivers/ps3/ps3av_cmd.c19
-rw-r--r--drivers/rtc/Kconfig22
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c42
-rw-r--r--drivers/rtc/rtc-bq4802.c30
-rw-r--r--drivers/rtc/rtc-cmos.c91
-rw-r--r--drivers/rtc/rtc-ds1216.c26
-rw-r--r--drivers/rtc/rtc-ds1302.c30
-rw-r--r--drivers/rtc/rtc-ds1305.c39
-rw-r--r--drivers/rtc/rtc-ds1307.c41
-rw-r--r--drivers/rtc/rtc-ds1511.c43
-rw-r--r--drivers/rtc/rtc-ds1553.c38
-rw-r--r--drivers/rtc/rtc-ds1742.c30
-rw-r--r--drivers/rtc/rtc-fm3130.c56
-rw-r--r--drivers/rtc/rtc-isl1208.c42
-rw-r--r--drivers/rtc/rtc-m41t80.c44
-rw-r--r--drivers/rtc/rtc-m41t94.c28
-rw-r--r--drivers/rtc/rtc-m48t59.c49
-rw-r--r--drivers/rtc/rtc-m48t86.c28
-rw-r--r--drivers/rtc/rtc-max6900.c32
-rw-r--r--drivers/rtc/rtc-max6902.c32
-rw-r--r--drivers/rtc/rtc-omap.c24
-rw-r--r--drivers/rtc/rtc-parisc.c111
-rw-r--r--drivers/rtc/rtc-pcf8563.c24
-rw-r--r--drivers/rtc/rtc-pcf8583.c20
-rw-r--r--drivers/rtc/rtc-r9701.c24
-rw-r--r--drivers/rtc/rtc-rs5c313.c28
-rw-r--r--drivers/rtc/rtc-rs5c348.c30
-rw-r--r--drivers/rtc/rtc-rs5c372.c42
-rw-r--r--drivers/rtc/rtc-s35390a.c34
-rw-r--r--drivers/rtc/rtc-s3c.c42
-rw-r--r--drivers/rtc/rtc-sh.c61
-rw-r--r--drivers/rtc/rtc-stk17ta8.c39
-rw-r--r--drivers/rtc/rtc-twl4030.c564
-rw-r--r--drivers/rtc/rtc-v3020.c28
-rw-r--r--drivers/rtc/rtc-vr41xx.c4
-rw-r--r--drivers/rtc/rtc-x1205.c30
-rw-r--r--drivers/s390/block/dasd.c11
-rw-r--r--drivers/s390/block/dasd_genhd.c4
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c15
-rw-r--r--drivers/s390/block/dcssblk.c17
-rw-r--r--drivers/s390/char/tape_block.c25
-rw-r--r--drivers/s390/crypto/ap_bus.c6
-rw-r--r--drivers/scsi/3w-9xxx.c3
-rw-r--r--drivers/scsi/3w-xxxx.c7
-rw-r--r--drivers/scsi/aha152x.c2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.reg185
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c15
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c12
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg.h_shipped567
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped1723
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg124
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c7
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped875
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped1165
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_gram.y10
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_scan.l1
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c3
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h3
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c3
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c3
-rw-r--r--drivers/scsi/ide-scsi.c48
-rw-r--r--drivers/scsi/ipr.c17
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c5
-rw-r--r--drivers/scsi/scsi_ioctl.c6
-rw-r--r--drivers/scsi/scsi_lib.c83
-rw-r--r--drivers/scsi/scsi_netlink.c9
-rw-r--r--drivers/scsi/sd.c56
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/sr.c40
-rw-r--r--drivers/scsi/sr_vendor.c12
-rw-r--r--drivers/scsi/st.c7
-rw-r--r--drivers/scsi/sun3x_esp.c4
-rw-r--r--drivers/serial/68328serial.c11
-rw-r--r--drivers/serial/8250.c69
-rw-r--r--drivers/serial/8250_gsc.c2
-rw-r--r--drivers/serial/8250_pci.c231
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/amba-pl010.c2
-rw-r--r--drivers/serial/amba-pl011.c2
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c2
-rw-r--r--drivers/serial/m32r_sio.c4
-rw-r--r--drivers/serial/serial_core.c2
-rw-r--r--drivers/serial/serial_lh7a40x.c2
-rw-r--r--drivers/serial/serial_txx9.c2
-rw-r--r--drivers/serial/sh-sci.c92
-rw-r--r--drivers/serial/sh-sci.h23
-rw-r--r--drivers/serial/sn_console.c2
-rw-r--r--drivers/serial/ucc_uart.c2
-rw-r--r--drivers/sh/Makefile2
-rw-r--r--drivers/sh/intc.c713
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/at76_usb/at76_usb.c4
-rw-r--r--drivers/staging/echo/bit_operations.h205
-rw-r--r--drivers/staging/echo/echo.c835
-rw-r--r--drivers/staging/echo/echo.h58
-rw-r--r--drivers/staging/echo/fir.h376
-rw-r--r--drivers/staging/echo/mmx.h29
-rw-r--r--drivers/staging/echo/oslec.h86
-rw-r--r--drivers/staging/et131x/et1310_phy.c2
-rw-r--r--drivers/staging/et131x/et131x_debug.c1
-rw-r--r--drivers/staging/et131x/et131x_initpci.c1
-rw-r--r--drivers/staging/go7007/Kconfig2
-rw-r--r--drivers/staging/go7007/go7007-driver.c1
-rw-r--r--drivers/staging/go7007/go7007-fw.c1
-rw-r--r--drivers/staging/go7007/go7007-i2c.c1
-rw-r--r--drivers/staging/go7007/go7007-usb.c1
-rw-r--r--drivers/staging/go7007/snd-go7007.c1
-rw-r--r--drivers/staging/go7007/wis-ov7640.c1
-rw-r--r--drivers/staging/go7007/wis-saa7113.c1
-rw-r--r--drivers/staging/go7007/wis-saa7115.c1
-rw-r--r--drivers/staging/go7007/wis-sony-tuner.c1
-rw-r--r--drivers/staging/go7007/wis-tw2804.c1
-rw-r--r--drivers/staging/go7007/wis-tw9903.c1
-rw-r--r--drivers/staging/go7007/wis-uda1342.c1
-rw-r--r--drivers/staging/me4000/me4000.c908
-rw-r--r--drivers/staging/me4000/me4000.h194
-rw-r--r--drivers/staging/poch/Kconfig6
-rw-r--r--drivers/staging/poch/Makefile1
-rw-r--r--drivers/staging/poch/README7
-rw-r--r--drivers/staging/poch/poch.c1425
-rw-r--r--drivers/staging/poch/poch.h29
-rw-r--r--drivers/staging/slicoss/slicoss.c18
-rw-r--r--drivers/staging/sxg/Kconfig1
-rw-r--r--drivers/staging/sxg/README1
-rw-r--r--drivers/staging/sxg/sxg.c1379
-rw-r--r--drivers/staging/sxg/sxg_os.h41
-rw-r--r--drivers/staging/sxg/sxgdbg.h2
-rw-r--r--drivers/staging/sxg/sxghif.h410
-rw-r--r--drivers/staging/sxg/sxghw.h404
-rw-r--r--drivers/staging/sxg/sxgphycode.h12
-rw-r--r--drivers/staging/usbip/usbip_common.c2
-rw-r--r--drivers/staging/usbip/vhci_rx.c2
-rw-r--r--drivers/staging/winbond/Kconfig2
-rw-r--r--drivers/staging/winbond/README1
-rw-r--r--drivers/staging/winbond/bss_f.h6
-rw-r--r--drivers/staging/winbond/ds_tkip.h6
-rw-r--r--drivers/staging/winbond/linux/common.h17
-rw-r--r--drivers/staging/winbond/linux/wb35reg.c63
-rw-r--r--drivers/staging/winbond/linux/wb35reg_f.h12
-rw-r--r--drivers/staging/winbond/linux/wb35reg_s.h4
-rw-r--r--drivers/staging/winbond/linux/wb35rx.c175
-rw-r--r--drivers/staging/winbond/linux/wb35rx_s.h2
-rw-r--r--drivers/staging/winbond/linux/wb35tx.c138
-rw-r--r--drivers/staging/winbond/linux/wb35tx_f.h2
-rw-r--r--drivers/staging/winbond/linux/wbusb.c259
-rw-r--r--drivers/staging/winbond/mds.c30
-rw-r--r--drivers/staging/winbond/mds_f.h6
-rw-r--r--drivers/staging/winbond/mds_s.h8
-rw-r--r--drivers/staging/winbond/mlme_s.h4
-rw-r--r--drivers/staging/winbond/mlmetxrx.c4
-rw-r--r--drivers/staging/winbond/mlmetxrx_f.h4
-rw-r--r--drivers/staging/winbond/reg.c24
-rw-r--r--drivers/staging/winbond/sme_api.c1
-rw-r--r--drivers/staging/winbond/sme_api.h2
-rw-r--r--drivers/staging/winbond/wbhal.c32
-rw-r--r--drivers/staging/winbond/wbhal_f.h28
-rw-r--r--drivers/staging/winbond/wbhal_s.h4
-rw-r--r--drivers/staging/winbond/wblinux.c208
-rw-r--r--drivers/staging/winbond/wblinux_s.h4
-rw-r--r--drivers/staging/wlan-ng/Kconfig2
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h2
-rw-r--r--drivers/staging/wlan-ng/p80211wep.c1
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c2
-rw-r--r--drivers/staging/wlan-ng/wlan_compat.h8
-rw-r--r--drivers/telephony/phonedev.c2
-rw-r--r--drivers/uio/uio.c14
-rw-r--r--drivers/usb/Kconfig3
-rw-r--r--drivers/usb/atm/speedtch.c12
-rw-r--r--drivers/usb/class/cdc-acm.c3
-rw-r--r--drivers/usb/class/cdc-wdm.c2
-rw-r--r--drivers/usb/core/driver.c3
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/gadget/config.c2
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c2
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c7
-rw-r--r--drivers/usb/host/Kconfig1
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c21
-rw-r--r--drivers/usb/host/ohci-tmio.c376
-rw-r--r--drivers/usb/misc/usbtest.c3
-rw-r--r--drivers/usb/serial/option.c96
-rw-r--r--drivers/usb/storage/initializers.c3
-rw-r--r--drivers/usb/storage/unusual_devs.h291
-rw-r--r--drivers/video/backlight/Kconfig37
-rw-r--r--drivers/video/backlight/Makefile4
-rw-r--r--drivers/video/backlight/da903x.c201
-rw-r--r--drivers/video/backlight/hp680_bl.c2
-rw-r--r--drivers/video/backlight/kb3886_bl.c204
-rw-r--r--drivers/video/backlight/tosa_bl.c198
-rw-r--r--drivers/video/backlight/tosa_lcd.c280
-rw-r--r--drivers/video/fbmem.c174
-rw-r--r--drivers/video/imacfb.c0
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c14
-rw-r--r--drivers/w1/slaves/w1_ds2760.c1
-rw-r--r--drivers/watchdog/ib700wdt.c2
-rw-r--r--drivers/watchdog/w83697ug_wdt.c2
-rw-r--r--drivers/xen/cpu_hotplug.c2
-rw-r--r--drivers/xen/events.c18
845 files changed, 37014 insertions, 17408 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 43fa673c68a..fceb71a741c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
+obj-y += idle/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-$(CONFIG_NEW_LEDS) += leds/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index da49b006bcc..f4f63291750 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -42,7 +42,7 @@ if ACPI
config ACPI_SLEEP
bool
- depends on PM_SLEEP
+ depends on SUSPEND || HIBERNATION
default y
config ACPI_PROCFS
@@ -157,18 +157,11 @@ config ACPI_FAN
applications to perform basic fan control (on, off, status).
config ACPI_DOCK
- tristate "Dock"
+ bool "Dock"
depends on EXPERIMENTAL
help
- This driver adds support for ACPI controlled docking stations
-
-config ACPI_BAY
- tristate "Removable Drive Bay (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- depends on ACPI_DOCK
- help
- This driver adds support for ACPI controlled removable drive
- bays such as the IBM ultrabay or the Dell Module Bay.
+ This driver adds support for ACPI controlled docking stations and removable
+ drive bays such as the IBM ultrabay or the Dell Module Bay.
config ACPI_PROCESSOR
tristate "Processor"
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 52a4cd4b81d..d91c027ece8 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -45,14 +45,13 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_DOCK) += dock.o
-obj-$(CONFIG_ACPI_BAY) += bay.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
-obj-$(CONFIG_ACPI_POWER) += power.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
+obj-$(CONFIG_ACPI_POWER) += power.o
obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
obj-$(CONFIG_ACPI_DEBUG) += debug.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 831883b7d6c..d72a1b6c8a9 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -85,7 +85,7 @@ struct acpi_ac {
struct power_supply charger;
#endif
struct acpi_device * device;
- unsigned long state;
+ unsigned long long state;
};
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
@@ -269,7 +269,7 @@ static int acpi_ac_add(struct acpi_device *device)
ac->device = device;
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_AC_CLASS);
- acpi_driver_data(device) = ac;
+ device->driver_data = ac;
result = acpi_ac_get_state(ac);
if (result)
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 5f1127ad5a9..71d21c51c45 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -194,8 +194,7 @@ acpi_memory_get_device(acpi_handle handle,
static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
{
- unsigned long current_status;
-
+ unsigned long long current_status;
/* Get device present/absent information from the _STA */
if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA",
@@ -264,7 +263,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
acpi_status status;
struct acpi_object_list arg_list;
union acpi_object arg;
- unsigned long current_status;
+ unsigned long long current_status;
/* Issue the _EJ0 command */
@@ -403,7 +402,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
mem_device->device = device;
sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
- acpi_driver_data(device) = mem_device;
+ device->driver_data = mem_device;
/* Get the range from the _CRS */
result = acpi_memory_get_device_resources(mem_device);
@@ -454,8 +453,8 @@ static int acpi_memory_device_start (struct acpi_device *device)
/* call add_memory func */
result = acpi_memory_enable_device(mem_device);
if (result)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_memory_enable_device\n"));
+ printk(KERN_ERR PREFIX
+ "Error in acpi_memory_enable_device\n");
}
return result;
}
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index d3d0886d637..1e74988c7b2 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -42,7 +42,7 @@
#define ASUS_ACPI_VERSION "0.30"
-#define PROC_ASUS "asus" //the directory
+#define PROC_ASUS "asus" /* The directory */
#define PROC_MLED "mled"
#define PROC_WLED "wled"
#define PROC_TLED "tled"
@@ -66,10 +66,10 @@
/*
* Flags for hotk status
*/
-#define MLED_ON 0x01 //mail LED
-#define WLED_ON 0x02 //wireless LED
-#define TLED_ON 0x04 //touchpad LED
-#define BT_ON 0x08 //internal Bluetooth
+#define MLED_ON 0x01 /* Mail LED */
+#define WLED_ON 0x02 /* Wireless LED */
+#define TLED_ON 0x04 /* Touchpad LED */
+#define BT_ON 0x08 /* Internal Bluetooth */
MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
@@ -82,28 +82,28 @@ MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus");
module_param(asus_gid, uint, 0);
MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus");
-/* For each model, all features implemented,
+/* For each model, all features implemented,
* those marked with R are relative to HOTK, A for absolute */
struct model_data {
- char *name; //name of the laptop________________A
- char *mt_mled; //method to handle mled_____________R
- char *mled_status; //node to handle mled reading_______A
- char *mt_wled; //method to handle wled_____________R
- char *wled_status; //node to handle wled reading_______A
- char *mt_tled; //method to handle tled_____________R
- char *tled_status; //node to handle tled reading_______A
- char *mt_ledd; //method to handle LED display______R
- char *mt_bt_switch; //method to switch Bluetooth on/off_R
- char *bt_status; //no model currently supports this__?
- char *mt_lcd_switch; //method to turn LCD on/off_________A
- char *lcd_status; //node to read LCD panel state______A
- char *brightness_up; //method to set brightness up_______A
- char *brightness_down; //guess what ?______________________A
- char *brightness_set; //method to set absolute brightness_R
- char *brightness_get; //method to get absolute brightness_R
- char *brightness_status; //node to get brightness____________A
- char *display_set; //method to set video output________R
- char *display_get; //method to get video output________R
+ char *name; /* name of the laptop________________A */
+ char *mt_mled; /* method to handle mled_____________R */
+ char *mled_status; /* node to handle mled reading_______A */
+ char *mt_wled; /* method to handle wled_____________R */
+ char *wled_status; /* node to handle wled reading_______A */
+ char *mt_tled; /* method to handle tled_____________R */
+ char *tled_status; /* node to handle tled reading_______A */
+ char *mt_ledd; /* method to handle LED display______R */
+ char *mt_bt_switch; /* method to switch Bluetooth on/off_R */
+ char *bt_status; /* no model currently supports this__? */
+ char *mt_lcd_switch; /* method to turn LCD on/off_________A */
+ char *lcd_status; /* node to read LCD panel state______A */
+ char *brightness_up; /* method to set brightness up_______A */
+ char *brightness_down; /* method to set brightness down ____A */
+ char *brightness_set; /* method to set absolute brightness_R */
+ char *brightness_get; /* method to get absolute brightness_R */
+ char *brightness_status;/* node to get brightness____________A */
+ char *display_set; /* method to set video output________R */
+ char *display_get; /* method to get video output________R */
};
/*
@@ -111,41 +111,41 @@ struct model_data {
* about the hotk device
*/
struct asus_hotk {
- struct acpi_device *device; //the device we are in
- acpi_handle handle; //the handle of the hotk device
- char status; //status of the hotk, for LEDs, ...
- u32 ledd_status; //status of the LED display
- struct model_data *methods; //methods available on the laptop
- u8 brightness; //brightness level
+ struct acpi_device *device; /* the device we are in */
+ acpi_handle handle; /* the handle of the hotk device */
+ char status; /* status of the hotk, for LEDs */
+ u32 ledd_status; /* status of the LED display */
+ struct model_data *methods; /* methods available on the laptop */
+ u8 brightness; /* brightness level */
enum {
- A1x = 0, //A1340D, A1300F
- A2x, //A2500H
- A4G, //A4700G
- D1x, //D1
- L2D, //L2000D
- L3C, //L3800C
- L3D, //L3400D
- L3H, //L3H, L2000E, L5D
- L4R, //L4500R
- L5x, //L5800C
- L8L, //L8400L
- M1A, //M1300A
- M2E, //M2400E, L4400L
- M6N, //M6800N, W3400N
- M6R, //M6700R, A3000G
- P30, //Samsung P30
- S1x, //S1300A, but also L1400B and M2400A (L84F)
- S2x, //S200 (J1 reported), Victor MP-XP7210
- W1N, //W1000N
- W5A, //W5A
- W3V, //W3030V
- xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
- A4S, //Z81sp
- //(Centrino)
- F3Sa,
+ A1x = 0, /* A1340D, A1300F */
+ A2x, /* A2500H */
+ A4G, /* A4700G */
+ D1x, /* D1 */
+ L2D, /* L2000D */
+ L3C, /* L3800C */
+ L3D, /* L3400D */
+ L3H, /* L3H, L2000E, L5D */
+ L4R, /* L4500R */
+ L5x, /* L5800C */
+ L8L, /* L8400L */
+ M1A, /* M1300A */
+ M2E, /* M2400E, L4400L */
+ M6N, /* M6800N, W3400N */
+ M6R, /* M6700R, A3000G */
+ P30, /* Samsung P30 */
+ S1x, /* S1300A, but also L1400B and M2400A (L84F) */
+ S2x, /* S200 (J1 reported), Victor MP-XP7210 */
+ W1N, /* W1000N */
+ W5A, /* W5A */
+ W3V, /* W3030V */
+ xxN, /* M2400N, M3700N, M5200N, M6800N,
+ S1300N, S5200N*/
+ A4S, /* Z81sp */
+ F3Sa, /* (Centrino) */
END_MODEL
- } model; //Models currently supported
- u16 event_count[128]; //count for each event TODO make this better
+ } model; /* Models currently supported */
+ u16 event_count[128]; /* Count for each event TODO make this better */
};
/* Here we go */
@@ -459,18 +459,18 @@ static struct acpi_driver asus_hotk_driver = {
},
};
-/*
+/*
* This function evaluates an ACPI method, given an int as parameter, the
* method is searched within the scope of the handle, can be NULL. The output
* of the method is written is output, which can also be NULL
*
- * returns 1 if write is successful, 0 else.
+ * returns 1 if write is successful, 0 else.
*/
static int write_acpi_int(acpi_handle handle, const char *method, int val,
struct acpi_buffer *output)
{
- struct acpi_object_list params; //list of input parameters (an int here)
- union acpi_object in_obj; //the only param we use
+ struct acpi_object_list params; /* list of input parameters (int) */
+ union acpi_object in_obj; /* the only param we use */
acpi_status status;
params.count = 1;
@@ -507,18 +507,18 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
{
int len = 0;
int temp;
- char buf[16]; //enough for all info
+ char buf[16]; /* enough for all info */
/*
- * We use the easy way, we don't care of off and count, so we don't set eof
- * to 1
+ * We use the easy way, we don't care of off and count,
+ * so we don't set eof to 1
*/
len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
len += sprintf(page + len, "Model reference : %s\n",
hotk->methods->name);
- /*
- * The SFUN method probably allows the original driver to get the list
- * of features supported by a given model. For now, 0x0100 or 0x0800
+ /*
+ * The SFUN method probably allows the original driver to get the list
+ * of features supported by a given model. For now, 0x0100 or 0x0800
* bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
* The significance of others is yet to be found.
*/
@@ -528,7 +528,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
/*
* Another value for userspace: the ASYM method returns 0x02 for
* battery low and 0x04 for battery critical, its readings tend to be
- * more accurate than those provided by _BST.
+ * more accurate than those provided by _BST.
* Note: since not all the laptops provide this method, errors are
* silently ignored.
*/
@@ -579,7 +579,7 @@ static int read_led(const char *ledname, int ledmask)
return (hotk->status & ledmask) ? 1 : 0;
}
-static int parse_arg(const char __user * buf, unsigned long count, int *val)
+static int parse_arg(const char __user *buf, unsigned long count, int *val)
{
char s[32];
if (!count)
@@ -596,7 +596,7 @@ static int parse_arg(const char __user * buf, unsigned long count, int *val)
/* FIXME: kill extraneous args so it can be called independently */
static int
-write_led(const char __user * buffer, unsigned long count,
+write_led(const char __user *buffer, unsigned long count,
char *ledname, int ledmask, int invert)
{
int rv, value;
@@ -631,7 +631,7 @@ proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_mled(struct file *file, const char __user * buffer,
+proc_write_mled(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
@@ -648,7 +648,7 @@ proc_read_ledd(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_ledd(struct file *file, const char __user * buffer,
+proc_write_ledd(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int rv, value;
@@ -677,7 +677,7 @@ proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_wled(struct file *file, const char __user * buffer,
+proc_write_wled(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
@@ -694,10 +694,10 @@ proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_bluetooth(struct file *file, const char __user * buffer,
+proc_write_bluetooth(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
- /* Note: mt_bt_switch controls both internal Bluetooth adapter's
+ /* Note: mt_bt_switch controls both internal Bluetooth adapter's
presence and its LED */
return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0);
}
@@ -714,7 +714,7 @@ proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_tled(struct file *file, const char __user * buffer,
+proc_write_tled(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
@@ -734,7 +734,7 @@ static int get_lcd_state(void)
input.count = 2;
input.pointer = mt_params;
- /* Note: the following values are partly guessed up, but
+ /* Note: the following values are partly guessed up, but
otherwise they seem to work */
mt_params[0].type = ACPI_TYPE_INTEGER;
mt_params[0].integer.value = 0x02;
@@ -753,7 +753,7 @@ static int get_lcd_state(void)
/* That's what the AML code does */
lcd = out_obj.integer.value >> 8;
} else if (hotk->model == F3Sa) {
- unsigned long tmp;
+ unsigned long long tmp;
union acpi_object param;
struct acpi_object_list input;
acpi_status status;
@@ -796,12 +796,13 @@ static int set_lcd_state(int value)
acpi_evaluate_object(NULL,
hotk->methods->mt_lcd_switch,
NULL, NULL);
- } else { /* L3H and the like have to be handled differently */
+ } else {
+ /* L3H and the like must be handled differently */
if (!write_acpi_int
(hotk->handle, hotk->methods->mt_lcd_switch, 0x07,
NULL))
status = AE_ERROR;
- /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
+ /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
the exact behaviour is simulated here */
}
if (ACPI_FAILURE(status))
@@ -819,7 +820,7 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_lcd(struct file *file, const char __user * buffer,
+proc_write_lcd(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int rv, value;
@@ -897,7 +898,7 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_brn(struct file *file, const char __user * buffer,
+proc_write_brn(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int rv, value;
@@ -921,7 +922,7 @@ static void set_display(int value)
}
/*
- * Now, *this* one could be more user-friendly, but so far, no-one has
+ * Now, *this* one could be more user-friendly, but so far, no-one has
* complained. The significance of bits is the same as in proc_write_disp()
*/
static int
@@ -933,18 +934,18 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
printk(KERN_WARNING
"Asus ACPI: Error reading display status\n");
- value &= 0x07; /* needed for some models, shouldn't hurt others */
+ value &= 0x07; /* needed for some models, shouldn't hurt others */
return sprintf(page, "%d\n", value);
}
/*
- * Experimental support for display switching. As of now: 1 should activate
- * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
- * (bitwise) of these will suffice. I never actually tested 3 displays hooked up
- * simultaneously, so be warned. See the acpi4asus README for more info.
+ * Experimental support for display switching. As of now: 1 should activate
+ * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
+ * (bitwise) of these will suffice. I never actually tested 3 displays hooked
+ * up simultaneously, so be warned. See the acpi4asus README for more info.
*/
static int
-proc_write_disp(struct file *file, const char __user * buffer,
+proc_write_disp(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int rv, value;
@@ -957,12 +958,12 @@ proc_write_disp(struct file *file, const char __user * buffer,
typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
int *eof, void *data);
-typedef int (proc_writefunc) (struct file * file, const char __user * buffer,
+typedef int (proc_writefunc) (struct file *file, const char __user *buffer,
unsigned long count, void *data);
static int
-asus_proc_add(char *name, proc_writefunc * writefunc,
- proc_readfunc * readfunc, mode_t mode,
+asus_proc_add(char *name, proc_writefunc *writefunc,
+ proc_readfunc *readfunc, mode_t mode,
struct acpi_device *device)
{
struct proc_dir_entry *proc =
@@ -1040,9 +1041,9 @@ static int asus_hotk_add_fs(struct acpi_device *device)
&proc_read_bluetooth, mode, device);
}
- /*
- * We need both read node and write method as LCD switch is also accessible
- * from keyboard
+ /*
+ * We need both read node and write method as LCD switch is also
+ * accessible from the keyboard
*/
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode,
@@ -1096,11 +1097,10 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
if (!hotk)
return;
- if ((event & ~((u32) BR_UP)) < 16) {
+ if ((event & ~((u32) BR_UP)) < 16)
hotk->brightness = (event & ~((u32) BR_UP));
- } else if ((event & ~((u32) BR_DOWN)) < 16) {
+ else if ((event & ~((u32) BR_DOWN)) < 16)
hotk->brightness = (event & ~((u32) BR_DOWN));
- }
acpi_bus_generate_proc_event(hotk->device, event,
hotk->event_count[event % 128]++);
@@ -1186,8 +1186,8 @@ static int asus_hotk_get_info(void)
acpi_status status;
/*
- * Get DSDT headers early enough to allow for differentiating between
- * models, but late enough to allow acpi_bus_register_driver() to fail
+ * Get DSDT headers early enough to allow for differentiating between
+ * models, but late enough to allow acpi_bus_register_driver() to fail
* before doing anything ACPI-specific. Should we encounter a machine,
* which needs special handling (i.e. its hotkey device has a different
* HID), this bit will be moved. A global variable asus_info contains
@@ -1212,8 +1212,8 @@ static int asus_hotk_get_info(void)
/*
* Try to match the object returned by INIT to the specific model.
- * Handle every possible object (or the lack of thereof) the DSDT
- * writers might throw at us. When in trouble, we pass NULL to
+ * Handle every possible object (or the lack of thereof) the DSDT
+ * writers might throw at us. When in trouble, we pass NULL to
* asus_model_match() and try something completely different.
*/
if (buffer.pointer) {
@@ -1244,6 +1244,8 @@ static int asus_hotk_get_info(void)
"default values\n", string);
printk(KERN_NOTICE
" send /proc/acpi/dsdt to the developers\n");
+ kfree(model);
+ return -ENODEV;
}
hotk->methods = &model_conf[hotk->model];
return AE_OK;
@@ -1254,7 +1256,7 @@ static int asus_hotk_get_info(void)
/* Sort of per-model blacklist */
if (strncmp(string, "L2B", 3) == 0)
hotk->methods->lcd_status = NULL;
- /* L2B is similar enough to L3C to use its settings, with this only
+ /* L2B is similar enough to L3C to use its settings, with this only
exception */
else if (strncmp(string, "A3G", 3) == 0)
hotk->methods->lcd_status = "\\BLFG";
@@ -1321,7 +1323,7 @@ static int asus_hotk_add(struct acpi_device *device)
hotk->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
- acpi_driver_data(device) = hotk;
+ device->driver_data = hotk;
hotk->device = device;
result = asus_hotk_check();
@@ -1366,10 +1368,9 @@ static int asus_hotk_add(struct acpi_device *device)
/* LED display is off by default */
hotk->ledd_status = 0xFFF;
- end:
- if (result) {
+end:
+ if (result)
kfree(hotk);
- }
return result;
}
@@ -1394,8 +1395,8 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
}
static struct backlight_ops asus_backlight_data = {
- .get_brightness = read_brightness,
- .update_status = set_brightness_status,
+ .get_brightness = read_brightness,
+ .update_status = set_brightness_status,
};
static void asus_acpi_exit(void)
@@ -1442,15 +1443,15 @@ static int __init asus_acpi_init(void)
return -ENODEV;
}
- asus_backlight_device = backlight_device_register("asus",NULL,NULL,
+ asus_backlight_device = backlight_device_register("asus", NULL, NULL,
&asus_backlight_data);
- if (IS_ERR(asus_backlight_device)) {
+ if (IS_ERR(asus_backlight_device)) {
printk(KERN_ERR "Could not register asus backlight device\n");
asus_backlight_device = NULL;
asus_acpi_exit();
return -ENODEV;
}
- asus_backlight_device->props.max_brightness = 15;
+ asus_backlight_device->props.max_brightness = 15;
return 0;
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index b1c723f9f58..b2133e89ad9 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -431,7 +431,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
}
static struct device_attribute alarm_attr = {
- .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
+ .attr = {.name = "alarm", .mode = 0644},
.show = acpi_battery_alarm_show,
.store = acpi_battery_alarm_store,
};
@@ -804,7 +804,7 @@ static int acpi_battery_add(struct acpi_device *device)
battery->device = device;
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
- acpi_driver_data(device) = battery;
+ device->driver_data = battery;
mutex_init(&battery->lock);
acpi_battery_update(battery);
#ifdef CONFIG_ACPI_PROCFS_POWER
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
deleted file mode 100644
index 61b6c5beb2d..00000000000
--- a/drivers/acpi/bay.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * bay.c - ACPI removable drive bay driver
- *
- * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/notifier.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#include <linux/platform_device.h>
-
-ACPI_MODULE_NAME("bay");
-MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
-MODULE_LICENSE("GPL");
-#define ACPI_BAY_CLASS "bay"
-#define ACPI_BAY_COMPONENT 0x10000000
-#define _COMPONENT ACPI_BAY_COMPONENT
-#define bay_dprintk(h,s) {\
- char prefix[80] = {'\0'};\
- struct acpi_buffer buffer = {sizeof(prefix), prefix};\
- acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
- printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
-static void bay_notify(acpi_handle handle, u32 event, void *data);
-
-static const struct acpi_device_id bay_device_ids[] = {
- {"LNXIOBAY", 0},
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, bay_device_ids);
-
-struct bay {
- acpi_handle handle;
- char *name;
- struct list_head list;
- struct platform_device *pdev;
-};
-
-static LIST_HEAD(drive_bays);
-
-
-/*****************************************************************************
- * Drive Bay functions *
- *****************************************************************************/
-/**
- * is_ejectable - see if a device is ejectable
- * @handle: acpi handle of the device
- *
- * If an acpi object has a _EJ0 method, then it is ejectable
- */
-static int is_ejectable(acpi_handle handle)
-{
- acpi_status status;
- acpi_handle tmp;
-
- status = acpi_get_handle(handle, "_EJ0", &tmp);
- if (ACPI_FAILURE(status))
- return 0;
- return 1;
-}
-
-/**
- * bay_present - see if the bay device is present
- * @bay: the drive bay
- *
- * execute the _STA method.
- */
-static int bay_present(struct bay *bay)
-{
- unsigned long sta;
- acpi_status status;
-
- if (bay) {
- status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta);
- if (ACPI_SUCCESS(status) && sta)
- return 1;
- }
- return 0;
-}
-
-/**
- * eject_device - respond to an eject request
- * @handle - the device to eject
- *
- * Call this devices _EJ0 method.
- */
-static void eject_device(acpi_handle handle)
-{
- struct acpi_object_list arg_list;
- union acpi_object arg;
-
- bay_dprintk(handle, "Ejecting device");
-
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
- &arg_list, NULL)))
- pr_debug("Failed to evaluate _EJ0!\n");
-}
-
-/*
- * show_present - read method for "present" file in sysfs
- */
-static ssize_t show_present(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct bay *bay = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay));
-
-}
-static DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
-
-/*
- * write_eject - write method for "eject" file in sysfs
- */
-static ssize_t write_eject(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct bay *bay = dev_get_drvdata(dev);
-
- if (!count)
- return -EINVAL;
-
- eject_device(bay->handle);
- return count;
-}
-static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
-
-/**
- * is_ata - see if a device is an ata device
- * @handle: acpi handle of the device
- *
- * If an acpi object has one of 4 ATA ACPI methods defined,
- * then it is an ATA device
- */
-static int is_ata(acpi_handle handle)
-{
- acpi_handle tmp;
-
- if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
- return 1;
-
- return 0;
-}
-
-/**
- * parent_is_ata(acpi_handle handle)
- *
- */
-static int parent_is_ata(acpi_handle handle)
-{
- acpi_handle phandle;
-
- if (acpi_get_parent(handle, &phandle))
- return 0;
-
- return is_ata(phandle);
-}
-
-/**
- * is_ejectable_bay - see if a device is an ejectable drive bay
- * @handle: acpi handle of the device
- *
- * If an acpi object is ejectable and has one of the ACPI ATA
- * methods defined, then we can safely call it an ejectable
- * drive bay
- */
-static int is_ejectable_bay(acpi_handle handle)
-{
- if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle))
- return 1;
- return 0;
-}
-
-#if 0
-/**
- * eject_removable_drive - try to eject this drive
- * @dev : the device structure of the drive
- *
- * If a device is a removable drive that requires an _EJ0 method
- * to be executed in order to safely remove from the system, do
- * it. ATM - always returns success
- */
-int eject_removable_drive(struct device *dev)
-{
- acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
-
- if (handle) {
- bay_dprintk(handle, "Got device handle");
- if (is_ejectable_bay(handle))
- eject_device(handle);
- } else {
- printk("No acpi handle for device\n");
- }
-
- /* should I return an error code? */
- return 0;
-}
-EXPORT_SYMBOL_GPL(eject_removable_drive);
-#endif /* 0 */
-
-static int acpi_bay_add_fs(struct bay *bay)
-{
- int ret;
- struct device *dev = &bay->pdev->dev;
-
- ret = device_create_file(dev, &dev_attr_present);
- if (ret)
- goto add_fs_err;
- ret = device_create_file(dev, &dev_attr_eject);
- if (ret) {
- device_remove_file(dev, &dev_attr_present);
- goto add_fs_err;
- }
- return 0;
-
- add_fs_err:
- bay_dprintk(bay->handle, "Error adding sysfs files\n");
- return ret;
-}
-
-static void acpi_bay_remove_fs(struct bay *bay)
-{
- struct device *dev = &bay->pdev->dev;
-
- /* cleanup sysfs */
- device_remove_file(dev, &dev_attr_present);
- device_remove_file(dev, &dev_attr_eject);
-}
-
-static int bay_is_dock_device(acpi_handle handle)
-{
- acpi_handle parent;
-
- acpi_get_parent(handle, &parent);
-
- /* if the device or it's parent is dependent on the
- * dock, then we are a dock device
- */
- return (is_dock_device(handle) || is_dock_device(parent));
-}
-
-static int bay_add(acpi_handle handle, int id)
-{
- acpi_status status;
- struct bay *new_bay;
- struct platform_device *pdev;
- struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL};
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer);
-
- bay_dprintk(handle, "Adding notify handler");
-
- /*
- * Initialize bay device structure
- */
- new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC);
- INIT_LIST_HEAD(&new_bay->list);
- new_bay->handle = handle;
- new_bay->name = (char *)nbuffer.pointer;
-
- /* initialize platform device stuff */
- pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
- if (IS_ERR(pdev)) {
- printk(KERN_ERR PREFIX "Error registering bay device\n");
- goto bay_add_err;
- }
- new_bay->pdev = pdev;
- platform_set_drvdata(pdev, new_bay);
-
- /*
- * we want the bay driver to be able to send uevents
- */
- pdev->dev.uevent_suppress = 0;
-
- /* register for events on this device */
- status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- bay_notify, new_bay);
- if (ACPI_FAILURE(status)) {
- printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
- platform_device_unregister(new_bay->pdev);
- goto bay_add_err;
- }
-
- if (acpi_bay_add_fs(new_bay)) {
- acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- bay_notify);
- platform_device_unregister(new_bay->pdev);
- goto bay_add_err;
- }
-
- /* if we are on a dock station, we should register for dock
- * notifications.
- */
- if (bay_is_dock_device(handle)) {
- bay_dprintk(handle, "Is dependent on dock\n");
- register_hotplug_dock_device(handle, bay_notify, new_bay);
- }
- list_add(&new_bay->list, &drive_bays);
- printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name);
- return 0;
-
-bay_add_err:
- kfree(new_bay->name);
- kfree(new_bay);
- return -ENODEV;
-}
-
-/**
- * bay_notify - act upon an acpi bay notification
- * @handle: the bay handle
- * @event: the acpi event
- * @data: our driver data struct
- *
- */
-static void bay_notify(acpi_handle handle, u32 event, void *data)
-{
- struct bay *bay_dev = (struct bay *)data;
- struct device *dev = &bay_dev->pdev->dev;
- char event_string[12];
- char *envp[] = { event_string, NULL };
-
- bay_dprintk(handle, "Bay event");
- sprintf(event_string, "BAY_EVENT=%d", event);
- kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
-}
-
-static acpi_status
-find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- int *count = (int *)context;
-
- /*
- * there could be more than one ejectable bay.
- * so, just return AE_OK always so that every object
- * will be checked.
- */
- if (is_ejectable_bay(handle)) {
- bay_dprintk(handle, "found ejectable bay");
- if (!bay_add(handle, *count))
- (*count)++;
- }
- return AE_OK;
-}
-
-static int __init bay_init(void)
-{
- int bays = 0;
-
- INIT_LIST_HEAD(&drive_bays);
-
- if (acpi_disabled)
- return -ENODEV;
-
- /* look for dockable drive bays */
- acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_bay, &bays, NULL);
-
- if (!bays)
- return -ENODEV;
-
- return 0;
-}
-
-static void __exit bay_exit(void)
-{
- struct bay *bay, *tmp;
-
- list_for_each_entry_safe(bay, tmp, &drive_bays, list) {
- if (is_dock_device(bay->handle))
- unregister_hotplug_dock_device(bay->handle);
- acpi_bay_remove_fs(bay);
- acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY,
- bay_notify);
- platform_device_unregister(bay->pdev);
- kfree(bay->name);
- kfree(bay);
- }
-}
-
-postcore_initcall(bay_init);
-module_exit(bay_exit);
-
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ccae305ee55..c797c6473f3 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -48,6 +48,23 @@ EXPORT_SYMBOL(acpi_root_dir);
#define STRUCT_TO_INT(s) (*((int*)&s))
+static int set_power_nocheck(const struct dmi_system_id *id)
+{
+ printk(KERN_NOTICE PREFIX "%s detected - "
+ "disable power check in power transistion\n", id->ident);
+ acpi_power_nocheck = 1;
+ return 0;
+}
+static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
+ {
+ set_power_nocheck, "HP Pavilion 05", {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL},
+ {},
+};
+
+
/* --------------------------------------------------------------------------
Device Management
-------------------------------------------------------------------------- */
@@ -77,7 +94,7 @@ EXPORT_SYMBOL(acpi_bus_get_device);
int acpi_bus_get_status(struct acpi_device *device)
{
acpi_status status = AE_OK;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
if (!device)
@@ -95,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device)
}
/*
- * Otherwise we assume the status of our parent (unless we don't
- * have one, in which case status is implied).
+ * According to ACPI spec some device can be present and functional
+ * even if the parent is not present but functional.
+ * In such conditions the child device should not inherit the status
+ * from the parent.
*/
- else if (device->parent)
- device->status = device->parent->status;
else
STRUCT_TO_INT(device->status) =
ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
if (device->status.functional && !device->status.present) {
- printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
- "functional but not present; setting present\n",
- device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status));
- device->status.present = 1;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
+ "functional but not present;\n",
+ device->pnp.bus_id,
+ (u32) STRUCT_TO_INT(device->status)));
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
@@ -155,7 +172,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
int result = 0;
acpi_status status = 0;
struct acpi_device *device = NULL;
- unsigned long psc = 0;
+ unsigned long long psc = 0;
result = acpi_bus_get_device(handle, &device);
@@ -223,7 +240,19 @@ int acpi_bus_set_power(acpi_handle handle, int state)
/*
* Get device's current power state
*/
- acpi_bus_get_power(device->handle, &device->power.state);
+ if (!acpi_power_nocheck) {
+ /*
+ * Maybe the incorrect power state is returned on the bogus
+ * bios, which is different with the real power state.
+ * For example: the bios returns D0 state and the real power
+ * state is D3. OS expects to set the device to D0 state. In
+ * such case if OS uses the power state returned by the BIOS,
+ * the device can't be transisted to the correct power state.
+ * So if the acpi_power_nocheck is set, it is unnecessary to
+ * get the power state by calling acpi_bus_get_power.
+ */
+ acpi_bus_get_power(device->handle, &device->power.state);
+ }
if ((state == device->power.state) && !device->flags.force_power_state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
state));
@@ -496,6 +525,19 @@ static int acpi_bus_check_scope(struct acpi_device *device)
return 0;
}
+static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
+int register_acpi_bus_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
+
+void unregister_acpi_bus_notifier(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
+
/**
* acpi_bus_notify
* ---------------
@@ -506,6 +548,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
int result = 0;
struct acpi_device *device = NULL;
+ blocking_notifier_call_chain(&acpi_bus_notify_list,
+ type, (void *)handle);
if (acpi_bus_get_device(handle, &device))
return;
@@ -749,6 +793,12 @@ static int __init acpi_bus_init(void)
goto error1;
}
+ /*
+ * Maybe EC region is required at bus_scan/acpi_get_devices. So it
+ * is necessary to enable it as early as possible.
+ */
+ acpi_boot_ec_enable();
+
printk(KERN_INFO PREFIX "Interpreter enabled\n");
/* Initialize sleep structures */
@@ -818,7 +868,11 @@ static int __init acpi_init(void)
}
} else
disable_acpi();
-
+ /*
+ * If the laptop falls into the DMI check table, the power state check
+ * will be disabled in the course of device power transistion.
+ */
+ dmi_check_system(power_nocheck_dmi_table);
return result;
}
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 1dfec413588..cb046c3fc3f 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -145,7 +145,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_button *button = seq->private;
acpi_status status;
- unsigned long state;
+ unsigned long long state;
if (!button || !button->device)
return 0;
@@ -253,7 +253,7 @@ static int acpi_button_remove_fs(struct acpi_device *device)
-------------------------------------------------------------------------- */
static int acpi_lid_send_state(struct acpi_button *button)
{
- unsigned long state;
+ unsigned long long state;
acpi_status status;
status = acpi_evaluate_integer(button->device->handle, "_LID", NULL,
@@ -262,6 +262,7 @@ static int acpi_lid_send_state(struct acpi_button *button)
return -ENODEV;
/* input layer checks if event is redundant */
input_report_switch(button->input, SW_LID, !state);
+ input_sync(button->input);
return 0;
}
@@ -285,8 +286,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
input_report_key(input, keycode, 1);
input_sync(input);
input_report_key(input, keycode, 0);
+ input_sync(input);
}
- input_sync(input);
acpi_bus_generate_proc_event(button->device, event,
++button->pushed);
@@ -384,7 +385,7 @@ static int acpi_button_add(struct acpi_device *device)
return -ENOMEM;
button->device = device;
- acpi_driver_data(device) = button;
+ device->driver_data = button;
button->input = input = input_allocate_device();
if (!input) {
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index f9db4f444bd..4441e84b28a 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -52,8 +52,8 @@ struct proc_dir_entry *acpi_lock_ac_dir(void)
if (acpi_ac_dir) {
lock_ac_dir_cnt++;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Cannot create %s\n", ACPI_AC_CLASS));
+ printk(KERN_ERR PREFIX
+ "Cannot create %s\n", ACPI_AC_CLASS);
}
mutex_unlock(&cm_sbs_mutex);
return acpi_ac_dir;
@@ -83,8 +83,8 @@ struct proc_dir_entry *acpi_lock_battery_dir(void)
if (acpi_battery_dir) {
lock_battery_dir_cnt++;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Cannot create %s\n", ACPI_BATTERY_CLASS));
+ printk(KERN_ERR PREFIX
+ "Cannot create %s\n", ACPI_BATTERY_CLASS);
}
mutex_unlock(&cm_sbs_mutex);
return acpi_battery_dir;
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 3c25ec7a187..134818b265a 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -76,7 +76,7 @@ static int is_device_present(acpi_handle handle)
{
acpi_handle temp;
acpi_status status;
- unsigned long sta;
+ unsigned long long sta;
status = acpi_get_handle(handle, "_STA", &temp);
@@ -108,7 +108,7 @@ static int acpi_container_add(struct acpi_device *device)
container->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
- acpi_driver_data(device) = container;
+ device->driver_data = container;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
acpi_device_name(device), acpi_device_bid(device)));
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 6df564f4ca6..abf36b4b1d1 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -47,8 +47,6 @@ static const struct acpi_dlayer acpi_debug_layers[] = {
};
static const struct acpi_dlevel acpi_debug_levels[] = {
- ACPI_DEBUG_INIT(ACPI_LV_ERROR),
- ACPI_DEBUG_INIT(ACPI_LV_WARN),
ACPI_DEBUG_INIT(ACPI_LV_INIT),
ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
ACPI_DEBUG_INIT(ACPI_LV_INFO),
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 4613b9ca579..279a5a60a0d 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -103,6 +103,9 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
NULL);
acpi_ex_enter_interpreter();
}
+
+ acpi_ds_clear_implicit_return(walk_state);
+
#ifdef ACPI_DISASSEMBLER
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index 13c43eac35d..d03f81bd1bc 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -43,7 +43,6 @@
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
-#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
@@ -52,11 +51,11 @@ ACPI_MODULE_NAME("dsmthdat")
/* Local prototypes */
static void
-acpi_ds_method_data_delete_value(u16 opcode,
+acpi_ds_method_data_delete_value(u8 type,
u32 index, struct acpi_walk_state *walk_state);
static acpi_status
-acpi_ds_method_data_set_value(u16 opcode,
+acpi_ds_method_data_set_value(u8 type,
u32 index,
union acpi_operand_object *object,
struct acpi_walk_state *walk_state);
@@ -216,7 +215,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
* Store the argument in the method/walk descriptor.
* Do not copy the arg in order to implement call by reference
*/
- status = acpi_ds_method_data_set_value(AML_ARG_OP, index,
+ status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
params[index],
walk_state);
if (ACPI_FAILURE(status)) {
@@ -234,7 +233,8 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
*
* FUNCTION: acpi_ds_method_data_get_node
*
- * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
+ * ACPI_REFCLASS_ARG
* Index - Which Local or Arg whose type to get
* walk_state - Current walk state object
* Node - Where the node is returned.
@@ -246,7 +246,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
******************************************************************************/
acpi_status
-acpi_ds_method_data_get_node(u16 opcode,
+acpi_ds_method_data_get_node(u8 type,
u32 index,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **node)
@@ -256,8 +256,8 @@ acpi_ds_method_data_get_node(u16 opcode,
/*
* Method Locals and Arguments are supported
*/
- switch (opcode) {
- case AML_LOCAL_OP:
+ switch (type) {
+ case ACPI_REFCLASS_LOCAL:
if (index > ACPI_METHOD_MAX_LOCAL) {
ACPI_ERROR((AE_INFO,
@@ -271,7 +271,7 @@ acpi_ds_method_data_get_node(u16 opcode,
*node = &walk_state->local_variables[index];
break;
- case AML_ARG_OP:
+ case ACPI_REFCLASS_ARG:
if (index > ACPI_METHOD_MAX_ARG) {
ACPI_ERROR((AE_INFO,
@@ -286,8 +286,8 @@ acpi_ds_method_data_get_node(u16 opcode,
break;
default:
- ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode));
- return_ACPI_STATUS(AE_AML_BAD_OPCODE);
+ ACPI_ERROR((AE_INFO, "Type %d is invalid", type));
+ return_ACPI_STATUS(AE_TYPE);
}
return_ACPI_STATUS(AE_OK);
@@ -297,7 +297,8 @@ acpi_ds_method_data_get_node(u16 opcode,
*
* FUNCTION: acpi_ds_method_data_set_value
*
- * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
+ * ACPI_REFCLASS_ARG
* Index - Which Local or Arg to get
* Object - Object to be inserted into the stack entry
* walk_state - Current walk state object
@@ -310,7 +311,7 @@ acpi_ds_method_data_get_node(u16 opcode,
******************************************************************************/
static acpi_status
-acpi_ds_method_data_set_value(u16 opcode,
+acpi_ds_method_data_set_value(u8 type,
u32 index,
union acpi_operand_object *object,
struct acpi_walk_state *walk_state)
@@ -321,13 +322,13 @@ acpi_ds_method_data_set_value(u16 opcode,
ACPI_FUNCTION_TRACE(ds_method_data_set_value);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "NewObj %p Opcode %X, Refs=%d [%s]\n", object,
- opcode, object->common.reference_count,
+ "NewObj %p Type %2.2X, Refs=%d [%s]\n", object,
+ type, object->common.reference_count,
acpi_ut_get_type_name(object->common.type)));
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -350,7 +351,8 @@ acpi_ds_method_data_set_value(u16 opcode,
*
* FUNCTION: acpi_ds_method_data_get_value
*
- * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
+ * ACPI_REFCLASS_ARG
* Index - Which local_var or argument to get
* walk_state - Current walk state object
* dest_desc - Where Arg or Local value is returned
@@ -363,7 +365,7 @@ acpi_ds_method_data_set_value(u16 opcode,
******************************************************************************/
acpi_status
-acpi_ds_method_data_get_value(u16 opcode,
+acpi_ds_method_data_get_value(u8 type,
u32 index,
struct acpi_walk_state *walk_state,
union acpi_operand_object **dest_desc)
@@ -383,7 +385,7 @@ acpi_ds_method_data_get_value(u16 opcode,
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -419,8 +421,8 @@ acpi_ds_method_data_get_value(u16 opcode,
/* Otherwise, return the error */
else
- switch (opcode) {
- case AML_ARG_OP:
+ switch (type) {
+ case ACPI_REFCLASS_ARG:
ACPI_ERROR((AE_INFO,
"Uninitialized Arg[%d] at node %p",
@@ -428,7 +430,7 @@ acpi_ds_method_data_get_value(u16 opcode,
return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
- case AML_LOCAL_OP:
+ case ACPI_REFCLASS_LOCAL:
ACPI_ERROR((AE_INFO,
"Uninitialized Local[%d] at node %p",
@@ -437,9 +439,10 @@ acpi_ds_method_data_get_value(u16 opcode,
return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
default:
+
ACPI_ERROR((AE_INFO,
"Not a Arg/Local opcode: %X",
- opcode));
+ type));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
@@ -458,7 +461,8 @@ acpi_ds_method_data_get_value(u16 opcode,
*
* FUNCTION: acpi_ds_method_data_delete_value
*
- * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
+ * ACPI_REFCLASS_ARG
* Index - Which local_var or argument to delete
* walk_state - Current walk state object
*
@@ -470,7 +474,7 @@ acpi_ds_method_data_get_value(u16 opcode,
******************************************************************************/
static void
-acpi_ds_method_data_delete_value(u16 opcode,
+acpi_ds_method_data_delete_value(u8 type,
u32 index, struct acpi_walk_state *walk_state)
{
acpi_status status;
@@ -481,7 +485,7 @@ acpi_ds_method_data_delete_value(u16 opcode,
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_VOID;
}
@@ -514,7 +518,8 @@ acpi_ds_method_data_delete_value(u16 opcode,
*
* FUNCTION: acpi_ds_store_object_to_local
*
- * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or
+ * ACPI_REFCLASS_ARG
* Index - Which Local or Arg to set
* obj_desc - Value to be stored
* walk_state - Current walk state
@@ -528,7 +533,7 @@ acpi_ds_method_data_delete_value(u16 opcode,
******************************************************************************/
acpi_status
-acpi_ds_store_object_to_local(u16 opcode,
+acpi_ds_store_object_to_local(u8 type,
u32 index,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
@@ -539,8 +544,8 @@ acpi_ds_store_object_to_local(u16 opcode,
union acpi_operand_object *new_obj_desc;
ACPI_FUNCTION_TRACE(ds_store_object_to_local);
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
- opcode, index, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n",
+ type, index, obj_desc));
/* Parameter validation */
@@ -550,7 +555,7 @@ acpi_ds_store_object_to_local(u16 opcode,
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -602,7 +607,7 @@ acpi_ds_store_object_to_local(u16 opcode,
*
* Weird, but true.
*/
- if (opcode == AML_ARG_OP) {
+ if (type == ACPI_REFCLASS_ARG) {
/*
* If we have a valid reference object that came from ref_of(),
* do the indirect store
@@ -611,8 +616,8 @@ acpi_ds_store_object_to_local(u16 opcode,
ACPI_DESC_TYPE_OPERAND)
&& (current_obj_desc->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
- && (current_obj_desc->reference.opcode ==
- AML_REF_OF_OP)) {
+ && (current_obj_desc->reference.class ==
+ ACPI_REFCLASS_REFOF)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Arg (%p) is an ObjRef(Node), storing in node %p\n",
new_obj_desc,
@@ -640,11 +645,9 @@ acpi_ds_store_object_to_local(u16 opcode,
}
}
- /*
- * Delete the existing object
- * before storing the new one
- */
- acpi_ds_method_data_delete_value(opcode, index, walk_state);
+ /* Delete the existing object before storing the new one */
+
+ acpi_ds_method_data_delete_value(type, index, walk_state);
}
/*
@@ -653,7 +656,7 @@ acpi_ds_store_object_to_local(u16 opcode,
* (increments the object reference count by one)
*/
status =
- acpi_ds_method_data_set_value(opcode, index, new_obj_desc,
+ acpi_ds_method_data_set_value(type, index, new_obj_desc,
walk_state);
/* Remove local reference if we copied the object above */
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 0f280589921..4f08e599d07 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -731,54 +731,70 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
switch (op_info->type) {
case AML_TYPE_LOCAL_VARIABLE:
- /* Split the opcode into a base opcode + offset */
+ /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */
- obj_desc->reference.opcode = AML_LOCAL_OP;
- obj_desc->reference.offset = opcode - AML_LOCAL_OP;
+ obj_desc->reference.value = opcode - AML_LOCAL_OP;
+ obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
#ifndef ACPI_NO_METHOD_EXECUTION
- status = acpi_ds_method_data_get_node(AML_LOCAL_OP,
- obj_desc->
- reference.offset,
- walk_state,
- (struct
- acpi_namespace_node
- **)&obj_desc->
- reference.object);
+ status =
+ acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
+ obj_desc->reference.
+ value, walk_state,
+ ACPI_CAST_INDIRECT_PTR
+ (struct
+ acpi_namespace_node,
+ &obj_desc->reference.
+ object));
#endif
break;
case AML_TYPE_METHOD_ARGUMENT:
- /* Split the opcode into a base opcode + offset */
+ /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */
- obj_desc->reference.opcode = AML_ARG_OP;
- obj_desc->reference.offset = opcode - AML_ARG_OP;
+ obj_desc->reference.value = opcode - AML_ARG_OP;
+ obj_desc->reference.class = ACPI_REFCLASS_ARG;
#ifndef ACPI_NO_METHOD_EXECUTION
- status = acpi_ds_method_data_get_node(AML_ARG_OP,
+ status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
obj_desc->
- reference.offset,
+ reference.value,
walk_state,
+ ACPI_CAST_INDIRECT_PTR
(struct
- acpi_namespace_node
- **)&obj_desc->
- reference.object);
+ acpi_namespace_node,
+ &obj_desc->
+ reference.
+ object));
#endif
break;
- default: /* Other literals, etc.. */
+ default: /* Object name or Debug object */
- if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+ switch (op->common.aml_opcode) {
+ case AML_INT_NAMEPATH_OP:
/* Node was saved in Op */
obj_desc->reference.node = op->common.node;
obj_desc->reference.object =
op->common.node->object;
- }
+ obj_desc->reference.class = ACPI_REFCLASS_NAME;
+ break;
+
+ case AML_DEBUG_OP:
- obj_desc->reference.opcode = opcode;
+ obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
+ break;
+
+ default:
+
+ ACPI_ERROR((AE_INFO,
+ "Unimplemented reference type for AML opcode: %4.4X",
+ opcode));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ }
break;
}
break;
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 6a81c4400ed..69fae5905bb 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -1330,7 +1330,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
(walk_state->results->results.obj_desc[0]) ==
ACPI_TYPE_LOCAL_REFERENCE)
&& ((walk_state->results->results.obj_desc[0])->
- reference.opcode != AML_INDEX_OP)) {
+ reference.class != ACPI_REFCLASS_INDEX)) {
status =
acpi_ex_resolve_to_value(&walk_state->
results->results.
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index b5072fa9c92..396fe12078c 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -166,6 +166,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
status = AE_CTRL_FALSE;
}
+ /* Predicate can be used for an implicit return value */
+
+ (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE);
+
cleanup:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
@@ -429,10 +433,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
ACPI_TYPE_LOCAL_REFERENCE)
&& (walk_state->operands[1]->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
- && (walk_state->operands[0]->reference.opcode ==
- walk_state->operands[1]->reference.opcode)
- && (walk_state->operands[0]->reference.offset ==
- walk_state->operands[1]->reference.offset)) {
+ && (walk_state->operands[0]->reference.class ==
+ walk_state->operands[1]->reference.class)
+ && (walk_state->operands[0]->reference.value ==
+ walk_state->operands[1]->reference.value)) {
status = AE_OK;
} else {
ACPI_EXCEPTION((AE_INFO, status,
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 7d2edf143f1..5b30b8d91d7 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -48,7 +48,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
" before undocking");
static struct atomic_notifier_head dock_notifier_list;
-static struct platform_device *dock_device;
static char dock_device_name[] = "dock";
static const struct acpi_device_id dock_device_ids[] = {
@@ -65,23 +64,29 @@ struct dock_station {
struct mutex hp_lock;
struct list_head dependent_devices;
struct list_head hotplug_devices;
+
+ struct list_head sibiling;
+ struct platform_device *dock_device;
};
+static LIST_HEAD(dock_stations);
+static int dock_station_count;
struct dock_dependent_device {
struct list_head list;
struct list_head hotplug_list;
acpi_handle handle;
- acpi_notify_handler handler;
+ struct acpi_dock_ops *ops;
void *context;
};
#define DOCK_DOCKING 0x00000001
#define DOCK_UNDOCKING 0x00000002
+#define DOCK_IS_DOCK 0x00000010
+#define DOCK_IS_ATA 0x00000020
+#define DOCK_IS_BAT 0x00000040
#define DOCK_EVENT 3
#define UNDOCK_EVENT 2
-static struct dock_station *dock_station;
-
/*****************************************************************************
* Dock Dependent device functions *
*****************************************************************************/
@@ -199,6 +204,60 @@ static int is_dock(acpi_handle handle)
return 1;
}
+static int is_ejectable(acpi_handle handle)
+{
+ acpi_status status;
+ acpi_handle tmp;
+
+ status = acpi_get_handle(handle, "_EJ0", &tmp);
+ if (ACPI_FAILURE(status))
+ return 0;
+ return 1;
+}
+
+static int is_ata(acpi_handle handle)
+{
+ acpi_handle tmp;
+
+ if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
+ (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
+ (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
+ (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
+ return 1;
+
+ return 0;
+}
+
+static int is_battery(acpi_handle handle)
+{
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ int ret = 1;
+
+ if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer)))
+ return 0;
+ info = buffer.pointer;
+ if (!(info->valid & ACPI_VALID_HID))
+ ret = 0;
+ else
+ ret = !strcmp("PNP0C0A", info->hardware_id.value);
+
+ kfree(buffer.pointer);
+ return ret;
+}
+
+static int is_ejectable_bay(acpi_handle handle)
+{
+ acpi_handle phandle;
+ if (!is_ejectable(handle))
+ return 0;
+ if (is_battery(handle) || is_ata(handle))
+ return 1;
+ if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
+ return 1;
+ return 0;
+}
+
/**
* is_dock_device - see if a device is on a dock station
* @handle: acpi handle of the device
@@ -209,11 +268,17 @@ static int is_dock(acpi_handle handle)
*/
int is_dock_device(acpi_handle handle)
{
- if (!dock_station)
+ struct dock_station *dock_station;
+
+ if (!dock_station_count)
return 0;
- if (is_dock(handle) || find_dock_dependent_device(dock_station, handle))
+ if (is_dock(handle))
return 1;
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ if (find_dock_dependent_device(dock_station, handle))
+ return 1;
+ }
return 0;
}
@@ -229,7 +294,7 @@ EXPORT_SYMBOL_GPL(is_dock_device);
*/
static int dock_present(struct dock_station *ds)
{
- unsigned long sta;
+ unsigned long long sta;
acpi_status status;
if (ds) {
@@ -320,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
* First call driver specific hotplug functions
*/
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
- if (dd->handler)
- dd->handler(dd->handle, event, dd->context);
+ if (dd->ops && dd->ops->handler)
+ dd->ops->handler(dd->handle, event, dd->context);
}
/*
@@ -341,9 +406,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
static void dock_event(struct dock_station *ds, u32 event, int num)
{
- struct device *dev = &dock_device->dev;
+ struct device *dev = &ds->dock_device->dev;
char event_string[13];
char *envp[] = { event_string, NULL };
+ struct dock_dependent_device *dd;
if (num == UNDOCK_EVENT)
sprintf(event_string, "EVENT=undock");
@@ -354,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
* Indicate that the status of the dock station has
* changed.
*/
- kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
+ if (num == DOCK_EVENT)
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
+
+ list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
+ if (dd->ops && dd->ops->uevent)
+ dd->ops->uevent(dd->handle, event, dd->context);
+ if (num != DOCK_EVENT)
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
}
/**
@@ -414,9 +487,10 @@ static void handle_dock(struct dock_station *ds, int dock)
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = dock;
status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
- if (ACPI_FAILURE(status))
- printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n",
- (char *)name_buffer.pointer);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+ ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
+ " _DCK\n", (char *)name_buffer.pointer));
+
kfree(buffer.pointer);
kfree(name_buffer.pointer);
}
@@ -452,6 +526,25 @@ static inline void complete_undock(struct dock_station *ds)
ds->flags &= ~(DOCK_UNDOCKING);
}
+static void dock_lock(struct dock_station *ds, int lock)
+{
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ acpi_status status;
+
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = !!lock;
+ status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ if (lock)
+ printk(KERN_WARNING PREFIX "Locking device failed\n");
+ else
+ printk(KERN_WARNING PREFIX "Unlocking device failed\n");
+ }
+}
+
/**
* dock_in_progress - see if we are in the middle of handling a dock event
* @ds: the dock station
@@ -479,7 +572,7 @@ static int dock_in_progress(struct dock_station *ds)
*/
int register_dock_notifier(struct notifier_block *nb)
{
- if (!dock_station)
+ if (!dock_station_count)
return -ENODEV;
return atomic_notifier_chain_register(&dock_notifier_list, nb);
@@ -493,7 +586,7 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
*/
void unregister_dock_notifier(struct notifier_block *nb)
{
- if (!dock_station)
+ if (!dock_station_count)
return;
atomic_notifier_chain_unregister(&dock_notifier_list, nb);
@@ -504,7 +597,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
/**
* register_hotplug_dock_device - register a hotplug function
* @handle: the handle of the device
- * @handler: the acpi_notifier_handler to call after docking
+ * @ops: handlers to call after docking
* @context: device specific data
*
* If a driver would like to perform a hotplug operation after a dock
@@ -512,27 +605,36 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
* the dock driver after _DCK is executed.
*/
int
-register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
+register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
void *context)
{
struct dock_dependent_device *dd;
+ struct dock_station *dock_station;
+ int ret = -EINVAL;
- if (!dock_station)
+ if (!dock_station_count)
return -ENODEV;
/*
* make sure this handle is for a device dependent on the dock,
* this would include the dock station itself
*/
- dd = find_dock_dependent_device(dock_station, handle);
- if (dd) {
- dd->handler = handler;
- dd->context = context;
- dock_add_hotplug_device(dock_station, dd);
- return 0;
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ /*
+ * An ATA bay can be in a dock and itself can be ejected
+ * seperately, so there are two 'dock stations' which need the
+ * ops
+ */
+ dd = find_dock_dependent_device(dock_station, handle);
+ if (dd) {
+ dd->ops = ops;
+ dd->context = context;
+ dock_add_hotplug_device(dock_station, dd);
+ ret = 0;
+ }
}
- return -EINVAL;
+ return ret;
}
EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
@@ -544,13 +646,16 @@ EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
void unregister_hotplug_dock_device(acpi_handle handle)
{
struct dock_dependent_device *dd;
+ struct dock_station *dock_station;
- if (!dock_station)
+ if (!dock_station_count)
return;
- dd = find_dock_dependent_device(dock_station, handle);
- if (dd)
- dock_del_hotplug_device(dock_station, dd);
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ dd = find_dock_dependent_device(dock_station, handle);
+ if (dd)
+ dock_del_hotplug_device(dock_station, dd);
+ }
}
EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
@@ -575,13 +680,9 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
*/
dock_event(ds, event, UNDOCK_EVENT);
- if (!dock_present(ds)) {
- complete_undock(ds);
- return -ENODEV;
- }
-
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
undock(ds);
+ dock_lock(ds, 0);
eject_dock(ds);
if (dock_present(ds)) {
printk(KERN_ERR PREFIX "Unable to undock!\n");
@@ -604,14 +705,36 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
static void dock_notify(acpi_handle handle, u32 event, void *data)
{
struct dock_station *ds = data;
+ struct acpi_device *tmp;
+ int surprise_removal = 0;
+
+ /*
+ * According to acpi spec 3.0a, if a DEVICE_CHECK notification
+ * is sent and _DCK is present, it is assumed to mean an undock
+ * request.
+ */
+ if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
+ event = ACPI_NOTIFY_EJECT_REQUEST;
+ /*
+ * dock station: BUS_CHECK - docked or surprise removal
+ * DEVICE_CHECK - undocked
+ * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
+ *
+ * To simplify event handling, dock dependent device handler always
+ * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
+ * ACPI_NOTIFY_EJECT_REQUEST for removal
+ */
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
- if (!dock_in_progress(ds) && dock_present(ds)) {
+ case ACPI_NOTIFY_DEVICE_CHECK:
+ if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
+ &tmp)) {
begin_dock(ds);
dock(ds);
if (!dock_present(ds)) {
printk(KERN_ERR PREFIX "Unable to dock!\n");
+ complete_dock(ds);
break;
}
atomic_notifier_call_chain(&dock_notifier_list,
@@ -619,20 +742,19 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
hotplug_dock_devices(ds, event);
complete_dock(ds);
dock_event(ds, event, DOCK_EVENT);
+ dock_lock(ds, 1);
+ break;
}
- break;
- case ACPI_NOTIFY_DEVICE_CHECK:
- /*
- * According to acpi spec 3.0a, if a DEVICE_CHECK notification
- * is sent and _DCK is present, it is assumed to mean an
- * undock request. This notify routine will only be called
- * for objects defining _DCK, so we will fall through to eject
- * request here. However, we will pass an eject request through
- * to the driver who wish to hotplug.
- */
+ if (dock_present(ds) || dock_in_progress(ds))
+ break;
+ /* This is a surprise removal */
+ surprise_removal = 1;
+ event = ACPI_NOTIFY_EJECT_REQUEST;
+ /* Fall back */
case ACPI_NOTIFY_EJECT_REQUEST:
begin_undock(ds);
- if (immediate_undock)
+ if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
+ || surprise_removal)
handle_eject_request(ds, event);
else
dock_event(ds, event, UNDOCK_EVENT);
@@ -642,6 +764,51 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
}
}
+struct dock_data {
+ acpi_handle handle;
+ unsigned long event;
+ struct dock_station *ds;
+};
+
+static void acpi_dock_deferred_cb(void *context)
+{
+ struct dock_data *data = (struct dock_data *)context;
+
+ dock_notify(data->handle, data->event, data->ds);
+ kfree(data);
+}
+
+static int acpi_dock_notifier_call(struct notifier_block *this,
+ unsigned long event, void *data)
+{
+ struct dock_station *dock_station;
+ acpi_handle handle = (acpi_handle)data;
+
+ if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
+ && event != ACPI_NOTIFY_EJECT_REQUEST)
+ return 0;
+ list_for_each_entry(dock_station, &dock_stations, sibiling) {
+ if (dock_station->handle == handle) {
+ struct dock_data *dock_data;
+
+ dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL);
+ if (!dock_data)
+ return 0;
+ dock_data->handle = handle;
+ dock_data->event = event;
+ dock_data->ds = dock_station;
+ acpi_os_hotplug_execute(acpi_dock_deferred_cb,
+ dock_data);
+ return 0 ;
+ }
+ }
+ return 0;
+}
+
+static struct notifier_block dock_acpi_notifier = {
+ .notifier_call = acpi_dock_notifier_call,
+};
+
/**
* find_dock_devices - find devices on the dock station
* @handle: the handle of the device we are examining
@@ -688,6 +855,8 @@ fdd_out:
static ssize_t show_docked(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
}
@@ -699,6 +868,8 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
static ssize_t show_flags(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
}
@@ -711,6 +882,8 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
if (!count)
return -EINVAL;
@@ -727,16 +900,38 @@ static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
static ssize_t show_dock_uid(struct device *dev,
struct device_attribute *attr, char *buf)
{
- unsigned long lbuf;
+ unsigned long long lbuf;
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
acpi_status status = acpi_evaluate_integer(dock_station->handle,
"_UID", NULL, &lbuf);
if (ACPI_FAILURE(status))
return 0;
- return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
+ return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
}
static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
+static ssize_t show_dock_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dock_station *dock_station = *((struct dock_station **)
+ dev->platform_data);
+ char *type;
+
+ if (dock_station->flags & DOCK_IS_DOCK)
+ type = "dock_station";
+ else if (dock_station->flags & DOCK_IS_ATA)
+ type = "ata_bay";
+ else if (dock_station->flags & DOCK_IS_BAT)
+ type = "battery_bay";
+ else
+ type = "unknown";
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", type);
+}
+static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
+
/**
* dock_add - add a new dock station
* @handle: the dock station handle
@@ -747,8 +942,9 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
static int dock_add(acpi_handle handle)
{
int ret;
- acpi_status status;
struct dock_dependent_device *dd;
+ struct dock_station *dock_station;
+ struct platform_device *dock_device;
/* allocate & initialize the dock_station private data */
dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
@@ -758,22 +954,34 @@ static int dock_add(acpi_handle handle)
dock_station->last_dock_time = jiffies - HZ;
INIT_LIST_HEAD(&dock_station->dependent_devices);
INIT_LIST_HEAD(&dock_station->hotplug_devices);
+ INIT_LIST_HEAD(&dock_station->sibiling);
spin_lock_init(&dock_station->dd_lock);
mutex_init(&dock_station->hp_lock);
ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
/* initialize platform device stuff */
- dock_device =
- platform_device_register_simple(dock_device_name, 0, NULL, 0);
+ dock_station->dock_device =
+ platform_device_register_simple(dock_device_name,
+ dock_station_count, NULL, 0);
+ dock_device = dock_station->dock_device;
if (IS_ERR(dock_device)) {
kfree(dock_station);
dock_station = NULL;
return PTR_ERR(dock_device);
}
+ platform_device_add_data(dock_device, &dock_station,
+ sizeof(struct dock_station *));
/* we want the dock device to send uevents */
dock_device->dev.uevent_suppress = 0;
+ if (is_dock(handle))
+ dock_station->flags |= DOCK_IS_DOCK;
+ if (is_ata(handle))
+ dock_station->flags |= DOCK_IS_ATA;
+ if (is_battery(handle))
+ dock_station->flags |= DOCK_IS_BAT;
+
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
if (ret) {
printk("Error %d adding sysfs file\n", ret);
@@ -812,6 +1020,9 @@ static int dock_add(acpi_handle handle)
dock_station = NULL;
return ret;
}
+ ret = device_create_file(&dock_device->dev, &dev_attr_type);
+ if (ret)
+ printk(KERN_ERR"Error %d adding sysfs file\n", ret);
/* Find dependent devices */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -828,24 +1039,12 @@ static int dock_add(acpi_handle handle)
}
add_dock_dependent_device(dock_station, dd);
- /* register for dock events */
- status = acpi_install_notify_handler(dock_station->handle,
- ACPI_SYSTEM_NOTIFY,
- dock_notify, dock_station);
-
- if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Error installing notify handler\n");
- ret = -ENODEV;
- goto dock_add_err;
- }
-
- printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION);
-
+ dock_station_count++;
+ list_add(&dock_station->sibiling, &dock_stations);
return 0;
-dock_add_err:
- kfree(dd);
dock_add_err_unregister:
+ device_remove_file(&dock_device->dev, &dev_attr_type);
device_remove_file(&dock_device->dev, &dev_attr_docked);
device_remove_file(&dock_device->dev, &dev_attr_undock);
device_remove_file(&dock_device->dev, &dev_attr_uid);
@@ -859,12 +1058,12 @@ dock_add_err_unregister:
/**
* dock_remove - free up resources related to the dock station
*/
-static int dock_remove(void)
+static int dock_remove(struct dock_station *dock_station)
{
struct dock_dependent_device *dd, *tmp;
- acpi_status status;
+ struct platform_device *dock_device = dock_station->dock_device;
- if (!dock_station)
+ if (!dock_station_count)
return 0;
/* remove dependent devices */
@@ -872,14 +1071,8 @@ static int dock_remove(void)
list)
kfree(dd);
- /* remove dock notify handler */
- status = acpi_remove_notify_handler(dock_station->handle,
- ACPI_SYSTEM_NOTIFY,
- dock_notify);
- if (ACPI_FAILURE(status))
- printk(KERN_ERR "Error removing notify handler\n");
-
/* cleanup sysfs */
+ device_remove_file(&dock_device->dev, &dev_attr_type);
device_remove_file(&dock_device->dev, &dev_attr_docked);
device_remove_file(&dock_device->dev, &dev_attr_undock);
device_remove_file(&dock_device->dev, &dev_attr_uid);
@@ -904,41 +1097,60 @@ static int dock_remove(void)
static acpi_status
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- int *count = context;
acpi_status status = AE_OK;
if (is_dock(handle)) {
if (dock_add(handle) >= 0) {
- (*count)++;
status = AE_CTRL_TERMINATE;
}
}
return status;
}
-static int __init dock_init(void)
+static acpi_status
+find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- int num = 0;
-
- dock_station = NULL;
+ /* If bay is a dock, it's already handled */
+ if (is_ejectable_bay(handle) && !is_dock(handle))
+ dock_add(handle);
+ return AE_OK;
+}
+static int __init dock_init(void)
+{
if (acpi_disabled)
return 0;
/* look for a dock station */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_dock, &num, NULL);
+ ACPI_UINT32_MAX, find_dock, NULL, NULL);
- if (!num)
- printk(KERN_INFO "No dock devices found.\n");
+ /* look for bay */
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, find_bay, NULL, NULL);
+ if (!dock_station_count) {
+ printk(KERN_INFO PREFIX "No dock devices found.\n");
+ return 0;
+ }
+ register_acpi_bus_notifier(&dock_acpi_notifier);
+ printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
+ ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
return 0;
}
static void __exit dock_exit(void)
{
- dock_remove();
+ struct dock_station *dock_station;
+
+ unregister_acpi_bus_notifier(&dock_acpi_notifier);
+ list_for_each_entry(dock_station, &dock_stations, sibiling)
+ dock_remove(dock_station);
}
-postcore_initcall(dock_init);
+/*
+ * Must be called before drivers of devices in dock, otherwise we can't know
+ * which devices are in a dock
+ */
+subsys_initcall(dock_init);
module_exit(dock_exit);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 13593f9f219..ef42316f89f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1,7 +1,7 @@
/*
- * ec.c - ACPI Embedded Controller Driver (v2.0)
+ * ec.c - ACPI Embedded Controller Driver (v2.1)
*
- * Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
+ * Copyright (C) 2006-2008 Alexey Starikovskiy <astarikovskiy@suse.de>
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
@@ -26,7 +26,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-/* Uncomment next line to get verbose print outs*/
+/* Uncomment next line to get verbose printout */
/* #define DEBUG */
#include <linux/kernel.h>
@@ -38,6 +38,7 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/list.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -65,22 +66,21 @@ enum ec_command {
ACPI_EC_COMMAND_QUERY = 0x84,
};
-/* EC events */
-enum ec_event {
- ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
- ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
-};
-
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */
+#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts
+ per one transaction */
+
enum {
- EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
EC_FLAGS_QUERY_PENDING, /* Query is pending */
- EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
+ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent
+ * for status change */
EC_FLAGS_NO_GPE, /* Don't use GPE mode */
- EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */
+ EC_FLAGS_GPE_STORM, /* GPE storm detected */
+ EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and
+ * OpReg are installed */
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -95,6 +95,15 @@ struct acpi_ec_query_handler {
u8 query_bit;
};
+struct transaction {
+ const u8 *wdata;
+ u8 *rdata;
+ unsigned short irq_count;
+ u8 command;
+ u8 wlen;
+ u8 rlen;
+};
+
static struct acpi_ec {
acpi_handle handle;
unsigned long gpe;
@@ -105,9 +114,8 @@ static struct acpi_ec {
struct mutex lock;
wait_queue_head_t wait;
struct list_head list;
- struct delayed_work work;
- atomic_t irq_count;
- u8 handlers_installed;
+ struct transaction *curr;
+ spinlock_t curr_lock;
} *boot_ec, *first_ec;
/*
@@ -150,7 +158,7 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{
u8 x = inb(ec->data_addr);
pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
- return inb(ec->data_addr);
+ return x;
}
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
@@ -165,158 +173,172 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
+static int ec_transaction_done(struct acpi_ec *ec)
{
- if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags))
- return 0;
- if (event == ACPI_EC_EVENT_OBF_1) {
- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
- return 1;
- } else if (event == ACPI_EC_EVENT_IBF_0) {
- if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
- return 1;
- }
-
- return 0;
+ unsigned long flags;
+ int ret = 0;
+ spin_lock_irqsave(&ec->curr_lock, flags);
+ if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen))
+ ret = 1;
+ spin_unlock_irqrestore(&ec->curr_lock, flags);
+ return ret;
}
-static void ec_schedule_ec_poll(struct acpi_ec *ec)
+static void gpe_transaction(struct acpi_ec *ec, u8 status)
{
- if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
- schedule_delayed_work(&ec->work,
- msecs_to_jiffies(ACPI_EC_DELAY));
+ unsigned long flags;
+ spin_lock_irqsave(&ec->curr_lock, flags);
+ if (!ec->curr)
+ goto unlock;
+ if (ec->curr->wlen > 0) {
+ if ((status & ACPI_EC_FLAG_IBF) == 0) {
+ acpi_ec_write_data(ec, *(ec->curr->wdata++));
+ --ec->curr->wlen;
+ } else
+ /* false interrupt, state didn't change */
+ ++ec->curr->irq_count;
+
+ } else if (ec->curr->rlen > 0) {
+ if ((status & ACPI_EC_FLAG_OBF) == 1) {
+ *(ec->curr->rdata++) = acpi_ec_read_data(ec);
+ --ec->curr->rlen;
+ } else
+ /* false interrupt, state didn't change */
+ ++ec->curr->irq_count;
+ }
+unlock:
+ spin_unlock_irqrestore(&ec->curr_lock, flags);
}
-static void ec_switch_to_poll_mode(struct acpi_ec *ec)
+static int acpi_ec_wait(struct acpi_ec *ec)
{
+ if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
+ msecs_to_jiffies(ACPI_EC_DELAY)))
+ return 0;
+ /* missing GPEs, switch back to poll mode */
+ if (printk_ratelimit())
+ pr_info(PREFIX "missing confirmations, "
+ "switch off interrupt mode.\n");
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
- set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
+ return 1;
}
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+static void acpi_ec_gpe_query(void *ec_cxt);
+
+static int ec_check_sci(struct acpi_ec *ec, u8 state)
{
- atomic_set(&ec->irq_count, 0);
- if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
- likely(!force_poll)) {
- if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
- msecs_to_jiffies(ACPI_EC_DELAY)))
- return 0;
- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- if (acpi_ec_check_status(ec, event)) {
- /* missing GPEs, switch back to poll mode */
- if (printk_ratelimit())
- pr_info(PREFIX "missing confirmations, "
- "switch off interrupt mode.\n");
- ec_switch_to_poll_mode(ec);
- ec_schedule_ec_poll(ec);
- return 0;
- }
- } else {
- unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- while (time_before(jiffies, delay)) {
- if (acpi_ec_check_status(ec, event))
- return 0;
- msleep(1);
- }
- if (acpi_ec_check_status(ec,event))
+ if (state & ACPI_EC_FLAG_SCI) {
+ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
+ return acpi_os_execute(OSL_EC_BURST_HANDLER,
+ acpi_ec_gpe_query, ec);
+ }
+ return 0;
+}
+
+static int ec_poll(struct acpi_ec *ec)
+{
+ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ msleep(1);
+ while (time_before(jiffies, delay)) {
+ gpe_transaction(ec, acpi_ec_read_status(ec));
+ msleep(1);
+ if (ec_transaction_done(ec))
return 0;
}
- pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
- acpi_ec_read_status(ec),
- (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\"");
return -ETIME;
}
-static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
- const u8 * wdata, unsigned wdata_len,
- u8 * rdata, unsigned rdata_len,
+static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
+ struct transaction *t,
int force_poll)
{
- int result = 0;
- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ unsigned long tmp;
+ int ret = 0;
pr_debug(PREFIX "transaction start\n");
- acpi_ec_write_cmd(ec, command);
- for (; wdata_len > 0; --wdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
- if (result) {
- pr_err(PREFIX
- "write_cmd timeout, command = %d\n", command);
- goto end;
- }
- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- acpi_ec_write_data(ec, *(wdata++));
+ /* disable GPE during transaction if storm is detected */
+ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
+ acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
}
-
- if (!rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
- if (result) {
- pr_err(PREFIX
- "finish-write timeout, command = %d\n", command);
- goto end;
- }
- } else if (command == ACPI_EC_COMMAND_QUERY)
+ /* start transaction */
+ spin_lock_irqsave(&ec->curr_lock, tmp);
+ /* following two actions should be kept atomic */
+ t->irq_count = 0;
+ ec->curr = t;
+ acpi_ec_write_cmd(ec, ec->curr->command);
+ if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
-
- for (; rdata_len > 0; --rdata_len) {
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
- if (result) {
- pr_err(PREFIX "read timeout, command = %d\n", command);
- goto end;
- }
- /* Don't expect GPE after last read */
- if (rdata_len > 1)
- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- *(rdata++) = acpi_ec_read_data(ec);
- }
- end:
+ spin_unlock_irqrestore(&ec->curr_lock, tmp);
+ /* if we selected poll mode or failed in GPE-mode do a poll loop */
+ if (force_poll ||
+ !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ||
+ acpi_ec_wait(ec))
+ ret = ec_poll(ec);
pr_debug(PREFIX "transaction end\n");
- return result;
+ spin_lock_irqsave(&ec->curr_lock, tmp);
+ ec->curr = NULL;
+ spin_unlock_irqrestore(&ec->curr_lock, tmp);
+ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+ /* check if we received SCI during transaction */
+ ec_check_sci(ec, acpi_ec_read_status(ec));
+ /* it is safe to enable GPE outside of transaction */
+ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
+ t->irq_count > ACPI_EC_STORM_THRESHOLD) {
+ pr_debug(PREFIX "GPE storm detected\n");
+ set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
+ }
+ return ret;
+}
+
+static int ec_check_ibf0(struct acpi_ec *ec)
+{
+ u8 status = acpi_ec_read_status(ec);
+ return (status & ACPI_EC_FLAG_IBF) == 0;
}
-static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
- const u8 * wdata, unsigned wdata_len,
- u8 * rdata, unsigned rdata_len,
+static int ec_wait_ibf0(struct acpi_ec *ec)
+{
+ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ /* interrupt wait manually if GPE mode is not active */
+ unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ?
+ msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1);
+ while (time_before(jiffies, delay))
+ if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout))
+ return 0;
+ return -ETIME;
+}
+
+static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
int force_poll)
{
int status;
u32 glk;
-
- if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
+ if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
return -EINVAL;
-
- if (rdata)
- memset(rdata, 0, rdata_len);
-
+ if (t->rdata)
+ memset(t->rdata, 0, t->rlen);
mutex_lock(&ec->lock);
if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status)) {
- mutex_unlock(&ec->lock);
- return -ENODEV;
+ status = -ENODEV;
+ goto unlock;
}
}
-
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
- if (status) {
+ if (ec_wait_ibf0(ec)) {
pr_err(PREFIX "input buffer is not empty, "
"aborting transaction\n");
+ status = -ETIME;
goto end;
}
-
- status = acpi_ec_transaction_unlocked(ec, command,
- wdata, wdata_len,
- rdata, rdata_len,
- force_poll);
-
- end:
-
+ status = acpi_ec_transaction_unlocked(ec, t, force_poll);
+end:
if (ec->global_lock)
acpi_release_global_lock(glk);
+unlock:
mutex_unlock(&ec->lock);
-
return status;
}
@@ -327,21 +349,32 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
int acpi_ec_burst_enable(struct acpi_ec *ec)
{
u8 d;
- return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0);
+ struct transaction t = {.command = ACPI_EC_BURST_ENABLE,
+ .wdata = NULL, .rdata = &d,
+ .wlen = 0, .rlen = 1};
+
+ return acpi_ec_transaction(ec, &t, 0);
}
int acpi_ec_burst_disable(struct acpi_ec *ec)
{
- return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0);
+ struct transaction t = {.command = ACPI_EC_BURST_DISABLE,
+ .wdata = NULL, .rdata = NULL,
+ .wlen = 0, .rlen = 0};
+
+ return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
+ acpi_ec_transaction(ec, &t, 0) : 0;
}
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
{
int result;
u8 d;
+ struct transaction t = {.command = ACPI_EC_COMMAND_READ,
+ .wdata = &address, .rdata = &d,
+ .wlen = 1, .rlen = 1};
- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
- &address, 1, &d, 1, 0);
+ result = acpi_ec_transaction(ec, &t, 0);
*data = d;
return result;
}
@@ -349,8 +382,11 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
{
u8 wdata[2] = { address, data };
- return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
- wdata, 2, NULL, 0, 0);
+ struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
+ .wdata = wdata, .rdata = NULL,
+ .wlen = 2, .rlen = 0};
+
+ return acpi_ec_transaction(ec, &t, 0);
}
/*
@@ -412,12 +448,13 @@ int ec_transaction(u8 command,
u8 * rdata, unsigned rdata_len,
int force_poll)
{
+ struct transaction t = {.command = command,
+ .wdata = wdata, .rdata = rdata,
+ .wlen = wdata_len, .rlen = rdata_len};
if (!first_ec)
return -ENODEV;
- return acpi_ec_transaction(first_ec, command, wdata,
- wdata_len, rdata, rdata_len,
- force_poll);
+ return acpi_ec_transaction(first_ec, &t, force_poll);
}
EXPORT_SYMBOL(ec_transaction);
@@ -426,7 +463,9 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
{
int result;
u8 d;
-
+ struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
+ .wdata = NULL, .rdata = &d,
+ .wlen = 0, .rlen = 1};
if (!ec || !data)
return -EINVAL;
@@ -436,7 +475,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
* bit to be cleared (and thus clearing the interrupt source).
*/
- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0);
+ result = acpi_ec_transaction(ec, &t, 0);
if (result)
return result;
@@ -513,46 +552,26 @@ static void acpi_ec_gpe_query(void *ec_cxt)
static u32 acpi_ec_gpe_handler(void *data)
{
- acpi_status status = AE_OK;
struct acpi_ec *ec = data;
- u8 state = acpi_ec_read_status(ec);
+ u8 status;
pr_debug(PREFIX "~~~> interrupt\n");
- atomic_inc(&ec->irq_count);
- if (atomic_read(&ec->irq_count) > 5) {
- pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
- ec_switch_to_poll_mode(ec);
- goto end;
- }
- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
- if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
+ status = acpi_ec_read_status(ec);
+
+ gpe_transaction(ec, status);
+ if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
wake_up(&ec->wait);
- if (state & ACPI_EC_FLAG_SCI) {
- if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
- status = acpi_os_execute(OSL_EC_BURST_HANDLER,
- acpi_ec_gpe_query, ec);
- } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
- !test_bit(EC_FLAGS_NO_GPE, &ec->flags) &&
- in_interrupt()) {
+ ec_check_sci(ec, status);
+ if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
+ !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) {
/* this is non-query, must be confirmation */
if (printk_ratelimit())
pr_info(PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
}
-end:
- ec_schedule_ec_poll(ec);
- return ACPI_SUCCESS(status) ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
-}
-
-static void do_ec_poll(struct work_struct *work)
-{
- struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work);
- atomic_set(&ec->irq_count, 0);
- (void)acpi_ec_gpe_handler(ec);
+ return ACPI_INTERRUPT_HANDLED;
}
/* --------------------------------------------------------------------------
@@ -696,8 +715,7 @@ static struct acpi_ec *make_acpi_ec(void)
mutex_init(&ec->lock);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
- INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll);
- atomic_set(&ec->irq_count, 0);
+ spin_lock_init(&ec->curr_lock);
return ec;
}
@@ -718,6 +736,7 @@ static acpi_status
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
{
acpi_status status;
+ unsigned long long tmp;
struct acpi_ec *ec = context;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
@@ -727,31 +746,26 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
if (ACPI_FAILURE(status))
return status;
+ ec->gpe = tmp;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
+ acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
+ ec->global_lock = tmp;
ec->handle = handle;
return AE_CTRL_TERMINATE;
}
-static void ec_poll_stop(struct acpi_ec *ec)
-{
- clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags);
- cancel_delayed_work(&ec->work);
-}
-
static void ec_remove_handlers(struct acpi_ec *ec)
{
- ec_poll_stop(ec);
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
pr_err(PREFIX "failed to remove gpe handler\n");
- ec->handlers_installed = 0;
+ clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
}
static int acpi_ec_add(struct acpi_device *device)
@@ -788,7 +802,7 @@ static int acpi_ec_add(struct acpi_device *device)
if (!first_ec)
first_ec = ec;
- acpi_driver_data(device) = ec;
+ device->driver_data = ec;
acpi_ec_add_fs(device);
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
@@ -813,7 +827,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
}
mutex_unlock(&ec->lock);
acpi_ec_remove_fs(device);
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
if (ec == first_ec)
first_ec = NULL;
kfree(ec);
@@ -846,27 +860,36 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
static int ec_install_handlers(struct acpi_ec *ec)
{
acpi_status status;
- if (ec->handlers_installed)
+ if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
return 0;
status = acpi_install_gpe_handler(NULL, ec->gpe,
- ACPI_GPE_EDGE_TRIGGERED,
- &acpi_ec_gpe_handler, ec);
+ ACPI_GPE_EDGE_TRIGGERED,
+ &acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status))
return -ENODEV;
-
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
-
status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
NULL, ec);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
- return -ENODEV;
+ if (status == AE_NOT_FOUND) {
+ /*
+ * Maybe OS fails in evaluating the _REG object.
+ * The AE_NOT_FOUND error will be ignored and OS
+ * continue to initialize EC.
+ */
+ printk(KERN_ERR "Fail in evaluating the _REG object"
+ " of EC device. Broken bios is suspected.\n");
+ } else {
+ acpi_remove_gpe_handler(NULL, ec->gpe,
+ &acpi_ec_gpe_handler);
+ return -ENODEV;
+ }
}
- ec->handlers_installed = 1;
+ set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
return 0;
}
@@ -887,7 +910,6 @@ static int acpi_ec_start(struct acpi_device *device)
/* EC is fully operational, allow queries */
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
- ec_schedule_ec_poll(ec);
return ret;
}
@@ -906,7 +928,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
int __init acpi_boot_ec_enable(void)
{
- if (!boot_ec || boot_ec->handlers_installed)
+ if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
return 0;
if (!ec_install_handlers(boot_ec)) {
first_ec = boot_ec;
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 8892b9824fa..74da6fa52ef 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -43,7 +43,6 @@
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/actables.h>
#include <acpi/acdispat.h>
@@ -91,13 +90,12 @@ acpi_ex_add_table(u32 table_index,
/* Init the table handle */
- obj_desc->reference.opcode = AML_LOAD_OP;
+ obj_desc->reference.class = ACPI_REFCLASS_TABLE;
*ddb_handle = obj_desc;
/* Install the new table into the local data structures */
- obj_desc->reference.object = ACPI_CAST_PTR(void,
- (unsigned long)table_index);
+ obj_desc->reference.value = table_index;
/* Add the table to the namespace */
@@ -280,6 +278,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *ddb_handle;
+ struct acpi_table_header *table;
struct acpi_table_desc table_desc;
u32 table_index;
acpi_status status;
@@ -294,9 +293,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
- obj_desc,
- acpi_ut_get_object_type_name(obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Load table from Region %p\n", obj_desc));
/* Region must be system_memory (from ACPI spec) */
@@ -316,61 +314,112 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
}
/*
- * We will simply map the memory region for the table. However, the
- * memory region is technically not guaranteed to remain stable and
- * we may eventually have to copy the table to a local buffer.
+ * Map the table header and get the actual table length. The region
+ * length is not guaranteed to be the same as the table length.
+ */
+ table = acpi_os_map_memory(obj_desc->region.address,
+ sizeof(struct acpi_table_header));
+ if (!table) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ length = table->length;
+ acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+ /* Must have at least an ACPI table header */
+
+ if (length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
+ }
+
+ /*
+ * The memory region is not guaranteed to remain stable and we must
+ * copy the table to a local buffer. For example, the memory region
+ * is corrupted after suspend on some machines. Dynamically loaded
+ * tables are usually small, so this overhead is minimal.
*/
+
+ /* Allocate a buffer for the table */
+
+ table_desc.pointer = ACPI_ALLOCATE(length);
+ if (!table_desc.pointer) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Map the entire table and copy it */
+
+ table = acpi_os_map_memory(obj_desc->region.address, length);
+ if (!table) {
+ ACPI_FREE(table_desc.pointer);
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ ACPI_MEMCPY(table_desc.pointer, table, length);
+ acpi_os_unmap_memory(table, length);
+
table_desc.address = obj_desc->region.address;
- table_desc.length = obj_desc->region.length;
- table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
break;
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Load from Buffer or Field %p %s\n", obj_desc,
- acpi_ut_get_object_type_name(obj_desc)));
-
- length = obj_desc->buffer.length;
+ "Load table from Buffer or Field %p\n",
+ obj_desc));
/* Must have at least an ACPI table header */
- if (length < sizeof(struct acpi_table_header)) {
+ if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
- /* Validate checksum here. It won't get validated in tb_add_table */
+ /* Get the actual table length from the table header */
- status =
- acpi_tb_verify_checksum(ACPI_CAST_PTR
- (struct acpi_table_header,
- obj_desc->buffer.pointer), length);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ table =
+ ACPI_CAST_PTR(struct acpi_table_header,
+ obj_desc->buffer.pointer);
+ length = table->length;
+
+ /* Table cannot extend beyond the buffer */
+
+ if (length > obj_desc->buffer.length) {
+ return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
+ }
+ if (length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/*
- * We need to copy the buffer since the original buffer could be
- * changed or deleted in the future
+ * Copy the table from the buffer because the buffer could be modified
+ * or even deleted in the future
*/
table_desc.pointer = ACPI_ALLOCATE(length);
if (!table_desc.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer,
- length);
- table_desc.length = length;
- table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+ ACPI_MEMCPY(table_desc.pointer, table, length);
+ table_desc.address = ACPI_TO_INTEGER(table_desc.pointer);
break;
default:
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- /*
- * Install the new table into the local data structures
- */
+ /* Validate table checksum (will not get validated in tb_add_table) */
+
+ status = acpi_tb_verify_checksum(table_desc.pointer, length);
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(table_desc.pointer);
+ return_ACPI_STATUS(status);
+ }
+
+ /* Complete the table descriptor */
+
+ table_desc.length = length;
+ table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+
+ /* Install the new table into the local data structures */
+
status = acpi_tb_add_table(&table_desc, &table_index);
if (ACPI_FAILURE(status)) {
goto cleanup;
@@ -379,7 +428,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/*
* Add the table to the namespace.
*
- * Note: We load the table objects relative to the root of the namespace.
+ * Note: Load the table objects relative to the root of the namespace.
* This appears to go against the ACPI specification, but we do it for
* compatibility with other ACPI implementations.
*/
@@ -415,7 +464,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
cleanup:
if (ACPI_FAILURE(status)) {
- /* Delete allocated buffer or mapping */
+ /* Delete allocated table buffer */
acpi_tb_delete_table(&table_desc);
}
@@ -455,9 +504,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */
+ /* Get the table index from the ddb_handle */
- table_index = (u32) (acpi_size) table_desc->reference.object;
+ table_index = table_desc->reference.value;
/* Invoke table handler if present */
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index 261d97516d9..1d1f35adddd 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -57,7 +57,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
*
* FUNCTION: acpi_ex_convert_to_integer
*
- * PARAMETERS: obj_desc - Object to be converted. Must be an
+ * PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the new Integer object is returned
* Flags - Used for string conversion
@@ -103,7 +103,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
}
/*
- * Convert the buffer/string to an integer. Note that both buffers and
+ * Convert the buffer/string to an integer. Note that both buffers and
* strings are treated as raw data - we don't convert ascii to hex for
* strings.
*
@@ -120,7 +120,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
/*
* Convert string to an integer - for most cases, the string must be
- * hexadecimal as per the ACPI specification. The only exception (as
+ * hexadecimal as per the ACPI specification. The only exception (as
* of ACPI 3.0) is that the to_integer() operator allows both decimal
* and hexadecimal strings (hex prefixed with "0x").
*/
@@ -159,6 +159,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
break;
default:
+
/* No other types can get here */
break;
}
@@ -185,7 +186,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
*
* FUNCTION: acpi_ex_convert_to_buffer
*
- * PARAMETERS: obj_desc - Object to be converted. Must be an
+ * PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the new buffer object is returned
*
@@ -365,7 +366,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
}
/*
- * Since leading zeros are supressed, we must check for the case where
+ * Since leading zeros are suppressed, we must check for the case where
* the integer equals 0
*
* Finally, null terminate the string and return the length
@@ -383,7 +384,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
*
* FUNCTION: acpi_ex_convert_to_string
*
- * PARAMETERS: obj_desc - Object to be converted. Must be an
+ * PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the string object is returned
* Type - String flags (base and conversion type)
@@ -472,7 +473,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
base = 10;
/*
- * Calculate the final string length. Individual string values
+ * Calculate the final string length. Individual string values
* are variable length (include separator for each)
*/
for (i = 0; i < obj_desc->buffer.length; i++) {
@@ -511,9 +512,14 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
/*
* Create a new string object and string buffer
* (-1 because of extra separator included in string_length from above)
+ * Allow creation of zero-length strings from zero-length buffers.
*/
+ if (string_length) {
+ string_length--;
+ }
+
return_desc = acpi_ut_create_string_object((acpi_size)
- (string_length - 1));
+ string_length);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -536,7 +542,9 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
* Null terminate the string
* (overwrites final comma/space from above)
*/
- new_buf--;
+ if (obj_desc->buffer.length) {
+ new_buf--;
+ }
*new_buf = 0;
break;
@@ -617,7 +625,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
/*
- * These types require an Integer operand. We can convert
+ * These types require an Integer operand. We can convert
* a Buffer or a String to an Integer if necessary.
*/
status =
@@ -627,7 +635,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
case ACPI_TYPE_STRING:
/*
- * The operand must be a String. We can convert an
+ * The operand must be a String. We can convert an
* Integer or Buffer if necessary
*/
status =
@@ -637,7 +645,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
case ACPI_TYPE_BUFFER:
/*
- * The operand must be a Buffer. We can convert an
+ * The operand must be a Buffer. We can convert an
* Integer or String if necessary
*/
status =
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 2be2e2bf95b..d087a7d28aa 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -45,7 +45,6 @@
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exdump")
@@ -214,10 +213,11 @@ static struct acpi_exdump_info acpi_ex_dump_index_field[5] = {
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"}
};
-static struct acpi_exdump_info acpi_ex_dump_reference[7] = {
+static struct acpi_exdump_info acpi_ex_dump_reference[8] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"},
- {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"},
@@ -413,10 +413,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
case ACPI_EXD_REFERENCE:
- acpi_ex_out_string("Opcode",
- (acpi_ps_get_opcode_info
- (obj_desc->reference.opcode))->
- name);
+ acpi_ex_out_string("Class Name",
+ (char *)
+ acpi_ut_get_reference_name
+ (obj_desc));
acpi_ex_dump_reference_obj(obj_desc);
break;
@@ -494,40 +494,41 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
- switch (obj_desc->reference.opcode) {
- case AML_DEBUG_OP:
+ acpi_os_printf("Reference: [%s] ",
+ acpi_ut_get_reference_name(obj_desc));
+
+ switch (obj_desc->reference.class) {
+ case ACPI_REFCLASS_DEBUG:
- acpi_os_printf("Reference: Debug\n");
+ acpi_os_printf("\n");
break;
- case AML_INDEX_OP:
+ case ACPI_REFCLASS_INDEX:
- acpi_os_printf("Reference: Index %p\n",
- obj_desc->reference.object);
+ acpi_os_printf("%p\n", obj_desc->reference.object);
break;
- case AML_LOAD_OP:
+ case ACPI_REFCLASS_TABLE:
- acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n",
- obj_desc->reference.object);
+ acpi_os_printf("Table Index %X\n",
+ obj_desc->reference.value);
break;
- case AML_REF_OF_OP:
+ case ACPI_REFCLASS_REFOF:
- acpi_os_printf("Reference: (RefOf) %p [%s]\n",
- obj_desc->reference.object,
+ acpi_os_printf("%p [%s]\n", obj_desc->reference.object,
acpi_ut_get_type_name(((union
acpi_operand_object
- *)obj_desc->
+ *)
+ obj_desc->
reference.
object)->common.
type));
break;
- case AML_ARG_OP:
+ case ACPI_REFCLASS_ARG:
- acpi_os_printf("Reference: Arg%d",
- obj_desc->reference.offset);
+ acpi_os_printf("%X", obj_desc->reference.value);
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
@@ -542,10 +543,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
acpi_os_printf("\n");
break;
- case AML_LOCAL_OP:
+ case ACPI_REFCLASS_LOCAL:
- acpi_os_printf("Reference: Local%d",
- obj_desc->reference.offset);
+ acpi_os_printf("%X", obj_desc->reference.value);
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
@@ -560,21 +560,16 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
acpi_os_printf("\n");
break;
- case AML_INT_NAMEPATH_OP:
+ case ACPI_REFCLASS_NAME:
- acpi_os_printf("Reference: Namepath %X [%4.4s]\n",
- obj_desc->reference.node->name.integer,
+ acpi_os_printf("- [%4.4s]\n",
obj_desc->reference.node->name.ascii);
break;
- default:
-
- /* Unknown opcode */
+ default: /* Unknown reference class */
- acpi_os_printf("Unknown Reference opcode=%X\n",
- obj_desc->reference.opcode);
+ acpi_os_printf("%2.2X\n", obj_desc->reference.class);
break;
-
}
break;
@@ -865,8 +860,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
- acpi_os_printf(" Named Object %p ", obj_desc->reference.node);
+ if (obj_desc->reference.class == ACPI_REFCLASS_NAME) {
+ acpi_os_printf(" %p ", obj_desc->reference.node);
status =
acpi_ns_handle_to_pathname(obj_desc->reference.node,
@@ -882,14 +877,12 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf(" Target: %p",
obj_desc->reference.object);
- if (obj_desc->reference.opcode == AML_LOAD_OP) {
- /*
- * For DDBHandle reference,
- * obj_desc->Reference.Object is the table index
- */
- acpi_os_printf(" [DDBHandle]\n");
+ if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) {
+ acpi_os_printf(" Table Index: %X\n",
+ obj_desc->reference.value);
} else {
- acpi_os_printf(" [%s]\n",
+ acpi_os_printf(" Target: %p [%s]\n",
+ obj_desc->reference.object,
acpi_ut_get_type_name(((union
acpi_operand_object
*)
@@ -988,9 +981,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
case ACPI_TYPE_LOCAL_REFERENCE:
- acpi_os_printf("[Object Reference] %s",
- (acpi_ps_get_opcode_info
- (obj_desc->reference.opcode))->name);
+ acpi_os_printf("[Object Reference] Type [%s] %2.2X",
+ acpi_ut_get_reference_name(obj_desc),
+ obj_desc->reference.class);
acpi_ex_dump_reference_obj(obj_desc);
break;
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 731414a581a..efb19134005 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -86,10 +86,10 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
/*
* Must be a reference to a Local or Arg
*/
- switch (obj_desc->reference.opcode) {
- case AML_LOCAL_OP:
- case AML_ARG_OP:
- case AML_DEBUG_OP:
+ switch (obj_desc->reference.class) {
+ case ACPI_REFCLASS_LOCAL:
+ case ACPI_REFCLASS_ARG:
+ case ACPI_REFCLASS_DEBUG:
/* The referenced object is the pseudo-node for the local/arg */
@@ -98,8 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
default:
- ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
- obj_desc->reference.opcode));
+ ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X",
+ obj_desc->reference.class));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
break;
@@ -127,7 +127,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_NO_MEMORY);
}
- reference_obj->reference.opcode = AML_REF_OF_OP;
+ reference_obj->reference.class = ACPI_REFCLASS_REFOF;
reference_obj->reference.object = referenced_obj;
*return_desc = reference_obj;
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 7c3bea575e0..f622f9eac8a 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -825,16 +825,16 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
*
* Must resolve/dereference the local/arg reference first
*/
- switch (operand[0]->reference.opcode) {
- case AML_LOCAL_OP:
- case AML_ARG_OP:
+ switch (operand[0]->reference.class) {
+ case ACPI_REFCLASS_LOCAL:
+ case ACPI_REFCLASS_ARG:
/* Set Operand[0] to the value of the local/arg */
status =
acpi_ds_method_data_get_value
- (operand[0]->reference.opcode,
- operand[0]->reference.offset,
+ (operand[0]->reference.class,
+ operand[0]->reference.value,
walk_state, &temp_desc);
if (ACPI_FAILURE(status)) {
goto cleanup;
@@ -848,7 +848,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
operand[0] = temp_desc;
break;
- case AML_REF_OF_OP:
+ case ACPI_REFCLASS_REFOF:
/* Get the object to which the reference refers */
@@ -928,8 +928,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
* This must be a reference object produced by either the
* Index() or ref_of() operator
*/
- switch (operand[0]->reference.opcode) {
- case AML_INDEX_OP:
+ switch (operand[0]->reference.class) {
+ case ACPI_REFCLASS_INDEX:
/*
* The target type for the Index operator must be
@@ -965,7 +965,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
return_desc->integer.value =
temp_desc->buffer.
pointer[operand[0]->reference.
- offset];
+ value];
break;
case ACPI_TYPE_PACKAGE:
@@ -985,7 +985,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
default:
ACPI_ERROR((AE_INFO,
- "Unknown Index TargetType %X in obj %p",
+ "Unknown Index TargetType %X in reference object %p",
operand[0]->reference.
target_type, operand[0]));
status = AE_AML_OPERAND_TYPE;
@@ -993,7 +993,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
}
break;
- case AML_REF_OF_OP:
+ case ACPI_REFCLASS_REFOF:
return_desc = operand[0]->reference.object;
@@ -1013,9 +1013,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
default:
ACPI_ERROR((AE_INFO,
- "Unknown opcode in reference(%p) - %X",
+ "Unknown class in reference(%p) - %2.2X",
operand[0],
- operand[0]->reference.opcode));
+ operand[0]->reference.class));
status = AE_TYPE;
goto cleanup;
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 8e8bbb6cceb..368def5dffc 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -391,8 +391,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
/* Initialize the Index reference object */
index = operand[1]->integer.value;
- return_desc->reference.offset = (u32) index;
- return_desc->reference.opcode = AML_INDEX_OP;
+ return_desc->reference.value = (u32) index;
+ return_desc->reference.class = ACPI_REFCLASS_INDEX;
/*
* At this point, the Source operand is a String, Buffer, or Package.
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index 5596f42c967..423ad3635f3 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -46,8 +46,6 @@
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresnte")
@@ -238,10 +236,10 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_LOCAL_REFERENCE:
- switch (source_desc->reference.opcode) {
- case AML_LOAD_OP: /* This is a ddb_handle */
- case AML_REF_OF_OP:
- case AML_INDEX_OP:
+ switch (source_desc->reference.class) {
+ case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */
+ case ACPI_REFCLASS_REFOF:
+ case ACPI_REFCLASS_INDEX:
/* Return an additional reference to the object */
@@ -253,10 +251,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
/* No named references are allowed here */
ACPI_ERROR((AE_INFO,
- "Unsupported Reference opcode %X (%s)",
- source_desc->reference.opcode,
- acpi_ps_get_opcode_name(source_desc->
- reference.opcode)));
+ "Unsupported Reference type %X",
+ source_desc->reference.class));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index b35f7c817ac..89571b92a52 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -47,7 +47,6 @@
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresolv")
@@ -141,7 +140,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
acpi_status status = AE_OK;
union acpi_operand_object *stack_desc;
union acpi_operand_object *obj_desc = NULL;
- u16 opcode;
+ u8 ref_type;
ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
@@ -152,19 +151,19 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
- opcode = stack_desc->reference.opcode;
+ ref_type = stack_desc->reference.class;
- switch (opcode) {
- case AML_LOCAL_OP:
- case AML_ARG_OP:
+ switch (ref_type) {
+ case ACPI_REFCLASS_LOCAL:
+ case ACPI_REFCLASS_ARG:
/*
* Get the local from the method's state info
* Note: this increments the local's object reference count
*/
- status = acpi_ds_method_data_get_value(opcode,
+ status = acpi_ds_method_data_get_value(ref_type,
stack_desc->
- reference.offset,
+ reference.value,
walk_state,
&obj_desc);
if (ACPI_FAILURE(status)) {
@@ -173,7 +172,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"[Arg/Local %X] ValueObj is %p\n",
- stack_desc->reference.offset,
+ stack_desc->reference.value,
obj_desc));
/*
@@ -184,7 +183,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
*stack_ptr = obj_desc;
break;
- case AML_INDEX_OP:
+ case ACPI_REFCLASS_INDEX:
switch (stack_desc->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
@@ -239,15 +238,15 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
}
break;
- case AML_REF_OF_OP:
- case AML_DEBUG_OP:
- case AML_LOAD_OP:
+ case ACPI_REFCLASS_REFOF:
+ case ACPI_REFCLASS_DEBUG:
+ case ACPI_REFCLASS_TABLE:
/* Just leave the object as-is, do not dereference */
break;
- case AML_INT_NAMEPATH_OP: /* Reference to a named object */
+ case ACPI_REFCLASS_NAME: /* Reference to a named object */
/* Dereference the name */
@@ -273,8 +272,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
default:
ACPI_ERROR((AE_INFO,
- "Unknown Reference opcode %X (%s) in %p",
- opcode, acpi_ps_get_opcode_name(opcode),
+ "Unknown Reference type %X in %p", ref_type,
stack_desc));
status = AE_AML_INTERNAL;
break;
@@ -388,13 +386,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
* traversing the list of possibly many nested references.
*/
while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
- switch (obj_desc->reference.opcode) {
- case AML_REF_OF_OP:
- case AML_INT_NAMEPATH_OP:
+ switch (obj_desc->reference.class) {
+ case ACPI_REFCLASS_REFOF:
+ case ACPI_REFCLASS_NAME:
/* Dereference the reference pointer */
- if (obj_desc->reference.opcode == AML_REF_OF_OP) {
+ if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
node = obj_desc->reference.object;
} else { /* AML_INT_NAMEPATH_OP */
@@ -429,7 +427,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
}
break;
- case AML_INDEX_OP:
+ case ACPI_REFCLASS_INDEX:
/* Get the type of this reference (index into another object) */
@@ -455,22 +453,22 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
}
break;
- case AML_LOAD_OP:
+ case ACPI_REFCLASS_TABLE:
type = ACPI_TYPE_DDB_HANDLE;
goto exit;
- case AML_LOCAL_OP:
- case AML_ARG_OP:
+ case ACPI_REFCLASS_LOCAL:
+ case ACPI_REFCLASS_ARG:
if (return_desc) {
status =
acpi_ds_method_data_get_value(obj_desc->
reference.
- opcode,
+ class,
obj_desc->
reference.
- offset,
+ value,
walk_state,
&obj_desc);
if (ACPI_FAILURE(status)) {
@@ -481,10 +479,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
status =
acpi_ds_method_data_get_node(obj_desc->
reference.
- opcode,
+ class,
obj_desc->
reference.
- offset,
+ value,
walk_state,
&node);
if (ACPI_FAILURE(status)) {
@@ -499,7 +497,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
}
break;
- case AML_DEBUG_OP:
+ case ACPI_REFCLASS_DEBUG:
/* The Debug Object is of type "DebugObject" */
@@ -509,8 +507,8 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
default:
ACPI_ERROR((AE_INFO,
- "Unknown Reference subtype %X",
- obj_desc->reference.opcode));
+ "Unknown Reference Class %2.2X",
+ obj_desc->reference.class));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index 54085f16ec2..0bb82593da7 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -225,41 +225,36 @@ acpi_ex_resolve_operands(u16 opcode,
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
- /* Decode the Reference */
+ /* Validate the Reference */
- op_info = acpi_ps_get_opcode_info(opcode);
- if (op_info->class == AML_CLASS_UNKNOWN) {
- return_ACPI_STATUS(AE_AML_BAD_OPCODE);
- }
+ switch (obj_desc->reference.class) {
+ case ACPI_REFCLASS_DEBUG:
- switch (obj_desc->reference.opcode) {
- case AML_DEBUG_OP:
target_op = AML_DEBUG_OP;
/*lint -fallthrough */
- case AML_INDEX_OP:
- case AML_REF_OF_OP:
- case AML_ARG_OP:
- case AML_LOCAL_OP:
- case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
- case AML_INT_NAMEPATH_OP: /* Reference to a named object */
-
- ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT
- ((ACPI_DB_EXEC,
- "Operand is a Reference, RefOpcode [%s]\n",
- (acpi_ps_get_opcode_info
- (obj_desc->
- reference.
- opcode))->
- name)));
+ case ACPI_REFCLASS_ARG:
+ case ACPI_REFCLASS_LOCAL:
+ case ACPI_REFCLASS_INDEX:
+ case ACPI_REFCLASS_REFOF:
+ case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
+ case ACPI_REFCLASS_NAME: /* Reference to a named object */
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Operand is a Reference, Class [%s] %2.2X\n",
+ acpi_ut_get_reference_name
+ (obj_desc),
+ obj_desc->reference.
+ class));
break;
default:
+
ACPI_ERROR((AE_INFO,
- "Operand is a Reference, Unknown Reference Opcode: %X",
- obj_desc->reference.
- opcode));
+ "Unknown Reference Class %2.2X in %p",
+ obj_desc->reference.class,
+ obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -270,8 +265,7 @@ acpi_ex_resolve_operands(u16 opcode,
/* Invalid descriptor */
- ACPI_ERROR((AE_INFO,
- "Invalid descriptor %p [%s]",
+ ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]",
obj_desc,
acpi_ut_get_descriptor_name(obj_desc)));
@@ -343,7 +337,7 @@ acpi_ex_resolve_operands(u16 opcode,
if ((opcode == AML_STORE_OP) &&
(ACPI_GET_OBJECT_TYPE(*stack_ptr) ==
ACPI_TYPE_LOCAL_REFERENCE)
- && ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
+ && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) {
goto next_operand;
}
break;
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 38b55e35249..3318df4cbd9 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -47,7 +47,6 @@
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstore")
@@ -179,22 +178,26 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
case ACPI_TYPE_LOCAL_REFERENCE:
- if (source_desc->reference.opcode == AML_INDEX_OP) {
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
- "[%s, 0x%X]\n",
- acpi_ps_get_opcode_name
- (source_desc->reference.opcode),
- source_desc->reference.offset));
- } else {
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]",
- acpi_ps_get_opcode_name
- (source_desc->reference.opcode)));
- }
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ",
+ acpi_ut_get_reference_name(source_desc)));
+
+ /* Decode the reference */
+
+ switch (source_desc->reference.class) {
+ case ACPI_REFCLASS_INDEX:
+
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n",
+ source_desc->reference.value));
+ break;
+
+ case ACPI_REFCLASS_TABLE:
- if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
- " Table OwnerId %p\n",
- source_desc->reference.object));
+ "Table Index 0x%X\n",
+ source_desc->reference.value));
+ break;
+
+ default:
break;
}
@@ -347,15 +350,15 @@ acpi_ex_store(union acpi_operand_object *source_desc,
}
/*
- * Examine the Reference opcode. These cases are handled:
+ * Examine the Reference class. These cases are handled:
*
* 1) Store to Name (Change the object associated with a name)
* 2) Store to an indexed area of a Buffer or Package
* 3) Store to a Method Local or Arg
* 4) Store to the debug object
*/
- switch (ref_desc->reference.opcode) {
- case AML_REF_OF_OP:
+ switch (ref_desc->reference.class) {
+ case ACPI_REFCLASS_REFOF:
/* Storing an object into a Name "container" */
@@ -365,7 +368,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
ACPI_IMPLICIT_CONVERSION);
break;
- case AML_INDEX_OP:
+ case ACPI_REFCLASS_INDEX:
/* Storing to an Index (pointer into a packager or buffer) */
@@ -374,18 +377,18 @@ acpi_ex_store(union acpi_operand_object *source_desc,
walk_state);
break;
- case AML_LOCAL_OP:
- case AML_ARG_OP:
+ case ACPI_REFCLASS_LOCAL:
+ case ACPI_REFCLASS_ARG:
/* Store to a method local/arg */
status =
- acpi_ds_store_object_to_local(ref_desc->reference.opcode,
- ref_desc->reference.offset,
+ acpi_ds_store_object_to_local(ref_desc->reference.class,
+ ref_desc->reference.value,
source_desc, walk_state);
break;
- case AML_DEBUG_OP:
+ case ACPI_REFCLASS_DEBUG:
/*
* Storing to the Debug object causes the value stored to be
@@ -401,9 +404,9 @@ acpi_ex_store(union acpi_operand_object *source_desc,
default:
- ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
- ref_desc->reference.opcode));
- ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR);
+ ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X",
+ ref_desc->reference.class));
+ ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);
status = AE_AML_INTERNAL;
break;
@@ -458,7 +461,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
if (ACPI_GET_OBJECT_TYPE(source_desc) ==
ACPI_TYPE_LOCAL_REFERENCE
- && source_desc->reference.opcode == AML_LOAD_OP) {
+ && source_desc->reference.class == ACPI_REFCLASS_TABLE) {
/* This is a DDBHandle, just add a reference to it */
@@ -553,7 +556,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
/* Store the source value into the target buffer byte */
- obj_desc->buffer.pointer[index_desc->reference.offset] = value;
+ obj_desc->buffer.pointer[index_desc->reference.value] = value;
break;
default:
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index a6d2168b81f..eef61a00803 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -121,7 +121,8 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
(ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) &&
!((ACPI_GET_OBJECT_TYPE(source_desc) ==
ACPI_TYPE_LOCAL_REFERENCE)
- && (source_desc->reference.opcode == AML_LOAD_OP))) {
+ && (source_desc->reference.class ==
+ ACPI_REFCLASS_TABLE))) {
/* Conversion successful but still not a valid type */
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 2655bc1b4ee..60d54d1f6b1 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -265,7 +265,7 @@ static int acpi_fan_add(struct acpi_device *device)
dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
- acpi_driver_data(device) = cdev;
+ device->driver_data = cdev;
result = sysfs_create_link(&device->dev.kobj,
&cdev->device.kobj,
"thermal_cooling");
@@ -327,8 +327,8 @@ static int acpi_fan_resume(struct acpi_device *device)
result = acpi_bus_get_power(device->handle, &power_state);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading fan power state\n"));
+ printk(KERN_ERR PREFIX
+ "Error reading fan power state\n");
return result;
}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index dba3cfbe8cb..25dccdf179b 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
return_ACPI_STATUS(status);
}
- /* Set the vector */
+ /*
+ * According to the ACPI specification 2.0c and later, the 64-bit
+ * waking vector should be cleared and the 32-bit waking vector should
+ * be used, unless we want the wake-up code to be called by the BIOS in
+ * Protected Mode. Some systems (for example HP dv5-1004nr) are known
+ * to fail to resume if the 64-bit vector is used.
+ */
+ if (facs->version >= 1)
+ facs->xfirmware_waking_vector = 0;
- if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
- /*
- * ACPI 1.0 FACS or short table or optional X_ field is zero
- */
- facs->firmware_waking_vector = (u32) physical_address;
- } else {
- /*
- * ACPI 2.0 FACS with valid X_ field
- */
- facs->xfirmware_waking_vector = physical_address;
- }
+ facs->firmware_waking_vector = (u32)physical_address;
return_ACPI_STATUS(AE_OK);
}
@@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
}
/* Get the vector */
-
- if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
- /*
- * ACPI 1.0 FACS or short table or optional X_ field is zero
- */
- *physical_address =
- (acpi_physical_address) facs->firmware_waking_vector;
- } else {
- /*
- * ACPI 2.0 FACS with valid X_ field
- */
- *physical_address =
- (acpi_physical_address) facs->xfirmware_waking_vector;
- }
+ *physical_address = (acpi_physical_address)facs->firmware_waking_vector;
return_ACPI_STATUS(AE_OK);
}
@@ -627,6 +612,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
}
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
+ /*
+ * Some BIOSes assume that WAK_STS will be cleared on resume and use
+ * it to determine whether the system is rebooting or resuming. Clear
+ * it for compatibility.
+ */
+ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);
+
acpi_gbl_system_awake_and_running = TRUE;
/* Enable power button */
diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile
index 3f63d364069..371a2daf837 100644
--- a/drivers/acpi/namespace/Makefile
+++ b/drivers/acpi/namespace/Makefile
@@ -5,7 +5,7 @@
obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
- nsparse.o
+ nsparse.o nspredef.o
obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index 0ab22004728..cc0ae39440e 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -43,7 +43,6 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsdump")
@@ -334,9 +333,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[%s]\n",
- acpi_ps_get_opcode_name(obj_desc->
- reference.
- opcode));
+ acpi_ut_get_reference_name(obj_desc));
break;
case ACPI_TYPE_BUFFER_FIELD:
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index d369164e00b..4cdf03ac2b4 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -78,6 +78,7 @@ ACPI_MODULE_NAME("nseval")
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
{
acpi_status status;
+ struct acpi_namespace_node *node;
ACPI_FUNCTION_TRACE(ns_evaluate);
@@ -117,6 +118,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
info->resolved_node,
acpi_ns_get_attached_object(info->resolved_node)));
+ node = info->resolved_node;
+
/*
* Two major cases here:
*
@@ -148,21 +151,22 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
info->param_count++;
}
- /* Error if too few arguments were passed in */
+ /*
+ * Warning if too few or too many arguments have been passed by the
+ * caller. We don't want to abort here with an error because an
+ * incorrect number of arguments may not cause the method to fail.
+ * However, the method will fail if there are too few arguments passed
+ * and the method attempts to use one of the missing ones.
+ */
if (info->param_count < info->obj_desc->method.param_count) {
- ACPI_ERROR((AE_INFO,
+ ACPI_WARNING((AE_INFO,
"Insufficient arguments - "
"method [%4.4s] needs %d, found %d",
acpi_ut_get_node_name(info->resolved_node),
info->obj_desc->method.param_count,
info->param_count));
- return_ACPI_STATUS(AE_MISSING_ARGUMENTS);
- }
-
- /* Just a warning if too many arguments */
-
- else if (info->param_count >
+ } else if (info->param_count >
info->obj_desc->method.param_count) {
ACPI_WARNING((AE_INFO,
"Excess arguments - "
@@ -195,7 +199,28 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
} else {
/*
* 2) Object is not a method, return its current value
+ *
+ * Disallow certain object types. For these, "evaluation" is undefined.
*/
+ switch (info->resolved_node->type) {
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_EVENT:
+ case ACPI_TYPE_MUTEX:
+ case ACPI_TYPE_REGION:
+ case ACPI_TYPE_THERMAL:
+ case ACPI_TYPE_LOCAL_SCOPE:
+
+ ACPI_ERROR((AE_INFO,
+ "[%4.4s] Evaluation of object type [%s] is not supported",
+ info->resolved_node->name.ascii,
+ acpi_ut_get_type_name(info->resolved_node->
+ type)));
+
+ return_ACPI_STATUS(AE_TYPE);
+
+ default:
+ break;
+ }
/*
* Objects require additional resolution steps (e.g., the Node may be
@@ -239,9 +264,35 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
}
}
- /*
- * Check if there is a return value that must be dealt with
- */
+ /* Validation of return values for ACPI-predefined methods and objects */
+
+ if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) {
+ /*
+ * If this is the first evaluation, check the return value. This
+ * ensures that any warnings will only be emitted during the very
+ * first evaluation of the object.
+ */
+ if (!(node->flags & ANOBJ_EVALUATED)) {
+ /*
+ * Check for a predefined ACPI name. If found, validate the
+ * returned object.
+ *
+ * Note: Ignore return status for now, emit warnings if there are
+ * problems with the returned object. May change later to abort
+ * the method on invalid return object.
+ */
+ (void)acpi_ns_check_predefined_names(node,
+ info->
+ return_object);
+ }
+
+ /* Mark the node as having been evaluated */
+
+ node->flags |= ANOBJ_EVALUATED;
+ }
+
+ /* Check if there is a return value that must be dealt with */
+
if (status == AE_CTRL_RETURN_VALUE) {
/* If caller does not want the return value, delete it */
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index bd577387800..42a39a7c96e 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -115,7 +115,6 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
return (AE_OK);
}
-#ifdef ACPI_DEBUG_OUTPUT
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_external_pathname
@@ -142,7 +141,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
size = acpi_ns_get_pathname_length(node);
if (!size) {
- return (NULL);
+ return_PTR(NULL);
}
/* Allocate a buffer to be returned to caller */
@@ -157,12 +156,12 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
status = acpi_ns_build_external_path(node, size, name_buffer);
if (ACPI_FAILURE(status)) {
- return (NULL);
+ ACPI_FREE(name_buffer);
+ return_PTR(NULL);
}
return_PTR(name_buffer);
}
-#endif
/*******************************************************************************
*
diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c
new file mode 100644
index 00000000000..0f17cf0898c
--- /dev/null
+++ b/drivers/acpi/namespace/nspredef.c
@@ -0,0 +1,900 @@
+/******************************************************************************
+ *
+ * Module Name: nspredef - Validation of ACPI predefined methods and objects
+ * $Revision: 1.1 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acpredef.h>
+
+#define _COMPONENT ACPI_NAMESPACE
+ACPI_MODULE_NAME("nspredef")
+
+/*******************************************************************************
+ *
+ * This module validates predefined ACPI objects that appear in the namespace,
+ * at the time they are evaluated (via acpi_evaluate_object). The purpose of this
+ * validation is to detect problems with BIOS-exposed predefined ACPI objects
+ * before the results are returned to the ACPI-related drivers.
+ *
+ * There are several areas that are validated:
+ *
+ * 1) The number of input arguments as defined by the method/object in the
+ * ASL is validated against the ACPI specification.
+ * 2) The type of the return object (if any) is validated against the ACPI
+ * specification.
+ * 3) For returned package objects, the count of package elements is
+ * validated, as well as the type of each package element. Nested
+ * packages are supported.
+ *
+ * For any problems found, a warning message is issued.
+ *
+ ******************************************************************************/
+/* Local prototypes */
+static acpi_status
+acpi_ns_check_package(char *pathname,
+ union acpi_operand_object *return_object,
+ const union acpi_predefined_info *predefined);
+
+static acpi_status
+acpi_ns_check_package_elements(char *pathname,
+ union acpi_operand_object **elements,
+ u8 type1, u32 count1, u8 type2, u32 count2);
+
+static acpi_status
+acpi_ns_check_object_type(char *pathname,
+ union acpi_operand_object *return_object,
+ u32 expected_btypes, u32 package_index);
+
+static acpi_status
+acpi_ns_check_reference(char *pathname,
+ union acpi_operand_object *return_object);
+
+/*
+ * Names for the types that can be returned by the predefined objects.
+ * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
+ */
+static const char *acpi_rtype_names[] = {
+ "/Integer",
+ "/String",
+ "/Buffer",
+ "/Package",
+ "/Reference",
+};
+
+#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_predefined_names
+ *
+ * PARAMETERS: Node - Namespace node for the method/object
+ * return_object - Object returned from the evaluation of this
+ * method/object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check an ACPI name for a match in the predefined name list.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
+ union acpi_operand_object *return_object)
+{
+ acpi_status status = AE_OK;
+ const union acpi_predefined_info *predefined;
+ char *pathname;
+
+ /* Match the name for this method/object against the predefined list */
+
+ predefined = acpi_ns_check_for_predefined_name(node);
+ if (!predefined) {
+
+ /* Name was not one of the predefined names */
+
+ return (AE_OK);
+ }
+
+ /* Get the full pathname to the object, for use in error messages */
+
+ pathname = acpi_ns_get_external_pathname(node);
+ if (!pathname) {
+ pathname = ACPI_CAST_PTR(char, predefined->info.name);
+ }
+
+ /*
+ * Check that the parameter count for this method is in accordance
+ * with the ACPI specification.
+ */
+ acpi_ns_check_parameter_count(pathname, node, predefined);
+
+ /*
+ * If there is no return value, check if we require a return value for
+ * this predefined name. Either one return value is expected, or none,
+ * for both methods and other objects.
+ *
+ * Exit now if there is no return object. Warning if one was expected.
+ */
+ if (!return_object) {
+ if ((predefined->info.expected_btypes) &&
+ (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) {
+ ACPI_ERROR((AE_INFO,
+ "%s: Missing expected return value",
+ pathname));
+
+ status = AE_AML_NO_RETURN_VALUE;
+ }
+ goto exit;
+ }
+
+ /*
+ * We have a return value, but if one wasn't expected, just exit, this is
+ * not a problem
+ *
+ * For example, if "Implicit return value" is enabled, methods will
+ * always return a value
+ */
+ if (!predefined->info.expected_btypes) {
+ goto exit;
+ }
+
+ /*
+ * Check that the type of the return object is what is expected for
+ * this predefined name
+ */
+ status = acpi_ns_check_object_type(pathname, return_object,
+ predefined->info.expected_btypes,
+ ACPI_NOT_PACKAGE);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* For returned Package objects, check the type of all sub-objects */
+
+ if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) {
+ status =
+ acpi_ns_check_package(pathname, return_object, predefined);
+ }
+
+ exit:
+ if (pathname) {
+ ACPI_FREE(pathname);
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_parameter_count
+ *
+ * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
+ * Node - Namespace node for the method/object
+ * Predefined - Pointer to entry in predefined name table
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a
+ * predefined name is what is expected (i.e., what is defined in
+ * the ACPI specification for this predefined name.)
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_check_parameter_count(char *pathname,
+ struct acpi_namespace_node *node,
+ const union acpi_predefined_info *predefined)
+{
+ u32 param_count;
+ u32 required_params_current;
+ u32 required_params_old;
+
+ /*
+ * Check that the ASL-defined parameter count is what is expected for
+ * this predefined name.
+ *
+ * Methods have 0-7 parameters. All other types have zero.
+ */
+ param_count = 0;
+ if (node->type == ACPI_TYPE_METHOD) {
+ param_count = node->object->method.param_count;
+ }
+
+ /* Validate parameter count - allow two different legal counts (_SCP) */
+
+ required_params_current = predefined->info.param_count & 0x0F;
+ required_params_old = predefined->info.param_count >> 4;
+
+ if ((param_count != required_params_current) &&
+ (param_count != required_params_old)) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Parameter count mismatch - ASL declared %d, expected %d",
+ pathname, param_count, required_params_current));
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_for_predefined_name
+ *
+ * PARAMETERS: Node - Namespace node for the method/object
+ *
+ * RETURN: Pointer to entry in predefined table. NULL indicates not found.
+ *
+ * DESCRIPTION: Check an object name against the predefined object list.
+ *
+ ******************************************************************************/
+
+const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
+ acpi_namespace_node
+ *node)
+{
+ const union acpi_predefined_info *this_name;
+
+ /* Quick check for a predefined name, first character must be underscore */
+
+ if (node->name.ascii[0] != '_') {
+ return (NULL);
+ }
+
+ /* Search info table for a predefined method/object name */
+
+ this_name = predefined_names;
+ while (this_name->info.name[0]) {
+ if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) {
+
+ /* Return pointer to this table entry */
+
+ return (this_name);
+ }
+
+ /*
+ * Skip next entry in the table if this name returns a Package
+ * (next entry contains the package info)
+ */
+ if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) {
+ this_name++;
+ }
+
+ this_name++;
+ }
+
+ return (NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_package
+ *
+ * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
+ * return_object - Object returned from the evaluation of a
+ * method or object
+ * Predefined - Pointer to entry in predefined name table
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check a returned package object for the correct count and
+ * correct type of all sub-objects.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_check_package(char *pathname,
+ union acpi_operand_object *return_object,
+ const union acpi_predefined_info *predefined)
+{
+ const union acpi_predefined_info *package;
+ union acpi_operand_object *sub_package;
+ union acpi_operand_object **elements;
+ union acpi_operand_object **sub_elements;
+ acpi_status status;
+ u32 expected_count;
+ u32 count;
+ u32 i;
+ u32 j;
+
+ ACPI_FUNCTION_NAME(ns_check_package);
+
+ /* The package info for this name is in the next table entry */
+
+ package = predefined + 1;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "%s Validating return Package of Type %X, Count %X\n",
+ pathname, package->ret_info.type,
+ return_object->package.count));
+
+ /* Extract package count and elements array */
+
+ elements = return_object->package.elements;
+ count = return_object->package.count;
+
+ /* The package must have at least one element, else invalid */
+
+ if (!count) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Return Package has no elements (empty)",
+ pathname));
+
+ return (AE_AML_OPERAND_VALUE);
+ }
+
+ /*
+ * Decode the type of the expected package contents
+ *
+ * PTYPE1 packages contain no subpackages
+ * PTYPE2 packages contain sub-packages
+ */
+ switch (package->ret_info.type) {
+ case ACPI_PTYPE1_FIXED:
+
+ /*
+ * The package count is fixed and there are no sub-packages
+ *
+ * If package is too small, exit.
+ * If package is larger than expected, issue warning but continue
+ */
+ expected_count =
+ package->ret_info.count1 + package->ret_info.count2;
+ if (count < expected_count) {
+ goto package_too_small;
+ } else if (count > expected_count) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Return Package is larger than needed - "
+ "found %u, expected %u", pathname, count,
+ expected_count));
+ }
+
+ /* Validate all elements of the returned package */
+
+ status = acpi_ns_check_package_elements(pathname, elements,
+ package->ret_info.
+ object_type1,
+ package->ret_info.
+ count1,
+ package->ret_info.
+ object_type2,
+ package->ret_info.
+ count2);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
+ case ACPI_PTYPE1_VAR:
+
+ /*
+ * The package count is variable, there are no sub-packages, and all
+ * elements must be of the same type
+ */
+ for (i = 0; i < count; i++) {
+ status = acpi_ns_check_object_type(pathname, *elements,
+ package->ret_info.
+ object_type1, i);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ elements++;
+ }
+ break;
+
+ case ACPI_PTYPE1_OPTION:
+
+ /*
+ * The package count is variable, there are no sub-packages. There are
+ * a fixed number of required elements, and a variable number of
+ * optional elements.
+ *
+ * Check if package is at least as large as the minimum required
+ */
+ expected_count = package->ret_info3.count;
+ if (count < expected_count) {
+ goto package_too_small;
+ }
+
+ /* Variable number of sub-objects */
+
+ for (i = 0; i < count; i++) {
+ if (i < package->ret_info3.count) {
+
+ /* These are the required package elements (0, 1, or 2) */
+
+ status =
+ acpi_ns_check_object_type(pathname,
+ *elements,
+ package->
+ ret_info3.
+ object_type[i],
+ i);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ } else {
+ /* These are the optional package elements */
+
+ status =
+ acpi_ns_check_object_type(pathname,
+ *elements,
+ package->
+ ret_info3.
+ tail_object_type,
+ i);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+ elements++;
+ }
+ break;
+
+ case ACPI_PTYPE2_PKG_COUNT:
+
+ /* First element is the (Integer) count of sub-packages to follow */
+
+ status = acpi_ns_check_object_type(pathname, *elements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /*
+ * Count cannot be larger than the parent package length, but allow it
+ * to be smaller. The >= accounts for the Integer above.
+ */
+ expected_count = (u32) (*elements)->integer.value;
+ if (expected_count >= count) {
+ goto package_too_small;
+ }
+
+ count = expected_count;
+ elements++;
+
+ /* Now we can walk the sub-packages */
+
+ /*lint -fallthrough */
+
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_FIXED:
+ case ACPI_PTYPE2_MIN:
+ case ACPI_PTYPE2_COUNT:
+
+ /*
+ * These types all return a single package that consists of a variable
+ * number of sub-packages
+ */
+ for (i = 0; i < count; i++) {
+ sub_package = *elements;
+ sub_elements = sub_package->package.elements;
+
+ /* Each sub-object must be of type Package */
+
+ status =
+ acpi_ns_check_object_type(pathname, sub_package,
+ ACPI_RTYPE_PACKAGE, i);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Examine the different types of sub-packages */
+
+ switch (package->ret_info.type) {
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_PKG_COUNT:
+
+ /* Each subpackage has a fixed number of elements */
+
+ expected_count =
+ package->ret_info.count1 +
+ package->ret_info.count2;
+ if (sub_package->package.count !=
+ expected_count) {
+ count = sub_package->package.count;
+ goto package_too_small;
+ }
+
+ status =
+ acpi_ns_check_package_elements(pathname,
+ sub_elements,
+ package->
+ ret_info.
+ object_type1,
+ package->
+ ret_info.
+ count1,
+ package->
+ ret_info.
+ object_type2,
+ package->
+ ret_info.
+ count2);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
+ case ACPI_PTYPE2_FIXED:
+
+ /* Each sub-package has a fixed length */
+
+ expected_count = package->ret_info2.count;
+ if (sub_package->package.count < expected_count) {
+ count = sub_package->package.count;
+ goto package_too_small;
+ }
+
+ /* Check the type of each sub-package element */
+
+ for (j = 0; j < expected_count; j++) {
+ status =
+ acpi_ns_check_object_type(pathname,
+ sub_elements
+ [j],
+ package->
+ ret_info2.
+ object_type
+ [j], j);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+ break;
+
+ case ACPI_PTYPE2_MIN:
+
+ /* Each sub-package has a variable but minimum length */
+
+ expected_count = package->ret_info.count1;
+ if (sub_package->package.count < expected_count) {
+ count = sub_package->package.count;
+ goto package_too_small;
+ }
+
+ /* Check the type of each sub-package element */
+
+ status =
+ acpi_ns_check_package_elements(pathname,
+ sub_elements,
+ package->
+ ret_info.
+ object_type1,
+ sub_package->
+ package.
+ count, 0, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
+ case ACPI_PTYPE2_COUNT:
+
+ /* First element is the (Integer) count of elements to follow */
+
+ status =
+ acpi_ns_check_object_type(pathname,
+ *sub_elements,
+ ACPI_RTYPE_INTEGER,
+ 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Make sure package is large enough for the Count */
+
+ expected_count =
+ (u32) (*sub_elements)->integer.value;
+ if (sub_package->package.count < expected_count) {
+ count = sub_package->package.count;
+ goto package_too_small;
+ }
+
+ /* Check the type of each sub-package element */
+
+ status =
+ acpi_ns_check_package_elements(pathname,
+ (sub_elements
+ + 1),
+ package->
+ ret_info.
+ object_type1,
+ (expected_count
+ - 1), 0, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ elements++;
+ }
+ break;
+
+ default:
+
+ /* Should not get here if predefined info table is correct */
+
+ ACPI_WARNING((AE_INFO,
+ "%s: Invalid internal return type in table entry: %X",
+ pathname, package->ret_info.type));
+
+ return (AE_AML_INTERNAL);
+ }
+
+ return (AE_OK);
+
+ package_too_small:
+
+ /* Error exit for the case with an incorrect package count */
+
+ ACPI_WARNING((AE_INFO, "%s: Return Package is too small - "
+ "found %u, expected %u", pathname, count,
+ expected_count));
+
+ return (AE_AML_OPERAND_VALUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_package_elements
+ *
+ * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
+ * Elements - Pointer to the package elements array
+ * Type1 - Object type for first group
+ * Count1 - Count for first group
+ * Type2 - Object type for second group
+ * Count2 - Count for second group
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check that all elements of a package are of the correct object
+ * type. Supports up to two groups of different object types.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_check_package_elements(char *pathname,
+ union acpi_operand_object **elements,
+ u8 type1, u32 count1, u8 type2, u32 count2)
+{
+ union acpi_operand_object **this_element = elements;
+ acpi_status status;
+ u32 i;
+
+ /*
+ * Up to two groups of package elements are supported by the data
+ * structure. All elements in each group must be of the same type.
+ * The second group can have a count of zero.
+ */
+ for (i = 0; i < count1; i++) {
+ status = acpi_ns_check_object_type(pathname, *this_element,
+ type1, i);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ this_element++;
+ }
+
+ for (i = 0; i < count2; i++) {
+ status = acpi_ns_check_object_type(pathname, *this_element,
+ type2, (i + count1));
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ this_element++;
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_object_type
+ *
+ * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
+ * return_object - Object return from the execution of this
+ * method/object
+ * expected_btypes - Bitmap of expected return type(s)
+ * package_index - Index of object within parent package (if
+ * applicable - ACPI_NOT_PACKAGE otherwise)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check the type of the return object against the expected object
+ * type(s). Use of Btype allows multiple expected object types.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_check_object_type(char *pathname,
+ union acpi_operand_object *return_object,
+ u32 expected_btypes, u32 package_index)
+{
+ acpi_status status = AE_OK;
+ u32 return_btype;
+ char type_buffer[48]; /* Room for 5 types */
+ u32 this_rtype;
+ u32 i;
+ u32 j;
+
+ /*
+ * If we get a NULL return_object here, it is a NULL package element,
+ * and this is always an error.
+ */
+ if (!return_object) {
+ goto type_error_exit;
+ }
+
+ /* A Namespace node should not get here, but make sure */
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Invalid return type - Found a Namespace node [%4.4s] type %s",
+ pathname, return_object->node.name.ascii,
+ acpi_ut_get_type_name(return_object->node.type)));
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ /*
+ * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
+ * The bitmapped type allows multiple possible return types.
+ *
+ * Note, the cases below must handle all of the possible types returned
+ * from all of the predefined names (including elements of returned
+ * packages)
+ */
+ switch (ACPI_GET_OBJECT_TYPE(return_object)) {
+ case ACPI_TYPE_INTEGER:
+ return_btype = ACPI_RTYPE_INTEGER;
+ break;
+
+ case ACPI_TYPE_BUFFER:
+ return_btype = ACPI_RTYPE_BUFFER;
+ break;
+
+ case ACPI_TYPE_STRING:
+ return_btype = ACPI_RTYPE_STRING;
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+ return_btype = ACPI_RTYPE_PACKAGE;
+ break;
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ return_btype = ACPI_RTYPE_REFERENCE;
+ break;
+
+ default:
+ /* Not one of the supported objects, must be incorrect */
+
+ goto type_error_exit;
+ }
+
+ /* Is the object one of the expected types? */
+
+ if (!(return_btype & expected_btypes)) {
+ goto type_error_exit;
+ }
+
+ /* For reference objects, check that the reference type is correct */
+
+ if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) {
+ status = acpi_ns_check_reference(pathname, return_object);
+ }
+
+ return (status);
+
+ type_error_exit:
+
+ /* Create a string with all expected types for this predefined object */
+
+ j = 1;
+ type_buffer[0] = 0;
+ this_rtype = ACPI_RTYPE_INTEGER;
+
+ for (i = 0; i < ACPI_NUM_RTYPES; i++) {
+
+ /* If one of the expected types, concatenate the name of this type */
+
+ if (expected_btypes & this_rtype) {
+ ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]);
+ j = 0; /* Use name separator from now on */
+ }
+ this_rtype <<= 1; /* Next Rtype */
+ }
+
+ if (package_index == ACPI_NOT_PACKAGE) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Return type mismatch - found %s, expected %s",
+ pathname,
+ acpi_ut_get_object_type_name(return_object),
+ type_buffer));
+ } else {
+ ACPI_WARNING((AE_INFO,
+ "%s: Return Package type mismatch at index %u - "
+ "found %s, expected %s", pathname, package_index,
+ acpi_ut_get_object_type_name(return_object),
+ type_buffer));
+ }
+
+ return (AE_AML_OPERAND_TYPE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_check_reference
+ *
+ * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
+ * return_object - Object returned from the evaluation of a
+ * method or object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check a returned reference object for the correct reference
+ * type. The only reference type that can be returned from a
+ * predefined method is a named reference. All others are invalid.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_check_reference(char *pathname,
+ union acpi_operand_object *return_object)
+{
+
+ /*
+ * Check the reference object for the correct reference type (opcode).
+ * The only type of reference that can be converted to an union acpi_object is
+ * a reference to a named object (reference class: NAME)
+ */
+ if (return_object->reference.class == ACPI_REFCLASS_NAME) {
+ return (AE_OK);
+ }
+
+ ACPI_WARNING((AE_INFO,
+ "%s: Return type mismatch - unexpected reference object type [%s] %2.2X",
+ pathname, acpi_ut_get_reference_name(return_object),
+ return_object->reference.class));
+
+ return (AE_AML_OPERAND_TYPE);
+}
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index 8399276cba1..a9a80bf811b 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -331,7 +331,7 @@ acpi_ns_search_and_enter(u32 target_name,
"Found bad character(s) in name, repaired: [%4.4s]\n",
ACPI_CAST_PTR(char, &target_name)));
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found bad character(s) in name, repaired: [%4.4s]\n",
ACPI_CAST_PTR(char, &target_name)));
}
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 38be5865d95..a085cc39c05 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -48,6 +48,10 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfeval")
+
+/* Local prototypes */
+static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
+
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -69,6 +73,7 @@ ACPI_MODULE_NAME("nsxfeval")
* be valid (non-null)
*
******************************************************************************/
+
acpi_status
acpi_evaluate_object_typed(acpi_handle handle,
acpi_string pathname,
@@ -283,6 +288,10 @@ acpi_evaluate_object(acpi_handle handle,
if (ACPI_SUCCESS(status)) {
+ /* Dereference Index and ref_of references */
+
+ acpi_ns_resolve_references(info);
+
/* Get the size of the returned object */
status =
@@ -352,6 +361,74 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
/*******************************************************************************
*
+ * FUNCTION: acpi_ns_resolve_references
+ *
+ * PARAMETERS: Info - Evaluation info block
+ *
+ * RETURN: Info->return_object is replaced with the dereferenced object
+ *
+ * DESCRIPTION: Dereference certain reference objects. Called before an
+ * internal return object is converted to an external union acpi_object.
+ *
+ * Performs an automatic dereference of Index and ref_of reference objects.
+ * These reference objects are not supported by the union acpi_object, so this is a
+ * last resort effort to return something useful. Also, provides compatibility
+ * with other ACPI implementations.
+ *
+ * NOTE: does not handle references within returned package objects or nested
+ * references, but this support could be added later if found to be necessary.
+ *
+ ******************************************************************************/
+static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
+{
+ union acpi_operand_object *obj_desc = NULL;
+ struct acpi_namespace_node *node;
+
+ /* We are interested in reference objects only */
+
+ if (ACPI_GET_OBJECT_TYPE(info->return_object) !=
+ ACPI_TYPE_LOCAL_REFERENCE) {
+ return;
+ }
+
+ /*
+ * Two types of references are supported - those created by Index and
+ * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
+ * to an union acpi_object, so it is not dereferenced here. A ddb_handle
+ * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
+ * an union acpi_object.
+ */
+ switch (info->return_object->reference.class) {
+ case ACPI_REFCLASS_INDEX:
+
+ obj_desc = *(info->return_object->reference.where);
+ break;
+
+ case ACPI_REFCLASS_REFOF:
+
+ node = info->return_object->reference.object;
+ if (node) {
+ obj_desc = node->object;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* Replace the existing reference object */
+
+ if (obj_desc) {
+ acpi_ut_add_reference(obj_desc);
+ acpi_ut_remove_reference(info->return_object);
+ info->return_object = obj_desc;
+ }
+
+ return;
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_walk_namespace
*
* PARAMETERS: Type - acpi_object_type to search for
@@ -379,6 +456,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
* function, etc.
*
******************************************************************************/
+
acpi_status
acpi_walk_namespace(acpi_object_type type,
acpi_handle start_object,
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index a287ed550f5..5efa4e7ddb0 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -253,6 +253,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
node = acpi_ns_map_handle_to_node(handle);
if (!node) {
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ status = AE_BAD_PARAMETER;
goto cleanup;
}
@@ -264,6 +265,10 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
info->name = node->name.integer;
info->valid = 0;
+ if (node->type == ACPI_TYPE_METHOD) {
+ info->param_count = node->object->method.param_count;
+ }
+
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto cleanup;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index cb9864e39ba..25ceae9191e 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -258,7 +258,7 @@ int __init acpi_numa_init(void)
int acpi_get_pxm(acpi_handle h)
{
- unsigned long pxm;
+ unsigned long long pxm;
acpi_status status;
acpi_handle handle;
acpi_handle phandle = h;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 235a1386888..4be252145cb 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -608,7 +608,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
acpi_handle handle;
struct acpi_pci_id *pci_id = *id;
acpi_status status;
- unsigned long temp;
+ unsigned long long temp;
acpi_object_type type;
acpi_get_parent(chandle, &handle);
@@ -620,8 +620,7 @@ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
return;
- status =
- acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
+ status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
&temp);
if (ACPI_SUCCESS(status)) {
u32 val;
@@ -682,6 +681,22 @@ static void acpi_os_execute_deferred(struct work_struct *work)
return;
}
+static void acpi_os_execute_hp_deferred(struct work_struct *work)
+{
+ struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
+ if (!dpc) {
+ printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
+ return;
+ }
+
+ acpi_os_wait_events_complete(NULL);
+
+ dpc->function(dpc->context);
+ kfree(dpc);
+
+ return;
+}
+
/*******************************************************************************
*
* FUNCTION: acpi_os_execute
@@ -697,12 +712,13 @@ static void acpi_os_execute_deferred(struct work_struct *work)
*
******************************************************************************/
-acpi_status acpi_os_execute(acpi_execute_type type,
- acpi_osd_exec_callback function, void *context)
+static acpi_status __acpi_os_execute(acpi_execute_type type,
+ acpi_osd_exec_callback function, void *context, int hp)
{
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct workqueue_struct *queue;
+ int ret;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
@@ -726,19 +742,38 @@ acpi_status acpi_os_execute(acpi_execute_type type,
dpc->function = function;
dpc->context = context;
- INIT_WORK(&dpc->work, acpi_os_execute_deferred);
- queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
- if (!queue_work(queue, &dpc->work)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Call to queue_work() failed.\n"));
+ if (!hp) {
+ INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+ queue = (type == OSL_NOTIFY_HANDLER) ?
+ kacpi_notify_wq : kacpid_wq;
+ ret = queue_work(queue, &dpc->work);
+ } else {
+ INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred);
+ ret = schedule_work(&dpc->work);
+ }
+
+ if (!ret) {
+ printk(KERN_ERR PREFIX
+ "Call to queue_work() failed.\n");
status = AE_ERROR;
kfree(dpc);
}
return_ACPI_STATUS(status);
}
+acpi_status acpi_os_execute(acpi_execute_type type,
+ acpi_osd_exec_callback function, void *context)
+{
+ return __acpi_os_execute(type, function, context, 0);
+}
EXPORT_SYMBOL(acpi_os_execute);
+acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
+ void *context)
+{
+ return __acpi_os_execute(0, function, context, 1);
+}
+
void acpi_os_wait_events_complete(void *context)
{
flush_workqueue(kacpid_wq);
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
index c06238e55d9..4647039a0d8 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/parser/psloop.c
@@ -719,6 +719,8 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
*op = NULL;
}
+ ACPI_PREEMPTION_POINT();
+
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 15e1702e48d..68e932f215e 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -137,6 +137,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
union acpi_parse_object *next;
const struct acpi_opcode_info *parent_info;
union acpi_parse_object *replacement_op = NULL;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op);
@@ -186,7 +187,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
replacement_op =
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto allocate_error;
+ status = AE_NO_MEMORY;
}
break;
@@ -211,7 +212,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
replacement_op =
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto allocate_error;
+ status = AE_NO_MEMORY;
}
} else
if ((op->common.parent->common.aml_opcode ==
@@ -226,13 +227,13 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
acpi_ps_alloc_op(op->common.
aml_opcode);
if (!replacement_op) {
- goto allocate_error;
+ status = AE_NO_MEMORY;
+ } else {
+ replacement_op->named.data =
+ op->named.data;
+ replacement_op->named.length =
+ op->named.length;
}
-
- replacement_op->named.data =
- op->named.data;
- replacement_op->named.length =
- op->named.length;
}
}
break;
@@ -242,7 +243,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
replacement_op =
acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto allocate_error;
+ status = AE_NO_MEMORY;
}
}
@@ -302,14 +303,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
/* Now we can actually delete the subtree rooted at Op */
acpi_ps_delete_parse_tree(op);
- return_ACPI_STATUS(AE_OK);
-
- allocate_error:
-
- /* Always delete the subtree, even on error */
-
- acpi_ps_delete_parse_tree(op);
- return_ACPI_STATUS(AE_NO_MEMORY);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -641,10 +635,12 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
ACPI_WALK_METHOD_RESTART;
}
} else {
- /* On error, delete any return object */
+ /* On error, delete any return object or implicit return */
acpi_ut_remove_reference(previous_walk_state->
return_desc);
+ acpi_ds_clear_implicit_return
+ (previous_walk_state);
}
}
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index cf47805a744..fcfdef7b4fd 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -709,7 +709,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
acpi_device_bid(link->device)));
if (link->refcnt == 0) {
- acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL);
+ acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
}
mutex_unlock(&acpi_link_lock);
return (link->irq.active);
@@ -737,7 +737,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
link->device = device;
strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
- acpi_driver_data(device) = link;
+ device->driver_data = link;
mutex_lock(&acpi_link_lock);
result = acpi_pci_link_get_possible(link);
@@ -773,7 +773,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
end:
/* disable all links -- to be activated on use */
- acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL);
+ acpi_evaluate_object(device->handle, "_DIS", NULL, NULL);
mutex_unlock(&acpi_link_lock);
if (result)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c3fed31166b..1b8f67d21d5 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -190,7 +190,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
struct acpi_pci_root *root = NULL;
struct acpi_pci_root *tmp;
acpi_status status = AE_OK;
- unsigned long value = 0;
+ unsigned long long value = 0;
acpi_handle handle = NULL;
struct acpi_device *child;
@@ -206,7 +206,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
root->device = device;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
- acpi_driver_data(device) = root;
+ device->driver_data = root;
device->ops.bind = acpi_pci_bind;
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index d5b4ef89887..cd1f4467be7 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -76,10 +76,10 @@ static struct acpi_pci_driver acpi_pci_slot_driver = {
};
static int
-check_slot(acpi_handle handle, unsigned long *sun)
+check_slot(acpi_handle handle, unsigned long long *sun)
{
int device = -1;
- unsigned long adr, sta;
+ unsigned long long adr, sta;
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -132,7 +132,7 @@ static acpi_status
register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int device;
- unsigned long sun;
+ unsigned long long sun;
char name[SLOT_NAME_SIZE];
struct acpi_pci_slot *slot;
struct pci_slot *pci_slot;
@@ -150,7 +150,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
}
snprintf(name, sizeof(name), "%u", (u32)sun);
- pci_slot = pci_create_slot(pci_bus, device, name);
+ pci_slot = pci_create_slot(pci_bus, device, name, NULL);
if (IS_ERR(pci_slot)) {
err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
kfree(slot);
@@ -182,7 +182,7 @@ static acpi_status
walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int device, function;
- unsigned long adr;
+ unsigned long long adr;
acpi_status status;
acpi_handle dummy_handle;
acpi_walk_callback user_function;
@@ -239,7 +239,7 @@ static int
walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
{
int seg, bus;
- unsigned long tmp;
+ unsigned long long tmp;
acpi_status status;
acpi_handle dummy_handle;
struct pci_bus *pci_bus;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 4ab21cb1c8c..a1718e56103 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power");
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "acpi."
+int acpi_power_nocheck;
+module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
+
static int acpi_power_add(struct acpi_device *device);
static int acpi_power_remove(struct acpi_device *device, int type);
static int acpi_power_resume(struct acpi_device *device);
@@ -128,16 +136,16 @@ acpi_power_get_context(acpi_handle handle,
return 0;
}
-static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
+static int acpi_power_get_state(acpi_handle handle, int *state)
{
acpi_status status = AE_OK;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
- if (!resource || !state)
+ if (!handle || !state)
return -EINVAL;
- status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -145,7 +153,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- resource->name, state ? "on" : "off"));
+ acpi_ut_get_node_name(handle), state ? "on" : "off"));
return 0;
}
@@ -153,7 +161,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
int result = 0, state1;
- struct acpi_power_resource *resource = NULL;
u32 i = 0;
@@ -161,12 +168,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return -EINVAL;
/* The state of the list is 'on' IFF all resources are 'on'. */
+ /* */
for (i = 0; i < list->count; i++) {
- result = acpi_power_get_context(list->handles[i], &resource);
- if (result)
- return result;
- result = acpi_power_get_state(resource, &state1);
+ /*
+ * The state of the power resource can be obtained by
+ * using the ACPI handle. In such case it is unnecessary to
+ * get the Power resource first and then get its state again.
+ */
+ result = acpi_power_get_state(list->handles[i], &state1);
if (result)
return result;
@@ -226,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource, &state);
- if (result)
- return result;
- if (state != ACPI_POWER_RESOURCE_STATE_ON)
- return -ENOEXEC;
-
+ if (!acpi_power_nocheck) {
+ /*
+ * If acpi_power_nocheck is set, it is unnecessary to check
+ * the power state after power transition.
+ */
+ result = acpi_power_get_state(resource->device->handle,
+ &state);
+ if (result)
+ return result;
+ if (state != ACPI_POWER_RESOURCE_STATE_ON)
+ return -ENOEXEC;
+ }
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D0;
@@ -277,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
- result = acpi_power_get_state(resource, &state);
- if (result)
- return result;
- if (state != ACPI_POWER_RESOURCE_STATE_OFF)
- return -ENOEXEC;
+ if (!acpi_power_nocheck) {
+ /*
+ * If acpi_power_nocheck is set, it is unnecessary to check
+ * the power state after power transition.
+ */
+ result = acpi_power_get_state(handle, &state);
+ if (result)
+ return result;
+ if (state != ACPI_POWER_RESOURCE_STATE_OFF)
+ return -ENOEXEC;
+ }
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D3;
@@ -555,7 +577,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if (!resource)
goto end;
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(resource->device->handle, &state);
if (result)
goto end;
@@ -657,7 +679,7 @@ static int acpi_power_add(struct acpi_device *device)
strcpy(resource->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
- acpi_driver_data(device) = resource;
+ device->driver_data = resource;
/* Evalute the object to get the system level and resource order. */
status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer);
@@ -668,7 +690,7 @@ static int acpi_power_add(struct acpi_device *device)
resource->system_level = acpi_object.power_resource.system_level;
resource->order = acpi_object.power_resource.resource_order;
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(device->handle, &state);
if (result)
goto end;
@@ -733,9 +755,9 @@ static int acpi_power_resume(struct acpi_device *device)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- resource = (struct acpi_power_resource *)acpi_driver_data(device);
+ resource = acpi_driver_data(device);
- result = acpi_power_get_state(resource, &state);
+ result = acpi_power_get_state(device->handle, &state);
if (result)
return result;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index ee68ac54c0d..24a362f8034 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -563,7 +563,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
/* Check if it is a Device with HID and UID */
if (has_uid) {
- unsigned long value;
+ unsigned long long value;
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
NULL, &value);
if (ACPI_FAILURE(status)) {
@@ -818,7 +818,7 @@ static int acpi_processor_add(struct acpi_device *device)
pr->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
- acpi_driver_data(device) = pr;
+ device->driver_data = pr;
return 0;
}
@@ -875,7 +875,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
static int is_processor_present(acpi_handle handle)
{
acpi_status status;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index cf5b1b7b684..81b40ed5379 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1587,6 +1587,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (acpi_idle_bm_check()) {
if (dev->safe_state) {
+ dev->last_state = dev->safe_state;
return dev->safe_state->enter(dev, dev->safe_state);
} else {
local_irq_disable();
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 80c251ec6d2..dbcf260ea93 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -39,6 +39,10 @@
#include <asm/uaccess.h>
#endif
+#ifdef CONFIG_X86
+#include <asm/cpufeature.h>
+#endif
+
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
@@ -126,7 +130,7 @@ static struct notifier_block acpi_ppc_notifier_block = {
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
acpi_status status = 0;
- unsigned long ppc = 0;
+ unsigned long long ppc = 0;
if (!pr)
@@ -334,7 +338,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
acpi_status status = AE_OK;
acpi_handle handle = NULL;
-
if (!pr || !pr->performance || !pr->handle)
return -EINVAL;
@@ -347,13 +350,27 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
result = acpi_processor_get_performance_control(pr);
if (result)
- return result;
+ goto update_bios;
result = acpi_processor_get_performance_states(pr);
if (result)
- return result;
+ goto update_bios;
return 0;
+
+ /*
+ * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
+ * the BIOS is older than the CPU and does not know its frequencies
+ */
+ update_bios:
+#ifdef CONFIG_X86
+ if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
+ if(boot_cpu_has(X86_FEATURE_EST))
+ printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
+ "frequency support\n");
+ }
+#endif
+ return result;
}
int acpi_processor_notify_smm(struct module *calling_module)
@@ -524,13 +541,13 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
psd = buffer.pointer;
if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
if (psd->package.count != 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
@@ -543,19 +560,19 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
status = acpi_extract_package(&(psd->package.elements[0]),
&format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
+ printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n");
result = -EFAULT;
goto end;
}
if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
+ printk(KERN_ERR PREFIX "Unknown _PSD:revision\n");
result = -EFAULT;
goto end;
}
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index a56fc6c4394..3da2df93d92 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -274,7 +274,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data)
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
acpi_status status = 0;
- unsigned long tpc = 0;
+ unsigned long long tpc = 0;
if (!pr)
return -EINVAL;
@@ -528,13 +528,13 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
tsd = buffer.pointer;
if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _TSD data\n");
result = -EFAULT;
goto end;
}
if (tsd->package.count != 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _TSD data\n");
result = -EFAULT;
goto end;
}
@@ -547,19 +547,19 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
status = acpi_extract_package(&(tsd->package.elements[0]),
&format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _TSD data\n");
result = -EFAULT;
goto end;
}
if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n"));
+ printk(KERN_ERR PREFIX "Unknown _TSD:num_entries\n");
result = -EFAULT;
goto end;
}
if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n"));
+ printk(KERN_ERR PREFIX "Unknown _TSD:revision\n");
result = -EFAULT;
goto end;
}
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index a6b662c00b6..755baf2ca70 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -15,9 +15,28 @@ void acpi_reboot(void)
rr = &acpi_gbl_FADT.reset_register;
- /* Is the reset register supported? */
- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
- rr->bit_width != 8 || rr->bit_offset != 0)
+ /*
+ * Is the ACPI reset register supported?
+ *
+ * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates
+ * whether the ACPI reset mechanism is supported.
+ *
+ * However, some boxes have this bit clear, yet a valid
+ * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only
+ * mechanism that works for them after S3.
+ *
+ * This suggests that other operating systems may not be checking
+ * the RESET_REG_SUP bit, and are using other means to decide
+ * whether to use the ACPI reboot mechanism or not.
+ *
+ * So when acpi reboot is requested,
+ * only the reset_register is checked. If the following
+ * conditions are met, it indicates that the reset register is supported.
+ * a. reset_register is not zero
+ * b. the access width is eight
+ * c. the bit_offset is zero
+ */
+ if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0)
return;
reset_value = acpi_gbl_FADT.reset_value;
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index d9063ea414e..8eaaecf9200 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -43,7 +43,6 @@
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
-#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
@@ -560,8 +559,8 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
ACPI_GET_OBJECT_TYPE(*sub_object_list)) ||
((ACPI_TYPE_LOCAL_REFERENCE ==
ACPI_GET_OBJECT_TYPE(*sub_object_list)) &&
- ((*sub_object_list)->reference.opcode ==
- AML_INT_NAMEPATH_OP)))) {
+ ((*sub_object_list)->reference.class ==
+ ACPI_REFCLASS_NAME)))) {
name_found = TRUE;
} else {
/* Look at the next element */
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 7804a8c40e7..c0bbfa2c419 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -43,7 +43,6 @@
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
-#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
@@ -310,13 +309,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
- if (obj_desc->reference.opcode !=
- AML_INT_NAMEPATH_OP) {
+ if (obj_desc->reference.class !=
+ ACPI_REFCLASS_NAME) {
ACPI_ERROR((AE_INFO,
- "(PRT[%X].Source) Need name, found reference op %X",
+ "(PRT[%X].Source) Need name, found Reference Class %X",
index,
- obj_desc->reference.
- opcode));
+ obj_desc->reference.class));
return_ACPI_STATUS(AE_BAD_DATA);
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 10a36512647..6050ce48187 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -463,7 +463,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
}
static struct device_attribute alarm_attr = {
- .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
+ .attr = {.name = "alarm", .mode = 0644},
.show = acpi_battery_alarm_show,
.store = acpi_battery_alarm_store,
};
@@ -931,7 +931,7 @@ static int acpi_sbs_add(struct acpi_device *device)
sbs->device = device;
strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
- acpi_driver_data(device) = sbs;
+ device->driver_data = sbs;
result = acpi_charger_add(sbs);
if (result)
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index a4e3767b8c6..e53e590252c 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -258,7 +258,7 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
static int acpi_smbus_hc_add(struct acpi_device *device)
{
int status;
- unsigned long val;
+ unsigned long long val;
struct acpi_smb_hc *hc;
if (!device)
@@ -282,7 +282,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
hc->ec = acpi_driver_data(device->parent);
hc->offset = (val >> 8) & 0xff;
hc->query_bit = val & 0xff;
- acpi_driver_data(device) = hc;
+ device->driver_data = hc;
acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
@@ -303,7 +303,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
hc = acpi_driver_data(device);
acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
kfree(hc);
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
return 0;
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f6f52c1a2ab..a9dda8e0f9f 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -113,16 +113,16 @@ static int acpi_bus_hot_remove_device(void *context)
if (acpi_bus_trim(device, 1)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Removing device failed\n"));
+ printk(KERN_ERR PREFIX
+ "Removing device failed\n");
return -1;
}
/* power off device */
status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Power-off device failed\n"));
+ printk(KERN_WARNING PREFIX
+ "Power-off device failed\n");
if (device->flags.lockable) {
arg_list.count = 1;
@@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device,
{
const struct acpi_device_id *id;
+ /*
+ * If the device is not present, it is unnecessary to load device
+ * driver for it.
+ */
+ if (!device->status.present)
+ return -ENODEV;
+
if (device->flags.hardware_id) {
for (id = ids; id->id[0]; id++) {
if (!strcmp((char*)id->id, device->pnp.hardware_id))
@@ -384,7 +391,7 @@ static int acpi_device_remove(struct device * dev)
acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
}
acpi_dev->driver = NULL;
- acpi_driver_data(dev) = NULL;
+ acpi_dev->driver_data = NULL;
put_device(dev);
return 0;
@@ -477,7 +484,7 @@ static int acpi_device_register(struct acpi_device *device,
result = acpi_device_setup_files(device);
if(result)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id));
+ printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id);
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0;
@@ -537,7 +544,7 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
result = driver->ops.add(device);
if (result) {
device->driver = NULL;
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
return result;
}
@@ -744,6 +751,16 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
+ /*
+ * Don't set Power button GPE as run_wake
+ * if Fixed Power button is used
+ */
+ if (!strcmp(device->pnp.hardware_id, "PNP0C0C") &&
+ !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
+ device->wakeup.flags.run_wake = 0;
+ device->wakeup.flags.valid = 0;
+ }
+
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
@@ -807,6 +824,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
/* TBD: System wake support and resource requirements. */
device->power.state = ACPI_STATE_UNKNOWN;
+ acpi_bus_get_power(device->handle, &(device->power.state));
return 0;
}
@@ -1153,20 +1171,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
}
static int
-acpi_is_child_device(struct acpi_device *device,
- int (*matcher)(struct acpi_device *))
-{
- int result = -ENODEV;
-
- do {
- if (ACPI_SUCCESS(matcher(device)))
- return AE_OK;
- } while ((device = device->parent));
-
- return result;
-}
-
-static int
acpi_add_single_object(struct acpi_device **child,
struct acpi_device *parent, acpi_handle handle, int type,
struct acpi_bus_ops *ops)
@@ -1221,15 +1225,18 @@ acpi_add_single_object(struct acpi_device **child,
result = -ENODEV;
goto end;
}
- if (!device->status.present) {
- /* Bay and dock should be handled even if absent */
- if (!ACPI_SUCCESS(
- acpi_is_child_device(device, acpi_bay_match)) &&
- !ACPI_SUCCESS(
- acpi_is_child_device(device, acpi_dock_match))) {
- result = -ENODEV;
- goto end;
- }
+ /*
+ * When the device is neither present nor functional, the
+ * device should not be added to Linux ACPI device tree.
+ * When the status of the device is not present but functinal,
+ * it should be added to Linux ACPI tree. For example : bay
+ * device , dock device.
+ * In such conditions it is unncessary to check whether it is
+ * bay device or dock device.
+ */
+ if (!device->status.present && !device->status.functional) {
+ result = -ENODEV;
+ goto end;
}
break;
default:
@@ -1252,6 +1259,16 @@ acpi_add_single_object(struct acpi_device **child,
acpi_device_set_id(device, parent, handle, type);
/*
+ * The ACPI device is attached to acpi handle before getting
+ * the power/wakeup/peformance flags. Otherwise OS can't get
+ * the corresponding ACPI device by the acpi handle in the course
+ * of getting the power/wakeup/performance flags.
+ */
+ result = acpi_device_set_context(device, type);
+ if (result)
+ goto end;
+
+ /*
* Power Management
* ----------------
*/
@@ -1281,8 +1298,6 @@ acpi_add_single_object(struct acpi_device **child,
goto end;
}
- if ((result = acpi_device_set_context(device, type)))
- goto end;
result = acpi_device_register(device, parent);
@@ -1402,7 +1417,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
* TBD: Need notifications and other detection mechanisms
* in place before we can fully implement this.
*/
- if (child->status.present) {
+ /*
+ * When the device is not present but functional, it is also
+ * necessary to scan the children of this device.
+ */
+ if (child->status.present || (!child->status.present &&
+ child->status.functional)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
NULL, NULL);
if (ACPI_SUCCESS(status)) {
@@ -1545,7 +1565,6 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
return result;
}
-int __init acpi_boot_ec_enable(void);
static int __init acpi_scan_init(void)
{
@@ -1579,9 +1598,6 @@ static int __init acpi_scan_init(void)
*/
result = acpi_bus_scan_fixed(acpi_root);
- /* EC region might be needed at bus_scan, so enable it now */
- acpi_boot_ec_enable();
-
if (!result)
result = acpi_bus_scan(acpi_root, &ops);
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index d13194a031b..80c0868d048 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -15,6 +15,7 @@
#include <linux/dmi.h>
#include <linux/device.h>
#include <linux/suspend.h>
+#include <linux/reboot.h>
#include <asm/io.h>
@@ -24,6 +25,36 @@
u8 sleep_states[ACPI_S_STATE_COUNT];
+static void acpi_sleep_tts_switch(u32 acpi_state)
+{
+ union acpi_object in_arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &in_arg };
+ acpi_status status = AE_OK;
+
+ in_arg.integer.value = acpi_state;
+ status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ /*
+ * OS can't evaluate the _TTS object correctly. Some warning
+ * message will be printed. But it won't break anything.
+ */
+ printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
+ }
+}
+
+static int tts_notify_reboot(struct notifier_block *this,
+ unsigned long code, void *x)
+{
+ acpi_sleep_tts_switch(ACPI_STATE_S5);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block tts_notifier = {
+ .notifier_call = tts_notify_reboot,
+ .next = NULL,
+ .priority = 0,
+};
+
static int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
@@ -45,9 +76,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ACPI_SLEEP
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
/*
* ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
* user to request that behavior by using the 'acpi_old_suspend_ordering'
@@ -131,8 +161,11 @@ static void acpi_pm_end(void)
* failing transition to a sleep state.
*/
acpi_target_sleep_state = ACPI_STATE_S0;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
}
-#endif /* CONFIG_PM_SLEEP */
+#else /* !CONFIG_ACPI_SLEEP */
+#define acpi_target_sleep_state ACPI_STATE_S0
+#endif /* CONFIG_ACPI_SLEEP */
#ifdef CONFIG_SUSPEND
extern void do_suspend_lowlevel(void);
@@ -155,6 +188,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
} else {
printk(KERN_ERR "ACPI does not support this state: %d\n",
pm_state);
@@ -200,6 +234,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
break;
}
+ /* If ACPI is not enabled by the BIOS, we need to enable it here. */
+ acpi_enable();
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
@@ -296,6 +332,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
},
},
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "HP xw4600 Workstation",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
@@ -313,6 +357,7 @@ void __init acpi_no_s4_hw_signature(void)
static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
return 0;
}
@@ -376,7 +421,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
*/
static int acpi_hibernation_begin_old(void)
{
- int error = acpi_sleep_prepare(ACPI_STATE_S4);
+ int error;
+ /*
+ * The _TTS object should always be evaluated before the _PTS object.
+ * When the old_suspended_ordering is true, the _PTS object is
+ * evaluated in the acpi_sleep_prepare.
+ */
+ acpi_sleep_tts_switch(ACPI_STATE_S4);
+
+ error = acpi_sleep_prepare(ACPI_STATE_S4);
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
@@ -444,7 +497,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
struct acpi_device *adev;
char acpi_method[] = "_SxD";
- unsigned long d_min, d_max;
+ unsigned long long d_min, d_max;
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
printk(KERN_DEBUG "ACPI handle has no context!\n");
@@ -596,5 +649,10 @@ int __init acpi_sleep_init(void)
pm_power_off = acpi_power_off;
}
printk(")\n");
+ /*
+ * Register the tts_notifier to reboot notifier list so that the _TTS
+ * object can also be evaluated when the system enters S5.
+ */
+ register_reboot_notifier(&tts_notifier);
return 0;
}
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index bf5b04de02d..631ee2ee2ca 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -120,13 +120,13 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
spin_unlock_irqrestore(&rtc_lock, flags);
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hr);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mo);
- BCD_TO_BIN(yr);
- BCD_TO_BIN(cent);
+ sec = bcd2bin(sec);
+ min = bcd2bin(min);
+ hr = bcd2bin(hr);
+ day = bcd2bin(day);
+ mo = bcd2bin(mo);
+ yr = bcd2bin(yr);
+ cent = bcd2bin(cent);
}
/* we're trusting the FADT (see above) */
@@ -204,7 +204,7 @@ static u32 cmos_bcd_read(int offset, int rtc_control)
{
u32 val = CMOS_READ(offset);
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- BCD_TO_BIN(val);
+ val = bcd2bin(val);
return val;
}
@@ -212,7 +212,7 @@ static u32 cmos_bcd_read(int offset, int rtc_control)
static void cmos_bcd_write(u32 val, int offset, int rtc_control)
{
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- BIN_TO_BCD(val);
+ val = bin2bcd(val);
CMOS_WRITE(val, offset);
}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 91dec448b3e..1d74171b794 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -115,7 +115,6 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
table_attr->attr.read = acpi_table_show;
table_attr->attr.attr.name = table_attr->name;
table_attr->attr.attr.mode = 0444;
- table_attr->attr.attr.owner = THIS_MODULE;
return;
}
@@ -387,8 +386,8 @@ static ssize_t counter_set(struct kobject *kobj,
goto end;
if (!(all_counters[index].flags & ACPI_EVENT_VALID)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Can not change Invalid GPE/Fixed Event status\n"));
+ printk(KERN_WARNING PREFIX
+ "Can not change Invalid GPE/Fixed Event status\n");
return -EINVAL;
}
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index a4a41ba2484..2c7885e7ffb 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt")
/* Local prototypes */
static void inline
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 bit_width, u64 address);
+ u8 byte_width, u64 address);
static void acpi_tb_convert_fadt(void);
@@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
* FUNCTION: acpi_tb_init_generic_address
*
* PARAMETERS: generic_address - GAS struct to be initialized
- * bit_width - Width of this register
+ * byte_width - Width of this register
* Address - Address of the register
*
* RETURN: None
@@ -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 bit_width, u64 address)
+ u8 byte_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 = bit_width;
+ generic_address->bit_width = byte_width << 3;
generic_address->bit_offset = 0;
generic_address->access_width = 0;
}
@@ -342,9 +342,20 @@ static void acpi_tb_convert_fadt(void)
* useful to calculate them once, here.
*
* 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 (pm1_event_length/2)
+ * PM Status Register block, followed immediately by the PM Enable
+ * Register block. Each is of length (xpm1x_event_block.bit_width/2).
+ *
+ * On various systems the v2 fields (and particularly the bit widths)
+ * cannot be relied upon, though. Hence resort to using the v1 length
+ * here (and warn about the inconsistency).
*/
+ if (acpi_gbl_FADT.xpm1a_event_block.bit_width
+ != acpi_gbl_FADT.pm1_event_length * 8)
+ printk(KERN_WARNING "FADT: "
+ "X_PM1a_EVT_BLK.bit_width (%u) does not match"
+ " PM1_EVT_LEN (%u)\n",
+ acpi_gbl_FADT.xpm1a_event_block.bit_width,
+ acpi_gbl_FADT.pm1_event_length);
pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
/* The PM1A register block is required */
@@ -360,13 +371,20 @@ 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) {
+ if (acpi_gbl_FADT.xpm1b_event_block.bit_width
+ != acpi_gbl_FADT.pm1_event_length * 8)
+ printk(KERN_WARNING "FADT: "
+ "X_PM1b_EVT_BLK.bit_width (%u) does not match"
+ " PM1_EVT_LEN (%u)\n",
+ acpi_gbl_FADT.xpm1b_event_block.bit_width,
+ acpi_gbl_FADT.pm1_event_length);
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.xpm1a_event_block.space_id;
+ acpi_gbl_FADT.xpm1b_event_block.space_id;
}
}
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index b22185f55a1..18747ce8dd2 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -110,7 +110,6 @@ acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
u32 i;
- u32 length;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_add_table);
@@ -145,25 +144,64 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
}
}
- length = ACPI_MIN(table_desc->length,
- acpi_gbl_root_table_list.tables[i].length);
+ /*
+ * Check for a table match on the entire table length,
+ * not just the header.
+ */
+ if (table_desc->length !=
+ acpi_gbl_root_table_list.tables[i].length) {
+ continue;
+ }
+
if (ACPI_MEMCMP(table_desc->pointer,
acpi_gbl_root_table_list.tables[i].pointer,
- length)) {
+ acpi_gbl_root_table_list.tables[i].length)) {
continue;
}
- /* Table is already registered */
-
+ /*
+ * Note: the current mechanism does not unregister a table if it is
+ * dynamically unloaded. The related namespace entries are deleted,
+ * but the table remains in the root table list.
+ *
+ * The assumption here is that the number of different tables that
+ * will be loaded is actually small, and there is minimal overhead
+ * in just keeping the table in case it is needed again.
+ *
+ * If this assumption changes in the future (perhaps on large
+ * machines with many table load/unload operations), tables will
+ * need to be unregistered when they are unloaded, and slots in the
+ * root table list should be reused when empty.
+ */
+
+ /*
+ * Table is already registered.
+ * We can delete the table that was passed as a parameter.
+ */
acpi_tb_delete_table(table_desc);
*table_index = i;
- status = AE_ALREADY_EXISTS;
- goto release;
+
+ if (acpi_gbl_root_table_list.tables[i].
+ flags & ACPI_TABLE_IS_LOADED) {
+
+ /* Table is still loaded, this is an error */
+
+ status = AE_ALREADY_EXISTS;
+ goto release;
+ } else {
+ /* Table was unloaded, allow it to be reloaded */
+
+ table_desc->pointer =
+ acpi_gbl_root_table_list.tables[i].pointer;
+ table_desc->address =
+ acpi_gbl_root_table_list.tables[i].address;
+ status = AE_OK;
+ goto print_header;
+ }
}
- /*
- * Add the table to the global table list
- */
+ /* Add the table to the global root table list */
+
status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
table_desc->length, table_desc->flags,
table_index);
@@ -171,6 +209,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
goto release;
}
+ print_header:
acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
release:
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 912703691d3..ad6cae938f0 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -246,18 +246,18 @@ static const struct file_operations acpi_thermal_polling_fops = {
static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
{
acpi_status status = AE_OK;
-
+ unsigned long long tmp;
if (!tz)
return -EINVAL;
tz->last_temperature = tz->temperature;
- status =
- acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature);
+ status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
+ tz->temperature = tmp;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
tz->temperature));
@@ -267,17 +267,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
{
acpi_status status = AE_OK;
-
+ unsigned long long tmp;
if (!tz)
return -EINVAL;
- status =
- acpi_evaluate_integer(tz->device->handle, "_TZP", NULL,
- &tz->polling_frequency);
+ status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
+ tz->polling_frequency = tmp;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
tz->polling_frequency));
@@ -356,6 +355,7 @@ do { \
static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
{
acpi_status status = AE_OK;
+ unsigned long long tmp;
struct acpi_handle_list devices;
int valid = 0;
int i;
@@ -363,7 +363,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
/* Critical Shutdown (required) */
if (flag & ACPI_TRIPS_CRITICAL) {
status = acpi_evaluate_integer(tz->device->handle,
- "_CRT", NULL, &tz->trips.critical.temperature);
+ "_CRT", NULL, &tmp);
+ tz->trips.critical.temperature = tmp;
/*
* Treat freezing temperatures as invalid as well; some
* BIOSes return really low values and cause reboots at startup.
@@ -388,10 +389,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
} else if (crt > 0) {
unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
/*
- * Allow override to lower critical threshold
+ * Allow override critical threshold
*/
- if (crt_k < tz->trips.critical.temperature)
- tz->trips.critical.temperature = crt_k;
+ if (crt_k > tz->trips.critical.temperature)
+ printk(KERN_WARNING PREFIX
+ "Critical threshold %d C\n", crt);
+ tz->trips.critical.temperature = crt_k;
}
}
}
@@ -399,12 +402,13 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
/* Critical Sleep (optional) */
if (flag & ACPI_TRIPS_HOT) {
status = acpi_evaluate_integer(tz->device->handle,
- "_HOT", NULL, &tz->trips.hot.temperature);
+ "_HOT", NULL, &tmp);
if (ACPI_FAILURE(status)) {
tz->trips.hot.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No hot threshold\n"));
} else {
+ tz->trips.hot.temperature = tmp;
tz->trips.hot.flags.valid = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found hot threshold [%lu]\n",
@@ -418,33 +422,40 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (psv == -1) {
status = AE_SUPPORT;
} else if (psv > 0) {
- tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
+ tmp = CELSIUS_TO_KELVIN(psv);
status = AE_OK;
} else {
status = acpi_evaluate_integer(tz->device->handle,
- "_PSV", NULL, &tz->trips.passive.temperature);
+ "_PSV", NULL, &tmp);
}
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
else {
+ tz->trips.passive.temperature = tmp;
tz->trips.passive.flags.valid = 1;
if (flag == ACPI_TRIPS_INIT) {
status = acpi_evaluate_integer(
tz->device->handle, "_TC1",
- NULL, &tz->trips.passive.tc1);
+ NULL, &tmp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
+ else
+ tz->trips.passive.tc1 = tmp;
status = acpi_evaluate_integer(
tz->device->handle, "_TC2",
- NULL, &tz->trips.passive.tc2);
+ NULL, &tmp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
+ else
+ tz->trips.passive.tc2 = tmp;
status = acpi_evaluate_integer(
tz->device->handle, "_TSP",
- NULL, &tz->trips.passive.tsp);
+ NULL, &tmp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
+ else
+ tz->trips.passive.tsp = tmp;
}
}
}
@@ -479,7 +490,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (flag & ACPI_TRIPS_ACTIVE) {
status = acpi_evaluate_integer(tz->device->handle,
- name, NULL, &tz->trips.active[i].temperature);
+ name, NULL, &tmp);
if (ACPI_FAILURE(status)) {
tz->trips.active[i].flags.valid = 0;
if (i == 0)
@@ -500,8 +511,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
tz->trips.active[i - 2].temperature :
CELSIUS_TO_KELVIN(act));
break;
- } else
+ } else {
+ tz->trips.active[i].temperature = tmp;
tz->trips.active[i].flags.valid = 1;
+ }
}
name[2] = 'L';
@@ -1213,8 +1226,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
acpi_bus_private_data_handler,
tz->thermal_zone);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error attaching device data\n"));
+ printk(KERN_ERR PREFIX
+ "Error attaching device data\n");
return -ENODEV;
}
@@ -1647,7 +1660,7 @@ static int acpi_thermal_add(struct acpi_device *device)
strcpy(tz->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
- acpi_driver_data(device) = tz;
+ device->driver_data = tz;
mutex_init(&tz->lock);
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 8a649f40d16..66aac06f2ac 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -371,6 +371,7 @@ static void bt_poll_rfkill(struct input_polled_dev *poll_dev)
RFKILL_STATE_HARD_BLOCKED);
input_report_switch(poll_dev->input, SW_RFKILL_ALL,
new_rfk_state);
+ input_sync(poll_dev->input);
}
}
@@ -548,7 +549,7 @@ static unsigned long write_video(const char *buffer, unsigned long count)
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
if (hci_result == HCI_SUCCESS) {
- int new_video_out = video_out;
+ unsigned int new_video_out = video_out;
if (lcd_out != -1)
_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
if (crt_out != -1)
@@ -842,6 +843,7 @@ static int __init toshiba_acpi_init(void)
set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit);
set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit);
input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE);
+ input_sync(toshiba_acpi.poll_dev->input);
ret = input_register_polled_device(toshiba_acpi.poll_dev);
if (ret) {
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 7dcb67e0b21..241c535c175 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -232,7 +232,7 @@ acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
* RETURN: Status
*
* DESCRIPTION: Validate that the buffer is of the required length or
- * allocate a new buffer. Returned buffer is always zeroed.
+ * allocate a new buffer. Returned buffer is always zeroed.
*
******************************************************************************/
@@ -240,7 +240,7 @@ acpi_status
acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
acpi_size required_length)
{
- acpi_status status = AE_OK;
+ acpi_size input_buffer_length;
/* Parameter validation */
@@ -248,55 +248,58 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
return (AE_BAD_PARAMETER);
}
- switch (buffer->length) {
+ /*
+ * Buffer->Length is used as both an input and output parameter. Get the
+ * input actual length and set the output required buffer length.
+ */
+ input_buffer_length = buffer->length;
+ buffer->length = required_length;
+
+ /*
+ * The input buffer length contains the actual buffer length, or the type
+ * of buffer to be allocated by this routine.
+ */
+ switch (input_buffer_length) {
case ACPI_NO_BUFFER:
- /* Set the exception and returned the required length */
+ /* Return the exception (and the required buffer length) */
- status = AE_BUFFER_OVERFLOW;
- break;
+ return (AE_BUFFER_OVERFLOW);
case ACPI_ALLOCATE_BUFFER:
/* Allocate a new buffer */
buffer->pointer = acpi_os_allocate(required_length);
- if (!buffer->pointer) {
- return (AE_NO_MEMORY);
- }
-
- /* Clear the buffer */
-
- ACPI_MEMSET(buffer->pointer, 0, required_length);
break;
case ACPI_ALLOCATE_LOCAL_BUFFER:
/* Allocate a new buffer with local interface to allow tracking */
- buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length);
- if (!buffer->pointer) {
- return (AE_NO_MEMORY);
- }
+ buffer->pointer = ACPI_ALLOCATE(required_length);
break;
default:
/* Existing buffer: Validate the size of the buffer */
- if (buffer->length < required_length) {
- status = AE_BUFFER_OVERFLOW;
- break;
+ if (input_buffer_length < required_length) {
+ return (AE_BUFFER_OVERFLOW);
}
+ break;
+ }
- /* Clear the buffer */
+ /* Validate allocation from above or input buffer pointer */
- ACPI_MEMSET(buffer->pointer, 0, required_length);
- break;
+ if (!buffer->pointer) {
+ return (AE_NO_MEMORY);
}
- buffer->length = required_length;
- return (status);
+ /* Have a valid buffer, clear it */
+
+ ACPI_MEMSET(buffer->pointer, 0, required_length);
+ return (AE_OK);
}
#ifdef NOT_USED_BY_LINUX
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 53499ac9098..5b2f7c27b70 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -42,7 +42,6 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
@@ -176,20 +175,24 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
/* This is an object reference. */
- switch (internal_object->reference.opcode) {
- case AML_INT_NAMEPATH_OP:
-
- /* For namepath, return the object handle ("reference") */
-
- default:
-
- /* We are referring to the namespace node */
+ switch (internal_object->reference.class) {
+ case ACPI_REFCLASS_NAME:
+ /*
+ * For namepath, return the object handle ("reference")
+ * We are referring to the namespace node
+ */
external_object->reference.handle =
internal_object->reference.node;
external_object->reference.actual_type =
acpi_ns_get_type(internal_object->reference.node);
break;
+
+ default:
+
+ /* All other reference types are unsupported */
+
+ return_ACPI_STATUS(AE_TYPE);
}
break;
@@ -533,7 +536,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
/* TBD: should validate incoming handle */
- internal_object->reference.opcode = AML_INT_NAMEPATH_OP;
+ internal_object->reference.class = ACPI_REFCLASS_NAME;
internal_object->reference.node =
external_object->reference.handle;
break;
@@ -743,11 +746,11 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
* We copied the reference object, so we now must add a reference
* to the object pointed to by the reference
*
- * DDBHandle reference (from Load/load_table is a special reference,
- * it's Reference.Object is the table index, so does not need to
+ * DDBHandle reference (from Load/load_table) is a special reference,
+ * it does not have a Reference.Object, so does not need to
* increase the reference count
*/
- if (source_desc->reference.opcode == AML_LOAD_OP) {
+ if (source_desc->reference.class == ACPI_REFCLASS_TABLE) {
break;
}
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 42609d3a8aa..d197c6b29e1 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -45,7 +45,6 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
-#include <acpi/amlcode.h>
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utdelete")
@@ -548,8 +547,8 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
* reference must track changes to the ref count of the index or
* target object.
*/
- if ((object->reference.opcode == AML_INDEX_OP) ||
- (object->reference.opcode == AML_INT_NAMEPATH_OP)) {
+ if ((object->reference.class == ACPI_REFCLASS_INDEX) ||
+ (object->reference.class == ACPI_REFCLASS_NAME)) {
next_object = object->reference.object;
}
break;
@@ -586,6 +585,13 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
ACPI_EXCEPTION((AE_INFO, status,
"Could not update object reference count"));
+ /* Free any stacked Update State objects */
+
+ while (state_list) {
+ state = acpi_ut_pop_generic_state(&state_list);
+ acpi_ut_delete_generic_state(state);
+ }
+
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index a6e71b801d2..670551b95e5 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -281,7 +281,6 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = {
/* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
ACPI_BITPOSITION_RT_CLOCK_ENABLE,
ACPI_BITMASK_RT_CLOCK_ENABLE},
- /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
/* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE,
ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE,
ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
@@ -575,6 +574,47 @@ char *acpi_ut_get_descriptor_name(void *object)
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_reference_name
+ *
+ * PARAMETERS: Object - An ACPI reference object
+ *
+ * RETURN: Pointer to a string
+ *
+ * DESCRIPTION: Decode a reference object sub-type to a string.
+ *
+ ******************************************************************************/
+
+/* Printable names of reference object sub-types */
+
+static const char *acpi_gbl_ref_class_names[] = {
+ /* 00 */ "Local",
+ /* 01 */ "Argument",
+ /* 02 */ "RefOf",
+ /* 03 */ "Index",
+ /* 04 */ "DdbHandle",
+ /* 05 */ "Named Object",
+ /* 06 */ "Debug"
+};
+
+const char *acpi_ut_get_reference_name(union acpi_operand_object *object)
+{
+ if (!object)
+ return "NULL Object";
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND)
+ return "Not an Operand object";
+
+ if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE)
+ return "Not a Reference object";
+
+ if (object->reference.class > ACPI_REFCLASS_MAX)
+ return "Unknown Reference class";
+
+ return acpi_gbl_ref_class_names[object->reference.class];
+}
+
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*
* Strings and procedures used for debug only
@@ -677,14 +717,14 @@ u8 acpi_ut_valid_object_type(acpi_object_type type)
*
* PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Init library globals. All globals that require specific
* initialization should be initialized here!
*
******************************************************************************/
-void acpi_ut_init_globals(void)
+acpi_status acpi_ut_init_globals(void)
{
acpi_status status;
u32 i;
@@ -695,7 +735,7 @@ void acpi_ut_init_globals(void)
status = acpi_ut_create_caches();
if (ACPI_FAILURE(status)) {
- return;
+ return_ACPI_STATUS(status);
}
/* Mutex locked flags */
@@ -772,8 +812,8 @@ void acpi_ut_init_globals(void)
acpi_gbl_display_final_mem_stats = FALSE;
#endif
- return_VOID;
+ return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_dbg_level)
- ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
+ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index f34be677355..9089a158a87 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -995,6 +995,15 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
state->pkg.
this_target_obj, 0);
if (!state) {
+
+ /* Free any stacked Update State objects */
+
+ while (state_list) {
+ state =
+ acpi_ut_pop_generic_state
+ (&state_list);
+ acpi_ut_delete_generic_state(state);
+ }
return_ACPI_STATUS(AE_NO_MEMORY);
}
}
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 916eff399eb..c354e7a42bc 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -43,7 +43,6 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-#include <acpi/amlcode.h>
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utobject")
@@ -478,8 +477,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
case ACPI_TYPE_LOCAL_REFERENCE:
- switch (internal_object->reference.opcode) {
- case AML_INT_NAMEPATH_OP:
+ switch (internal_object->reference.class) {
+ case ACPI_REFCLASS_NAME:
/*
* Get the actual length of the full pathname to this object.
@@ -503,8 +502,10 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
* required eventually.
*/
ACPI_ERROR((AE_INFO,
- "Unsupported Reference opcode=%X in object %p",
- internal_object->reference.opcode,
+ "Cannot convert to external object - "
+ "unsupported Reference Class [%s] %X in object %p",
+ acpi_ut_get_reference_name(internal_object),
+ internal_object->reference.class,
internal_object));
status = AE_TYPE;
break;
@@ -513,7 +514,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
default:
- ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p",
+ ACPI_ERROR((AE_INFO, "Cannot convert to external object - "
+ "unsupported type [%s] %X in object %p",
+ acpi_ut_get_object_type_name(internal_object),
ACPI_GET_OBJECT_TYPE(internal_object),
internal_object));
status = AE_TYPE;
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index f8bdadf3c32..c198a4d4058 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -81,7 +81,12 @@ acpi_status __init acpi_initialize_subsystem(void)
/* Initialize all globals used by the subsystem */
- acpi_ut_init_globals();
+ status = acpi_ut_init_globals();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During initialization of globals"));
+ return_ACPI_STATUS(status);
+ }
/* Create the default mutex objects */
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 10092614381..e827be36ee8 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -256,7 +256,7 @@ EXPORT_SYMBOL(acpi_extract_package);
acpi_status
acpi_evaluate_integer(acpi_handle handle,
acpi_string pathname,
- struct acpi_object_list *arguments, unsigned long *data)
+ struct acpi_object_list *arguments, unsigned long long *data)
{
acpi_status status = AE_OK;
union acpi_object *element;
@@ -288,7 +288,7 @@ acpi_evaluate_integer(acpi_handle handle,
*data = element->integer.value;
kfree(element);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
return AE_OK;
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e8a51a1700f..a29b0ccac65 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -291,20 +291,20 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
int level);
static int acpi_video_device_lcd_get_level_current(
struct acpi_video_device *device,
- unsigned long *level);
+ unsigned long long *level);
static int acpi_video_get_next_level(struct acpi_video_device *device,
u32 level_current, u32 event);
static void acpi_video_switch_brightness(struct acpi_video_device *device,
int event);
static int acpi_video_device_get_state(struct acpi_video_device *device,
- unsigned long *state);
+ unsigned long long *state);
static int acpi_video_output_get(struct output_device *od);
static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
/*backlight device sysfs support*/
static int acpi_video_get_brightness(struct backlight_device *bd)
{
- unsigned long cur_level;
+ unsigned long long cur_level;
int i;
struct acpi_video_device *vd =
(struct acpi_video_device *)bl_get_data(bd);
@@ -336,7 +336,7 @@ static struct backlight_ops acpi_backlight_ops = {
/*video output device sysfs support*/
static int acpi_video_output_get(struct output_device *od)
{
- unsigned long state;
+ unsigned long long state;
struct acpi_video_device *vd =
(struct acpi_video_device *)dev_get_drvdata(&od->dev);
acpi_video_device_get_state(vd, &state);
@@ -370,7 +370,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
struct acpi_video_device *video = acpi_driver_data(device);
- unsigned long level;
+ unsigned long long level;
int state;
acpi_video_device_lcd_get_level_current(video, &level);
@@ -410,7 +410,7 @@ static struct thermal_cooling_device_ops video_cooling_ops = {
/* device */
static int
-acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
+acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state)
{
int status;
@@ -421,7 +421,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
static int
acpi_video_device_get_state(struct acpi_video_device *device,
- unsigned long *state)
+ unsigned long long *state)
{
int status;
@@ -436,7 +436,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state)
int status;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
- unsigned long ret;
+ unsigned long long ret;
arg0.integer.value = state;
@@ -495,7 +495,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
static int
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
- unsigned long *level)
+ unsigned long long *level)
{
if (device->cap._BQC)
return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL,
@@ -549,7 +549,7 @@ static int
acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
{
int status;
- unsigned long tmp;
+ unsigned long long tmp;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
@@ -564,7 +564,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
}
static int
-acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
+acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
{
int status;
@@ -575,7 +575,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
static int
acpi_video_bus_POST_options(struct acpi_video_bus *video,
- unsigned long *options)
+ unsigned long long *options)
{
int status;
@@ -918,7 +918,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
{
int status;
struct acpi_video_device *dev = seq->private;
- unsigned long state;
+ unsigned long long state;
if (!dev)
@@ -927,14 +927,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
status = acpi_video_device_get_state(dev, &state);
seq_printf(seq, "state: ");
if (ACPI_SUCCESS(status))
- seq_printf(seq, "0x%02lx\n", state);
+ seq_printf(seq, "0x%02llx\n", state);
else
seq_printf(seq, "<not supported>\n");
status = acpi_video_device_query(dev, &state);
seq_printf(seq, "query: ");
if (ACPI_SUCCESS(status))
- seq_printf(seq, "0x%02lx\n", state);
+ seq_printf(seq, "0x%02llx\n", state);
else
seq_printf(seq, "<not supported>\n");
@@ -1217,7 +1217,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_video_bus *video = seq->private;
- unsigned long options;
+ unsigned long long options;
int status;
@@ -1232,7 +1232,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
printk(KERN_WARNING PREFIX
"This indicates a BIOS bug. Please contact the manufacturer.\n");
}
- printk("%lx\n", options);
+ printk("%llx\n", options);
seq_printf(seq, "can POST: <integrated video>");
if (options & 2)
seq_printf(seq, " <PCI video>");
@@ -1256,7 +1256,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_video_bus *video = seq->private;
int status;
- unsigned long id;
+ unsigned long long id;
if (!video)
@@ -1303,7 +1303,7 @@ acpi_video_bus_write_POST(struct file *file,
struct seq_file *m = file->private_data;
struct acpi_video_bus *video = m->private;
char str[12] = { 0 };
- unsigned long opt, options;
+ unsigned long long opt, options;
if (!video || count + 1 > sizeof str)
@@ -1473,7 +1473,7 @@ static int
acpi_video_bus_get_one_device(struct acpi_device *device,
struct acpi_video_bus *video)
{
- unsigned long device_id;
+ unsigned long long device_id;
int status;
struct acpi_video_device *data;
struct acpi_video_device_attrib* attribute;
@@ -1491,7 +1491,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
- acpi_driver_data(device) = data;
+ device->driver_data = data;
data->device_id = device_id;
data->video = video;
@@ -1530,8 +1530,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
acpi_video_device_notify,
data);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ printk(KERN_ERR PREFIX
+ "Error installing notify handler\n");
if(data->brightness)
kfree(data->brightness->levels);
kfree(data->brightness);
@@ -1724,7 +1724,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
static void
acpi_video_switch_brightness(struct acpi_video_device *device, int event)
{
- unsigned long level_current, level_next;
+ unsigned long long level_current, level_next;
if (!device->brightness)
return;
acpi_video_device_lcd_get_level_current(device, &level_current);
@@ -1745,8 +1745,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Cant attach device"));
+ printk(KERN_WARNING PREFIX
+ "Cant attach device");
continue;
}
}
@@ -1982,7 +1982,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
video->device = device;
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
- acpi_driver_data(device) = video;
+ device->driver_data = video;
acpi_video_bus_find_cap(video);
error = acpi_video_bus_check(video);
@@ -2003,8 +2003,8 @@ static int acpi_video_bus_add(struct acpi_device *device)
ACPI_DEVICE_NOTIFY,
acpi_video_bus_notify, video);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ printk(KERN_ERR PREFIX
+ "Error installing notify handler\n");
error = -ENODEV;
goto err_stop_video;
}
@@ -2058,7 +2058,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
acpi_video_bus_remove_fs(device);
err_free_video:
kfree(video);
- acpi_driver_data(device) = NULL;
+ device->driver_data = NULL;
return error;
}
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
index cfe2c833474..47cd7baf9b1 100644
--- a/drivers/acpi/wmi.c
+++ b/drivers/acpi/wmi.c
@@ -217,6 +217,35 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
return 0;
}
+static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
+{
+ struct guid_block *block = NULL;
+ char method[5];
+ struct acpi_object_list input;
+ union acpi_object params[1];
+ acpi_status status;
+ acpi_handle handle;
+
+ block = &wblock->gblock;
+ handle = wblock->handle;
+
+ if (!block)
+ return AE_NOT_EXIST;
+
+ input.count = 1;
+ input.pointer = params;
+ params[0].type = ACPI_TYPE_INTEGER;
+ params[0].integer.value = enable;
+
+ snprintf(method, 5, "WE%02X", block->notify_id);
+ status = acpi_evaluate_object(handle, method, &input, NULL);
+
+ if (status != AE_OK && status != AE_NOT_FOUND)
+ return status;
+ else
+ return AE_OK;
+}
+
/*
* Exported WMI functions
*/
@@ -242,7 +271,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
char method[4] = "WM";
if (!find_guid(guid_string, &wblock))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@@ -304,7 +333,7 @@ struct acpi_buffer *out)
return AE_BAD_PARAMETER;
if (!find_guid(guid_string, &wblock))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@@ -314,7 +343,7 @@ struct acpi_buffer *out)
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
input.count = 1;
input.pointer = wq_params;
@@ -385,7 +414,7 @@ const struct acpi_buffer *in)
return AE_BAD_DATA;
if (!find_guid(guid_string, &wblock))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
block = &wblock->gblock;
handle = wblock->handle;
@@ -395,7 +424,7 @@ const struct acpi_buffer *in)
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
input.count = 2;
input.pointer = params;
@@ -427,6 +456,7 @@ acpi_status wmi_install_notify_handler(const char *guid,
wmi_notify_handler handler, void *data)
{
struct wmi_block *block;
+ acpi_status status;
if (!guid || !handler)
return AE_BAD_PARAMETER;
@@ -441,7 +471,9 @@ wmi_notify_handler handler, void *data)
block->handler = handler;
block->handler_data = data;
- return AE_OK;
+ status = wmi_method_enable(block, 1);
+
+ return status;
}
EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
@@ -453,6 +485,7 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
acpi_status wmi_remove_notify_handler(const char *guid)
{
struct wmi_block *block;
+ acpi_status status;
if (!guid)
return AE_BAD_PARAMETER;
@@ -464,10 +497,12 @@ acpi_status wmi_remove_notify_handler(const char *guid)
if (!block->handler)
return AE_NULL_ENTRY;
+ status = wmi_method_enable(block, 0);
+
block->handler = NULL;
block->handler_data = NULL;
- return AE_OK;
+ return status;
}
EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 9330b7922f6..c012307d0ba 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -120,21 +120,6 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
}
-static void ata_acpi_eject_device(acpi_handle handle)
-{
- struct acpi_object_list arg_list;
- union acpi_object arg;
-
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
- &arg_list, NULL)))
- printk(KERN_ERR "Failed to evaluate _EJ0!\n");
-}
-
/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
{
@@ -157,7 +142,6 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* @ap: ATA port ACPI event occurred
* @dev: ATA device ACPI event occurred (can be NULL)
* @event: ACPI event which occurred
- * @is_dock_event: boolean indicating whether the event was a dock one
*
* All ACPI bay / device realted events end up in this function. If
* the event is port-wide @dev is NULL. If the event is specific to a
@@ -171,117 +155,100 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* ACPI notify handler context. May sleep.
*/
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
- u32 event, int is_dock_event)
+ u32 event)
{
- char event_string[12];
- char *envp[] = { event_string, NULL };
struct ata_eh_info *ehi = &ap->link.eh_info;
- struct kobject *kobj = NULL;
int wait = 0;
unsigned long flags;
- acpi_handle handle, tmphandle;
- unsigned long sta;
- acpi_status status;
+ acpi_handle handle;
- if (dev) {
- if (dev->sdev)
- kobj = &dev->sdev->sdev_gendev.kobj;
+ if (dev)
handle = dev->acpi_handle;
- } else {
- kobj = &ap->dev->kobj;
+ else
handle = ap->acpi_handle;
- }
-
- status = acpi_get_handle(handle, "_EJ0", &tmphandle);
- if (ACPI_FAILURE(status))
- /* This device does not support hotplug */
- return;
-
- if (event == ACPI_NOTIFY_BUS_CHECK ||
- event == ACPI_NOTIFY_DEVICE_CHECK)
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
spin_lock_irqsave(ap->lock, flags);
-
+ /*
+ * When dock driver calls into the routine, it will always use
+ * ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
+ * ACPI_NOTIFY_EJECT_REQUEST for remove
+ */
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
ata_ehi_push_desc(ehi, "ACPI event");
- if (ACPI_FAILURE(status)) {
- ata_port_printk(ap, KERN_ERR,
- "acpi: failed to determine bay status (0x%x)\n",
- status);
- break;
- }
-
- if (sta) {
- ata_ehi_hotplugged(ehi);
- ata_port_freeze(ap);
- } else {
- /* The device has gone - unplug it */
- ata_acpi_detach_device(ap, dev);
- wait = 1;
- }
+ ata_ehi_hotplugged(ehi);
+ ata_port_freeze(ap);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
ata_ehi_push_desc(ehi, "ACPI event");
- if (!is_dock_event)
- break;
-
- /* undock event - immediate unplug */
ata_acpi_detach_device(ap, dev);
wait = 1;
break;
}
- /* make sure kobj doesn't go away while ap->lock is released */
- kobject_get(kobj);
-
spin_unlock_irqrestore(ap->lock, flags);
- if (wait) {
+ if (wait)
ata_port_wait_eh(ap);
- ata_acpi_eject_device(handle);
- }
-
- if (kobj && !is_dock_event) {
- sprintf(event_string, "BAY_EVENT=%d", event);
- kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
- }
-
- kobject_put(kobj);
}
static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
{
struct ata_device *dev = data;
- ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1);
+ ata_acpi_handle_hotplug(dev->link->ap, dev, event);
}
static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
- ata_acpi_handle_hotplug(ap, NULL, event, 1);
+ ata_acpi_handle_hotplug(ap, NULL, event);
}
-static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
+ u32 event)
{
- struct ata_device *dev = data;
+ struct kobject *kobj = NULL;
+ char event_string[20];
+ char *envp[] = { event_string, NULL };
+
+ if (dev) {
+ if (dev->sdev)
+ kobj = &dev->sdev->sdev_gendev.kobj;
+ } else
+ kobj = &ap->dev->kobj;
- ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0);
+ if (kobj) {
+ snprintf(event_string, 20, "BAY_EVENT=%d", event);
+ kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
+ }
}
-static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
{
- struct ata_port *ap = data;
+ ata_acpi_uevent(data, NULL, event);
+}
- ata_acpi_handle_hotplug(ap, NULL, event, 0);
+static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_device *dev = data;
+ ata_acpi_uevent(dev->link->ap, dev, event);
}
+static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
+ .handler = ata_acpi_dev_notify_dock,
+ .uevent = ata_acpi_dev_uevent,
+};
+
+static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
+ .handler = ata_acpi_ap_notify_dock,
+ .uevent = ata_acpi_ap_uevent,
+};
+
/**
* ata_acpi_associate - associate ATA host with ACPI objects
* @host: target ATA host
@@ -315,24 +282,18 @@ void ata_acpi_associate(struct ata_host *host)
ata_acpi_associate_ide_port(ap);
if (ap->acpi_handle) {
- acpi_install_notify_handler(ap->acpi_handle,
- ACPI_SYSTEM_NOTIFY,
- ata_acpi_ap_notify, ap);
/* we might be on a docking station */
register_hotplug_dock_device(ap->acpi_handle,
- ata_acpi_ap_notify_dock, ap);
+ &ata_acpi_ap_dock_ops, ap);
}
for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
struct ata_device *dev = &ap->link.device[j];
if (dev->acpi_handle) {
- acpi_install_notify_handler(dev->acpi_handle,
- ACPI_SYSTEM_NOTIFY,
- ata_acpi_dev_notify, dev);
/* we might be on a docking station */
register_hotplug_dock_device(dev->acpi_handle,
- ata_acpi_dev_notify_dock, dev);
+ &ata_acpi_dev_dock_ops, dev);
}
}
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 1ee9499bd34..8cb0b360bfd 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1713,8 +1713,6 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
else
tag = 0;
- if (test_and_set_bit(tag, &ap->qc_allocated))
- BUG();
qc = __ata_qc_from_tag(ap, tag);
qc->tag = tag;
@@ -4553,37 +4551,6 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
}
/**
- * ata_qc_new - Request an available ATA command, for queueing
- * @ap: Port associated with device @dev
- * @dev: Device from whom we request an available command structure
- *
- * LOCKING:
- * None.
- */
-
-static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
-{
- struct ata_queued_cmd *qc = NULL;
- unsigned int i;
-
- /* no command while frozen */
- if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
- return NULL;
-
- /* the last tag is reserved for internal command. */
- for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
- if (!test_and_set_bit(i, &ap->qc_allocated)) {
- qc = __ata_qc_from_tag(ap, i);
- break;
- }
-
- if (qc)
- qc->tag = i;
-
- return qc;
-}
-
-/**
* ata_qc_new_init - Request an available ATA command, and initialize it
* @dev: Device from whom we request an available command structure
*
@@ -4591,16 +4558,20 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
* None.
*/
-struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
+struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
{
struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
- qc = ata_qc_new(ap);
+ if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+ return NULL;
+
+ qc = __ata_qc_from_tag(ap, tag);
if (qc) {
qc->scsicmd = NULL;
qc->ap = ap;
qc->dev = dev;
+ qc->tag = tag;
ata_qc_reinit(qc);
}
@@ -4608,31 +4579,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
return qc;
}
-/**
- * ata_qc_free - free unused ata_queued_cmd
- * @qc: Command to complete
- *
- * Designed to free unused ata_queued_cmd object
- * in case something prevents using it.
- *
- * LOCKING:
- * spin_lock_irqsave(host lock)
- */
-void ata_qc_free(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- unsigned int tag;
-
- WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
-
- qc->flags = 0;
- tag = qc->tag;
- if (likely(ata_tag_valid(tag))) {
- qc->tag = ATA_TAG_POISON;
- clear_bit(tag, &ap->qc_allocated);
- }
-}
-
void __ata_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@@ -5373,6 +5319,8 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
#ifdef CONFIG_ATA_SFF
INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
+#else
+ INIT_DELAYED_WORK(&ap->port_task, NULL);
#endif
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index a93247cc395..5d687d7cffa 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1206,7 +1206,10 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
ata_eh_clear_action(link, dev, ehi, action);
- if (!(ehc->i.flags & ATA_EHI_QUIET))
+ /* About to take EH action, set RECOVERED. Ignore actions on
+ * slave links as master will do them again.
+ */
+ if (!(ehc->i.flags & ATA_EHI_QUIET) && link != ap->slave_link)
ap->pflags |= ATA_PFLAG_RECOVERED;
spin_unlock_irqrestore(ap->lock, flags);
@@ -2010,8 +2013,13 @@ void ata_eh_autopsy(struct ata_port *ap)
struct ata_eh_context *mehc = &ap->link.eh_context;
struct ata_eh_context *sehc = &ap->slave_link->eh_context;
+ /* transfer control flags from master to slave */
+ sehc->i.flags |= mehc->i.flags & ATA_EHI_TO_SLAVE_MASK;
+
+ /* perform autopsy on the slave link */
ata_eh_link_autopsy(ap->slave_link);
+ /* transfer actions from slave to master and clear slave */
ata_eh_about_to_do(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS);
mehc->i.action |= sehc->i.action;
mehc->i.dev_action[1] |= sehc->i.dev_action[1];
@@ -2447,14 +2455,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
dev->pio_mode = XFER_PIO_0;
dev->flags &= ~ATA_DFLAG_SLEEPING;
- if (ata_phys_link_offline(ata_dev_phys_link(dev)))
- continue;
-
- /* apply class override */
- if (lflags & ATA_LFLAG_ASSUME_ATA)
- classes[dev->devno] = ATA_DEV_ATA;
- else if (lflags & ATA_LFLAG_ASSUME_SEMB)
- classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */
+ if (!ata_phys_link_offline(ata_dev_phys_link(dev))) {
+ /* apply class override */
+ if (lflags & ATA_LFLAG_ASSUME_ATA)
+ classes[dev->devno] = ATA_DEV_ATA;
+ else if (lflags & ATA_LFLAG_ASSUME_SEMB)
+ classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
+ } else
+ classes[dev->devno] = ATA_DEV_NONE;
}
/* record current link speed */
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 5d312dc9be9..4b95c4387e9 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -708,7 +708,11 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
{
struct ata_queued_cmd *qc;
- qc = ata_qc_new_init(dev);
+ if (cmd->request->tag != -1)
+ qc = ata_qc_new_init(dev, cmd->request->tag);
+ else
+ qc = ata_qc_new_init(dev, 0);
+
if (qc) {
qc->scsicmd = cmd;
qc->scsidone = done;
@@ -1103,7 +1107,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
depth = min(ATA_MAX_QUEUE - 1, depth);
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+ scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
+ scsi_activate_tcq(sdev, depth);
}
return 0;
@@ -1943,6 +1948,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
hdr[1] |= (1 << 7);
memcpy(rbuf, hdr, sizeof(hdr));
+
+ /* if ncq, set tags supported */
+ if (ata_id_has_ncq(args->id))
+ rbuf[7] |= (1 << 1);
+
memcpy(&rbuf[8], "ATA ", 8);
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 2a4c516894f..4b473948632 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -2153,8 +2153,17 @@ void ata_sff_error_handler(struct ata_port *ap)
*/
void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
{
- if (qc->ap->ioaddr.bmdma_addr)
+ struct ata_port *ap = qc->ap;
+ unsigned long flags;
+
+ spin_lock_irqsave(ap->lock, flags);
+
+ ap->hsm_task_state = HSM_ST_IDLE;
+
+ if (ap->ioaddr.bmdma_addr)
ata_bmdma_stop(qc);
+
+ spin_unlock_irqrestore(ap->lock, flags);
}
/**
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index fe2839e5877..d3831d39bda 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -74,7 +74,7 @@ extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
extern void ata_force_cbl(struct ata_port *ap);
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
-extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
unsigned int tag);
@@ -103,7 +103,6 @@ extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
extern void ata_sg_clean(struct ata_queued_cmd *qc);
-extern void ata_qc_free(struct ata_queued_cmd *qc);
extern void ata_qc_issue(struct ata_queued_cmd *qc);
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern int atapi_check_dma(struct ata_queued_cmd *qc);
@@ -119,6 +118,22 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
+/**
+ * ata_qc_free - free unused ata_queued_cmd
+ * @qc: Command to complete
+ *
+ * Designed to free unused ata_queued_cmd object
+ * in case something prevents using it.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static inline void ata_qc_free(struct ata_queued_cmd *qc)
+{
+ qc->flags = 0;
+ qc->tag = ATA_TAG_POISON;
+}
+
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
extern void ata_acpi_associate_sata_port(struct ata_port *ap);
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1cfa74535d9..5b72e734300 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -70,6 +70,7 @@ enum {
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
+static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
static void svia_noop_freeze(struct ata_port *ap);
static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
static int vt6421_pata_cable_detect(struct ata_port *ap);
@@ -103,21 +104,26 @@ static struct scsi_host_template svia_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
-static struct ata_port_operations vt6420_sata_ops = {
+static struct ata_port_operations svia_base_ops = {
.inherits = &ata_bmdma_port_ops,
+ .sff_tf_load = svia_tf_load,
+};
+
+static struct ata_port_operations vt6420_sata_ops = {
+ .inherits = &svia_base_ops,
.freeze = svia_noop_freeze,
.prereset = vt6420_prereset,
};
static struct ata_port_operations vt6421_pata_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &svia_base_ops,
.cable_detect = vt6421_pata_cable_detect,
.set_piomode = vt6421_set_pio_mode,
.set_dmamode = vt6421_set_dma_mode,
};
static struct ata_port_operations vt6421_sata_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &svia_base_ops,
.scr_read = svia_scr_read,
.scr_write = svia_scr_write,
};
@@ -168,6 +174,29 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
return 0;
}
+/**
+ * svia_tf_load - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+ * Outputs ATA taskfile to standard ATA host controller.
+ *
+ * This is to fix the internal bug of via chipsets, which will
+ * reset the device register after changing the IEN bit on ctl
+ * register.
+ */
+static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+ struct ata_taskfile ttf;
+
+ if (tf->ctl != ap->last_ctl) {
+ ttf = *tf;
+ ttf.flags |= ATA_TFLAG_DEVICE;
+ tf = &ttf;
+ }
+ ata_sff_tf_load(ap, tf);
+}
+
static void svia_noop_freeze(struct ata_port *ap)
{
/* Some VIA controllers choke if ATA_NIEN is manipulated in
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index af0d175c025..5260e9e0df4 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -21,6 +21,8 @@
#include <linux/memory_hotplug.h>
#include <linux/mm.h>
#include <linux/mutex.h>
+#include <linux/stat.h>
+
#include <asm/atomic.h>
#include <asm/uaccess.h>
@@ -325,7 +327,7 @@ memory_probe_store(struct class *class, const char *buf, size_t count)
return count;
}
-static CLASS_ATTR(probe, 0700, NULL, memory_probe_store);
+static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
static int memory_probe_init(void)
{
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 5116b78c632..f5207090885 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -13,6 +13,7 @@
#include <linux/nodemask.h>
#include <linux/cpu.h>
#include <linux/device.h>
+#include <linux/swap.h>
static struct sysdev_class node_class = {
.name = "node",
@@ -61,34 +62,52 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
si_meminfo_node(&i, nid);
n = sprintf(buf, "\n"
- "Node %d MemTotal: %8lu kB\n"
- "Node %d MemFree: %8lu kB\n"
- "Node %d MemUsed: %8lu kB\n"
- "Node %d Active: %8lu kB\n"
- "Node %d Inactive: %8lu kB\n"
+ "Node %d MemTotal: %8lu kB\n"
+ "Node %d MemFree: %8lu kB\n"
+ "Node %d MemUsed: %8lu kB\n"
+ "Node %d Active: %8lu kB\n"
+ "Node %d Inactive: %8lu kB\n"
+ "Node %d Active(anon): %8lu kB\n"
+ "Node %d Inactive(anon): %8lu kB\n"
+ "Node %d Active(file): %8lu kB\n"
+ "Node %d Inactive(file): %8lu kB\n"
+#ifdef CONFIG_UNEVICTABLE_LRU
+ "Node %d Unevictable: %8lu kB\n"
+ "Node %d Mlocked: %8lu kB\n"
+#endif
#ifdef CONFIG_HIGHMEM
- "Node %d HighTotal: %8lu kB\n"
- "Node %d HighFree: %8lu kB\n"
- "Node %d LowTotal: %8lu kB\n"
- "Node %d LowFree: %8lu kB\n"
+ "Node %d HighTotal: %8lu kB\n"
+ "Node %d HighFree: %8lu kB\n"
+ "Node %d LowTotal: %8lu kB\n"
+ "Node %d LowFree: %8lu kB\n"
#endif
- "Node %d Dirty: %8lu kB\n"
- "Node %d Writeback: %8lu kB\n"
- "Node %d FilePages: %8lu kB\n"
- "Node %d Mapped: %8lu kB\n"
- "Node %d AnonPages: %8lu kB\n"
- "Node %d PageTables: %8lu kB\n"
- "Node %d NFS_Unstable: %8lu kB\n"
- "Node %d Bounce: %8lu kB\n"
- "Node %d WritebackTmp: %8lu kB\n"
- "Node %d Slab: %8lu kB\n"
- "Node %d SReclaimable: %8lu kB\n"
- "Node %d SUnreclaim: %8lu kB\n",
+ "Node %d Dirty: %8lu kB\n"
+ "Node %d Writeback: %8lu kB\n"
+ "Node %d FilePages: %8lu kB\n"
+ "Node %d Mapped: %8lu kB\n"
+ "Node %d AnonPages: %8lu kB\n"
+ "Node %d PageTables: %8lu kB\n"
+ "Node %d NFS_Unstable: %8lu kB\n"
+ "Node %d Bounce: %8lu kB\n"
+ "Node %d WritebackTmp: %8lu kB\n"
+ "Node %d Slab: %8lu kB\n"
+ "Node %d SReclaimable: %8lu kB\n"
+ "Node %d SUnreclaim: %8lu kB\n",
nid, K(i.totalram),
nid, K(i.freeram),
nid, K(i.totalram - i.freeram),
- nid, K(node_page_state(nid, NR_ACTIVE)),
- nid, K(node_page_state(nid, NR_INACTIVE)),
+ nid, K(node_page_state(nid, NR_ACTIVE_ANON) +
+ node_page_state(nid, NR_ACTIVE_FILE)),
+ nid, K(node_page_state(nid, NR_INACTIVE_ANON) +
+ node_page_state(nid, NR_INACTIVE_FILE)),
+ nid, K(node_page_state(nid, NR_ACTIVE_ANON)),
+ nid, K(node_page_state(nid, NR_INACTIVE_ANON)),
+ nid, K(node_page_state(nid, NR_ACTIVE_FILE)),
+ nid, K(node_page_state(nid, NR_INACTIVE_FILE)),
+#ifdef CONFIG_UNEVICTABLE_LRU
+ nid, K(node_page_state(nid, NR_UNEVICTABLE)),
+ nid, K(node_page_state(nid, NR_MLOCK)),
+#endif
#ifdef CONFIG_HIGHMEM
nid, K(i.totalhigh),
nid, K(i.freehigh),
@@ -173,6 +192,8 @@ int register_node(struct node *node, int num, struct node *parent)
sysdev_create_file(&node->sysdev, &attr_meminfo);
sysdev_create_file(&node->sysdev, &attr_numastat);
sysdev_create_file(&node->sysdev, &attr_distance);
+
+ scan_unevictable_register_node(node);
}
return error;
}
@@ -192,6 +213,8 @@ void unregister_node(struct node *node)
sysdev_remove_file(&node->sysdev, &attr_numastat);
sysdev_remove_file(&node->sysdev, &attr_distance);
+ scan_unevictable_unregister_node(node);
+
sysdev_unregister(&node->sysdev);
}
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index a002a381df9..f6a337c34ac 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -72,9 +72,9 @@ static long disk_size(DAC960_Controller_T *p, int drive_nr)
}
}
-static int DAC960_open(struct inode *inode, struct file *file)
+static int DAC960_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
DAC960_Controller_T *p = disk->queue->queuedata;
int drive_nr = (long)disk->private_data;
@@ -89,7 +89,7 @@ static int DAC960_open(struct inode *inode, struct file *file)
return -ENXIO;
}
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
if (!get_capacity(p->disks[drive_nr]))
return -ENXIO;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 7516baff3bb..4b1d4ac960f 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1437,10 +1437,11 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int fd_ioctl(struct inode *inode, struct file *filp,
+static int fd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long param)
{
- int drive = iminor(inode) & 3;
+ struct amiga_floppy_struct *p = bdev->bd_disk->private_data;
+ int drive = p - unit;
static struct floppy_struct getprm;
void __user *argp = (void __user *)param;
@@ -1451,7 +1452,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
rel_fdc();
return -EBUSY;
}
- fsync_bdev(inode->i_bdev);
+ fsync_bdev(bdev);
if (fd_motor_on(drive) == 0) {
rel_fdc();
return -ENODEV;
@@ -1464,12 +1465,12 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
rel_fdc();
break;
case FDFMTTRK:
- if (param < unit[drive].type->tracks * unit[drive].type->heads)
+ if (param < p->type->tracks * p->type->heads)
{
get_fdc(drive);
if (fd_seek(drive,param) != 0){
- memset(unit[drive].trackbuf, FD_FILL_BYTE,
- unit[drive].dtype->sects * unit[drive].type->sect_mult * 512);
+ memset(p->trackbuf, FD_FILL_BYTE,
+ p->dtype->sects * p->type->sect_mult * 512);
non_int_flush_track(drive);
}
floppy_off(drive);
@@ -1480,14 +1481,14 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
break;
case FDFMTEND:
floppy_off(drive);
- invalidate_bdev(inode->i_bdev);
+ invalidate_bdev(bdev);
break;
case FDGETPRM:
memset((void *)&getprm, 0, sizeof (getprm));
- getprm.track=unit[drive].type->tracks;
- getprm.head=unit[drive].type->heads;
- getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult;
- getprm.size=unit[drive].blocks;
+ getprm.track=p->type->tracks;
+ getprm.head=p->type->heads;
+ getprm.sect=p->dtype->sects * p->type->sect_mult;
+ getprm.size=p->blocks;
if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct)))
return -EFAULT;
break;
@@ -1500,10 +1501,10 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
break;
#ifdef RAW_IOCTL
case IOCTL_RAW_TRACK:
- if (copy_to_user(argp, raw_buf, unit[drive].type->read_size))
+ if (copy_to_user(argp, raw_buf, p->type->read_size))
return -EFAULT;
else
- return unit[drive].type->read_size;
+ return p->type->read_size;
#endif
default:
printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",
@@ -1548,10 +1549,10 @@ static void fd_probe(int dev)
* /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers.
*/
-static int floppy_open(struct inode *inode, struct file *filp)
+static int floppy_open(struct block_device *bdev, fmode_t mode)
{
- int drive = iminor(inode) & 3;
- int system = (iminor(inode) & 4) >> 2;
+ int drive = MINOR(bdev->bd_dev) & 3;
+ int system = (MINOR(bdev->bd_dev) & 4) >> 2;
int old_dev;
unsigned long flags;
@@ -1560,9 +1561,9 @@ static int floppy_open(struct inode *inode, struct file *filp)
if (fd_ref[drive] && old_dev != system)
return -EBUSY;
- if (filp && filp->f_mode & 3) {
- check_disk_change(inode->i_bdev);
- if (filp->f_mode & 2 ) {
+ if (mode & (FMODE_READ|FMODE_WRITE)) {
+ check_disk_change(bdev);
+ if (mode & FMODE_WRITE) {
int wrprot;
get_fdc(drive);
@@ -1592,9 +1593,10 @@ static int floppy_open(struct inode *inode, struct file *filp)
return 0;
}
-static int floppy_release(struct inode * inode, struct file * filp)
+static int floppy_release(struct gendisk *disk, fmode_t mode)
{
- int drive = iminor(inode) & 3;
+ struct amiga_floppy_struct *p = disk->private_data;
+ int drive = p - unit;
if (unit[drive].dirty == 1) {
del_timer (flush_track_timer + drive);
@@ -1650,7 +1652,7 @@ static struct block_device_operations floppy_fops = {
.owner = THIS_MODULE,
.open = floppy_open,
.release = floppy_release,
- .ioctl = fd_ioctl,
+ .locked_ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = amiga_floppy_change,
};
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index b82654e883a..1747dd272cd 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -90,7 +90,7 @@ static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
static struct device_attribute dev_attr_firmware_version = {
- .attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE },
+ .attr = { .name = "firmware-version", .mode = S_IRUGO },
.show = aoedisk_show_fwver,
};
@@ -118,13 +118,11 @@ aoedisk_rm_sysfs(struct aoedev *d)
}
static int
-aoeblk_open(struct inode *inode, struct file *filp)
+aoeblk_open(struct block_device *bdev, fmode_t mode)
{
- struct aoedev *d;
+ struct aoedev *d = bdev->bd_disk->private_data;
ulong flags;
- d = inode->i_bdev->bd_disk->private_data;
-
spin_lock_irqsave(&d->lock, flags);
if (d->flags & DEVFL_UP) {
d->nopen++;
@@ -136,13 +134,11 @@ aoeblk_open(struct inode *inode, struct file *filp)
}
static int
-aoeblk_release(struct inode *inode, struct file *filp)
+aoeblk_release(struct gendisk *disk, fmode_t mode)
{
- struct aoedev *d;
+ struct aoedev *d = disk->private_data;
ulong flags;
- d = inode->i_bdev->bd_disk->private_data;
-
spin_lock_irqsave(&d->lock, flags);
if (--d->nopen == 0) {
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 432cf401829..69e1df7dfa1 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -361,13 +361,13 @@ static void finish_fdc( void );
static void finish_fdc_done( int dummy );
static void setup_req_params( int drive );
static void redo_fd_request( void);
-static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int
+static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
cmd, unsigned long param);
static void fd_probe( int drive );
static int fd_test_drive_present( int drive );
static void config_types( void );
-static int floppy_open( struct inode *inode, struct file *filp );
-static int floppy_release( struct inode * inode, struct file * filp );
+static int floppy_open(struct block_device *bdev, fmode_t mode);
+static int floppy_release(struct gendisk *disk, fmode_t mode);
/************************* End of Prototypes **************************/
@@ -1483,10 +1483,10 @@ void do_fd_request(struct request_queue * q)
atari_enable_irq( IRQ_MFP_FDC );
}
-static int fd_ioctl(struct inode *inode, struct file *filp,
+static int fd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long param)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
struct atari_floppy_struct *floppy = disk->private_data;
int drive = floppy - unit;
int type = floppy->type;
@@ -1661,7 +1661,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
/* invalidate the buffer track to force a reread */
BufferDrive = -1;
set_bit(drive, &fake_change);
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
return 0;
default:
return -EINVAL;
@@ -1804,37 +1804,36 @@ static void __init config_types( void )
* drive with different device numbers.
*/
-static int floppy_open( struct inode *inode, struct file *filp )
+static int floppy_open(struct block_device *bdev, fmode_t mode)
{
- struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
- int type = iminor(inode) >> 2;
+ struct atari_floppy_struct *p = bdev->bd_disk->private_data;
+ int type = MINOR(bdev->bd_dev) >> 2;
DPRINT(("fd_open: type=%d\n",type));
if (p->ref && p->type != type)
return -EBUSY;
- if (p->ref == -1 || (p->ref && filp->f_flags & O_EXCL))
+ if (p->ref == -1 || (p->ref && mode & FMODE_EXCL))
return -EBUSY;
- if (filp->f_flags & O_EXCL)
+ if (mode & FMODE_EXCL)
p->ref = -1;
else
p->ref++;
p->type = type;
- if (filp->f_flags & O_NDELAY)
+ if (mode & FMODE_NDELAY)
return 0;
- if (filp->f_mode & 3) {
- check_disk_change(inode->i_bdev);
- if (filp->f_mode & 2) {
+ if (mode & (FMODE_READ|FMODE_WRITE)) {
+ check_disk_change(bdev);
+ if (mode & FMODE_WRITE) {
if (p->wpstat) {
if (p->ref < 0)
p->ref = 0;
else
p->ref--;
- floppy_release(inode, filp);
return -EROFS;
}
}
@@ -1843,9 +1842,9 @@ static int floppy_open( struct inode *inode, struct file *filp )
}
-static int floppy_release( struct inode * inode, struct file * filp )
+static int floppy_release(struct gendisk *disk, fmode_t mode)
{
- struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
+ struct atari_floppy_struct *p = disk->private_data;
if (p->ref < 0)
p->ref = 0;
else if (!p->ref--) {
@@ -1859,7 +1858,7 @@ static struct block_device_operations floppy_fops = {
.owner = THIS_MODULE,
.open = floppy_open,
.release = floppy_release,
- .ioctl = fd_ioctl,
+ .locked_ioctl = fd_ioctl,
.media_changed = check_floppy_change,
.revalidate_disk= floppy_revalidate,
};
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index d070d492e38..bdd4f5f4557 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -340,11 +340,10 @@ static int brd_direct_access (struct block_device *bdev, sector_t sector,
}
#endif
-static int brd_ioctl(struct inode *inode, struct file *file,
+static int brd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
int error;
- struct block_device *bdev = inode->i_bdev;
struct brd_device *brd = bdev->bd_disk->private_data;
if (cmd != BLKFLSBUF)
@@ -376,7 +375,7 @@ static int brd_ioctl(struct inode *inode, struct file *file,
static struct block_device_operations brd_fops = {
.owner = THIS_MODULE,
- .ioctl = brd_ioctl,
+ .locked_ioctl = brd_ioctl,
#ifdef CONFIG_BLK_DEV_XIP
.direct_access = brd_direct_access,
#endif
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1e1f9153000..4023885353e 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -152,9 +152,9 @@ static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(struct request_queue *q);
static irqreturn_t do_cciss_intr(int irq, void *dev_id);
-static int cciss_open(struct inode *inode, struct file *filep);
-static int cciss_release(struct inode *inode, struct file *filep);
-static int cciss_ioctl(struct inode *inode, struct file *filep,
+static int cciss_open(struct block_device *bdev, fmode_t mode);
+static int cciss_release(struct gendisk *disk, fmode_t mode);
+static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg);
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
@@ -192,14 +192,15 @@ static void cciss_procinit(int i)
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_COMPAT
-static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+static int cciss_compat_ioctl(struct block_device *, fmode_t,
+ unsigned, unsigned long);
#endif
static struct block_device_operations cciss_fops = {
.owner = THIS_MODULE,
.open = cciss_open,
.release = cciss_release,
- .ioctl = cciss_ioctl,
+ .locked_ioctl = cciss_ioctl,
.getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = cciss_compat_ioctl,
@@ -547,13 +548,13 @@ static inline drive_info_struct *get_drv(struct gendisk *disk)
/*
* Open. Make sure the device is really there.
*/
-static int cciss_open(struct inode *inode, struct file *filep)
+static int cciss_open(struct block_device *bdev, fmode_t mode)
{
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
- drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
+ ctlr_info_t *host = get_host(bdev->bd_disk);
+ drive_info_struct *drv = get_drv(bdev->bd_disk);
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
+ printk(KERN_DEBUG "cciss_open %s\n", bdev->bd_disk->disk_name);
#endif /* CCISS_DEBUG */
if (host->busy_initializing || drv->busy_configuring)
@@ -567,9 +568,9 @@ static int cciss_open(struct inode *inode, struct file *filep)
* for "raw controller".
*/
if (drv->heads == 0) {
- if (iminor(inode) != 0) { /* not node 0? */
+ if (MINOR(bdev->bd_dev) != 0) { /* not node 0? */
/* if not node 0 make sure it is a partition = 0 */
- if (iminor(inode) & 0x0f) {
+ if (MINOR(bdev->bd_dev) & 0x0f) {
return -ENXIO;
/* if it is, make sure we have a LUN ID */
} else if (drv->LunID == 0) {
@@ -587,14 +588,13 @@ static int cciss_open(struct inode *inode, struct file *filep)
/*
* Close. Sync first.
*/
-static int cciss_release(struct inode *inode, struct file *filep)
+static int cciss_release(struct gendisk *disk, fmode_t mode)
{
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
- drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
+ ctlr_info_t *host = get_host(disk);
+ drive_info_struct *drv = get_drv(disk);
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss_release %s\n",
- inode->i_bdev->bd_disk->disk_name);
+ printk(KERN_DEBUG "cciss_release %s\n", disk->disk_name);
#endif /* CCISS_DEBUG */
drv->usage_count--;
@@ -604,21 +604,23 @@ static int cciss_release(struct inode *inode, struct file *filep)
#ifdef CONFIG_COMPAT
-static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+static int do_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
int ret;
lock_kernel();
- ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
+ ret = cciss_ioctl(bdev, mode, cmd, arg);
unlock_kernel();
return ret;
}
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
- unsigned long arg);
-static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd,
- unsigned long arg);
+static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg);
+static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg);
-static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+static int cciss_compat_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
switch (cmd) {
case CCISS_GETPCIINFO:
@@ -636,20 +638,20 @@ static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
case CCISS_REGNEWD:
case CCISS_RESCANDISK:
case CCISS_GETLUNINFO:
- return do_ioctl(f, cmd, arg);
+ return do_ioctl(bdev, mode, cmd, arg);
case CCISS_PASSTHRU32:
- return cciss_ioctl32_passthru(f, cmd, arg);
+ return cciss_ioctl32_passthru(bdev, mode, cmd, arg);
case CCISS_BIG_PASSTHRU32:
- return cciss_ioctl32_big_passthru(f, cmd, arg);
+ return cciss_ioctl32_big_passthru(bdev, mode, cmd, arg);
default:
return -ENOIOCTLCMD;
}
}
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
- unsigned long arg)
+static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
IOCTL32_Command_struct __user *arg32 =
(IOCTL32_Command_struct __user *) arg;
@@ -676,7 +678,7 @@ static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
if (err)
return -EFAULT;
- err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long)p);
+ err = do_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p);
if (err)
return err;
err |=
@@ -687,8 +689,8 @@ static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
return err;
}
-static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd,
- unsigned long arg)
+static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
BIG_IOCTL32_Command_struct __user *arg32 =
(BIG_IOCTL32_Command_struct __user *) arg;
@@ -717,7 +719,7 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd,
if (err)
return -EFAULT;
- err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long)p);
+ err = do_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p);
if (err)
return err;
err |=
@@ -745,10 +747,9 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
/*
* ioctl
*/
-static int cciss_ioctl(struct inode *inode, struct file *filep,
+static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
ctlr_info_t *host = get_host(disk);
drive_info_struct *drv = get_drv(disk);
@@ -1232,7 +1233,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
case SG_EMULATED_HOST:
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
- return scsi_cmd_ioctl(filep, disk->queue, disk, cmd, argp);
+ return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
/* scsi_cmd_ioctl would normally handle these, below, but */
/* they aren't a good fit for cciss, as CD-ROMs are */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 3d967525e9a..47d233c6d0b 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -156,9 +156,9 @@ static int sendcmd(
unsigned int blkcnt,
unsigned int log_unit );
-static int ida_open(struct inode *inode, struct file *filep);
-static int ida_release(struct inode *inode, struct file *filep);
-static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
+static int ida_open(struct block_device *bdev, fmode_t mode);
+static int ida_release(struct gendisk *disk, fmode_t mode);
+static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg);
static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
@@ -197,7 +197,7 @@ static struct block_device_operations ida_fops = {
.owner = THIS_MODULE,
.open = ida_open,
.release = ida_release,
- .ioctl = ida_ioctl,
+ .locked_ioctl = ida_ioctl,
.getgeo = ida_getgeo,
.revalidate_disk= ida_revalidate,
};
@@ -818,12 +818,12 @@ DBGINFO(
/*
* Open. Make sure the device is really there.
*/
-static int ida_open(struct inode *inode, struct file *filep)
+static int ida_open(struct block_device *bdev, fmode_t mode)
{
- drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+ drv_info_t *drv = get_drv(bdev->bd_disk);
+ ctlr_info_t *host = get_host(bdev->bd_disk);
- DBGINFO(printk("ida_open %s\n", inode->i_bdev->bd_disk->disk_name));
+ DBGINFO(printk("ida_open %s\n", bdev->bd_disk->disk_name));
/*
* Root is allowed to open raw volume zero even if it's not configured
* so array config can still work. I don't think I really like this,
@@ -843,9 +843,9 @@ static int ida_open(struct inode *inode, struct file *filep)
/*
* Close. Sync first.
*/
-static int ida_release(struct inode *inode, struct file *filep)
+static int ida_release(struct gendisk *disk, fmode_t mode)
{
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+ ctlr_info_t *host = get_host(disk);
host->usage_count--;
return 0;
}
@@ -1128,10 +1128,10 @@ static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* ida_ioctl does some miscellaneous stuff like reporting drive geometry,
* setting readahead and submitting commands from userspace to the controller.
*/
-static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
+static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
- drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+ drv_info_t *drv = get_drv(bdev->bd_disk);
+ ctlr_info_t *host = get_host(bdev->bd_disk);
int error;
ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
ida_ioctl_t *my_io;
@@ -1165,7 +1165,7 @@ out_passthru:
put_user(host->ctlr_sig, (int __user *)arg);
return 0;
case IDAREVALIDATEVOLS:
- if (iminor(inode) != 0)
+ if (MINOR(bdev->bd_dev) != 0)
return -ENXIO;
return revalidate_allvol(host);
case IDADRIVERVERSION:
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 2cea27aba9a..14db747a636 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3450,14 +3450,14 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
unsigned long param)
{
-#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
+#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
#define OUT(c,x) case c: outparam = (const char *) (x); break
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
- int drive = (long)inode->i_bdev->bd_disk->private_data;
+ int drive = (long)bdev->bd_disk->private_data;
int type = ITYPE(UDRS->fd_device);
int i;
int ret;
@@ -3516,11 +3516,11 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
current_type[drive] = NULL;
floppy_sizes[drive] = MAX_DISK_SIZE << 1;
UDRS->keep_data = 0;
- return invalidate_drive(inode->i_bdev);
+ return invalidate_drive(bdev);
case FDSETPRM:
case FDDEFPRM:
return set_geometry(cmd, &inparam.g,
- drive, type, inode->i_bdev);
+ drive, type, bdev);
case FDGETPRM:
ECALL(get_floppy_geometry(drive, type,
(struct floppy_struct **)
@@ -3551,7 +3551,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
case FDFMTEND:
case FDFLUSH:
LOCK_FDC(drive, 1);
- return invalidate_drive(inode->i_bdev);
+ return invalidate_drive(bdev);
case FDSETEMSGTRESH:
UDP->max_errors.reporting =
@@ -3659,9 +3659,9 @@ static void __init config_types(void)
printk("\n");
}
-static int floppy_release(struct inode *inode, struct file *filp)
+static int floppy_release(struct gendisk *disk, fmode_t mode)
{
- int drive = (long)inode->i_bdev->bd_disk->private_data;
+ int drive = (long)disk->private_data;
mutex_lock(&open_lock);
if (UDRS->fd_ref < 0)
@@ -3682,18 +3682,17 @@ static int floppy_release(struct inode *inode, struct file *filp)
* /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers.
*/
-static int floppy_open(struct inode *inode, struct file *filp)
+static int floppy_open(struct block_device *bdev, fmode_t mode)
{
- int drive = (long)inode->i_bdev->bd_disk->private_data;
- int old_dev;
+ int drive = (long)bdev->bd_disk->private_data;
+ int old_dev, new_dev;
int try;
int res = -EBUSY;
char *tmp;
- filp->private_data = (void *)0;
mutex_lock(&open_lock);
old_dev = UDRS->fd_device;
- if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
+ if (opened_bdev[drive] && opened_bdev[drive] != bdev)
goto out2;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
@@ -3701,15 +3700,15 @@ static int floppy_open(struct inode *inode, struct file *filp)
USETF(FD_VERIFY);
}
- if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
+ if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL)))
goto out2;
- if (filp->f_flags & O_EXCL)
+ if (mode & FMODE_EXCL)
UDRS->fd_ref = -1;
else
UDRS->fd_ref++;
- opened_bdev[drive] = inode->i_bdev;
+ opened_bdev[drive] = bdev;
res = -ENXIO;
@@ -3744,31 +3743,26 @@ static int floppy_open(struct inode *inode, struct file *filp)
}
}
- UDRS->fd_device = iminor(inode);
- set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
- if (old_dev != -1 && old_dev != iminor(inode)) {
+ new_dev = MINOR(bdev->bd_dev);
+ UDRS->fd_device = new_dev;
+ set_capacity(disks[drive], floppy_sizes[new_dev]);
+ if (old_dev != -1 && old_dev != new_dev) {
if (buffer_drive == drive)
buffer_track = -1;
}
- /* Allow ioctls if we have write-permissions even if read-only open.
- * Needed so that programs such as fdrawcmd still can work on write
- * protected disks */
- if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
- filp->private_data = (void *)8;
-
if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2;
- if (!(filp->f_flags & O_NDELAY)) {
- if (filp->f_mode & 3) {
+ if (!(mode & FMODE_NDELAY)) {
+ if (mode & (FMODE_READ|FMODE_WRITE)) {
UDRS->last_checked = 0;
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
if (UTESTF(FD_DISK_CHANGED))
goto out;
}
res = -EROFS;
- if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+ if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE)))
goto out;
}
mutex_unlock(&open_lock);
@@ -3911,7 +3905,7 @@ static struct block_device_operations floppy_fops = {
.owner = THIS_MODULE,
.open = floppy_open,
.release = floppy_release,
- .ioctl = fd_ioctl,
+ .locked_ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate,
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index d3a25b027ff..3f09cd8bcc3 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -210,7 +210,7 @@ lo_do_transfer(struct loop_device *lo, int cmd,
* space operations write_begin and write_end.
*/
static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
- int bsize, loff_t pos, struct page *unused)
+ loff_t pos, struct page *unused)
{
struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
struct address_space *mapping = file->f_mapping;
@@ -302,7 +302,7 @@ static int __do_lo_send_write(struct file *file,
* filesystems.
*/
static int do_lo_send_direct_write(struct loop_device *lo,
- struct bio_vec *bvec, int bsize, loff_t pos, struct page *page)
+ struct bio_vec *bvec, loff_t pos, struct page *page)
{
ssize_t bw = __do_lo_send_write(lo->lo_backing_file,
kmap(bvec->bv_page) + bvec->bv_offset,
@@ -326,7 +326,7 @@ static int do_lo_send_direct_write(struct loop_device *lo,
* destination pages of the backing file.
*/
static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
- int bsize, loff_t pos, struct page *page)
+ loff_t pos, struct page *page)
{
int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page,
bvec->bv_offset, bvec->bv_len, pos >> 9);
@@ -341,10 +341,9 @@ static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
return ret;
}
-static int lo_send(struct loop_device *lo, struct bio *bio, int bsize,
- loff_t pos)
+static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos)
{
- int (*do_lo_send)(struct loop_device *, struct bio_vec *, int, loff_t,
+ int (*do_lo_send)(struct loop_device *, struct bio_vec *, loff_t,
struct page *page);
struct bio_vec *bvec;
struct page *page = NULL;
@@ -362,7 +361,7 @@ static int lo_send(struct loop_device *lo, struct bio *bio, int bsize,
}
}
bio_for_each_segment(bvec, bio, i) {
- ret = do_lo_send(lo, bvec, bsize, pos, page);
+ ret = do_lo_send(lo, bvec, pos, page);
if (ret < 0)
break;
pos += bvec->bv_len;
@@ -478,7 +477,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
if (bio_rw(bio) == WRITE)
- ret = lo_send(lo, bio, lo->lo_blocksize, pos);
+ ret = lo_send(lo, bio, pos);
else
ret = lo_receive(lo, bio, lo->lo_blocksize, pos);
return ret;
@@ -652,8 +651,8 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
* This can only work if the loop device is used read-only, and if the
* new backing store is the same size and type as the old backing store.
*/
-static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
- struct block_device *bdev, unsigned int arg)
+static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ unsigned int arg)
{
struct file *file, *old_file;
struct inode *inode;
@@ -712,7 +711,7 @@ static inline int is_loop_device(struct file *file)
return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
}
-static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
+static int loop_set_fd(struct loop_device *lo, fmode_t mode,
struct block_device *bdev, unsigned int arg)
{
struct file *file, *f;
@@ -740,7 +739,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
while (is_loop_device(f)) {
struct loop_device *l;
- if (f->f_mapping->host->i_rdev == lo_file->f_mapping->host->i_rdev)
+ if (f->f_mapping->host->i_bdev == bdev)
goto out_putf;
l = f->f_mapping->host->i_bdev->bd_disk->private_data;
@@ -786,7 +785,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
goto out_putf;
}
- if (!(lo_file->f_mode & FMODE_WRITE))
+ if (!(mode & FMODE_WRITE))
lo_flags |= LO_FLAGS_READ_ONLY;
set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
@@ -918,9 +917,11 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
- invalidate_bdev(bdev);
+ if (bdev)
+ invalidate_bdev(bdev);
set_capacity(lo->lo_disk, 0);
- bd_set_size(bdev, 0);
+ if (bdev)
+ bd_set_size(bdev, 0);
mapping_set_gfp_mask(filp->f_mapping, gfp);
lo->lo_state = Lo_unbound;
fput(filp);
@@ -1137,22 +1138,22 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
return err;
}
-static int lo_ioctl(struct inode * inode, struct file * file,
+static int lo_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ struct loop_device *lo = bdev->bd_disk->private_data;
int err;
mutex_lock(&lo->lo_ctl_mutex);
switch (cmd) {
case LOOP_SET_FD:
- err = loop_set_fd(lo, file, inode->i_bdev, arg);
+ err = loop_set_fd(lo, mode, bdev, arg);
break;
case LOOP_CHANGE_FD:
- err = loop_change_fd(lo, file, inode->i_bdev, arg);
+ err = loop_change_fd(lo, bdev, arg);
break;
case LOOP_CLR_FD:
- err = loop_clr_fd(lo, inode->i_bdev);
+ err = loop_clr_fd(lo, bdev);
break;
case LOOP_SET_STATUS:
err = loop_set_status_old(lo, (struct loop_info __user *) arg);
@@ -1292,10 +1293,10 @@ loop_get_status_compat(struct loop_device *lo,
return err;
}
-static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ struct loop_device *lo = bdev->bd_disk->private_data;
int err;
switch(cmd) {
@@ -1317,7 +1318,7 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
arg = (unsigned long) compat_ptr(arg);
case LOOP_SET_FD:
case LOOP_CHANGE_FD:
- err = lo_ioctl(inode, file, cmd, arg);
+ err = lo_ioctl(bdev, mode, cmd, arg);
break;
default:
err = -ENOIOCTLCMD;
@@ -1327,9 +1328,9 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
}
#endif
-static int lo_open(struct inode *inode, struct file *file)
+static int lo_open(struct block_device *bdev, fmode_t mode)
{
- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ struct loop_device *lo = bdev->bd_disk->private_data;
mutex_lock(&lo->lo_ctl_mutex);
lo->lo_refcnt++;
@@ -1338,15 +1339,15 @@ static int lo_open(struct inode *inode, struct file *file)
return 0;
}
-static int lo_release(struct inode *inode, struct file *file)
+static int lo_release(struct gendisk *disk, fmode_t mode)
{
- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ struct loop_device *lo = disk->private_data;
mutex_lock(&lo->lo_ctl_mutex);
--lo->lo_refcnt;
if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt)
- loop_clr_fd(lo, inode->i_bdev);
+ loop_clr_fd(lo, NULL);
mutex_unlock(&lo->lo_ctl_mutex);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7b3351260d5..d3a91cacee8 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -391,7 +391,7 @@ static ssize_t pid_show(struct device *dev,
}
static struct device_attribute pid_attr = {
- .attr = { .name = "pid", .mode = S_IRUGO, .owner = THIS_MODULE },
+ .attr = { .name = "pid", .mode = S_IRUGO},
.show = pid_show,
};
@@ -557,10 +557,11 @@ static void do_nbd_request(struct request_queue * q)
}
}
-static int nbd_ioctl(struct inode *inode, struct file *file,
+static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
+ struct nbd_device *lo = bdev->bd_disk->private_data;
+ struct file *file;
int error;
struct request sreq ;
struct task_struct *thread;
@@ -612,8 +613,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
error = -EINVAL;
file = fget(arg);
if (file) {
- struct block_device *bdev = inode->i_bdev;
- inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
if (S_ISSOCK(inode->i_mode)) {
lo->file = file;
lo->sock = SOCKET_I(inode);
@@ -628,14 +628,14 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
case NBD_SET_BLKSIZE:
lo->blksize = arg;
lo->bytesize &= ~(lo->blksize-1);
- inode->i_bdev->bd_inode->i_size = lo->bytesize;
- set_blocksize(inode->i_bdev, lo->blksize);
+ bdev->bd_inode->i_size = lo->bytesize;
+ set_blocksize(bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_SET_SIZE:
lo->bytesize = arg & ~(lo->blksize-1);
- inode->i_bdev->bd_inode->i_size = lo->bytesize;
- set_blocksize(inode->i_bdev, lo->blksize);
+ bdev->bd_inode->i_size = lo->bytesize;
+ set_blocksize(bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_SET_TIMEOUT:
@@ -643,8 +643,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
return 0;
case NBD_SET_SIZE_BLOCKS:
lo->bytesize = ((u64) arg) * lo->blksize;
- inode->i_bdev->bd_inode->i_size = lo->bytesize;
- set_blocksize(inode->i_bdev, lo->blksize);
+ bdev->bd_inode->i_size = lo->bytesize;
+ set_blocksize(bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_DO_IT:
@@ -666,10 +666,10 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
if (file)
fput(file);
lo->bytesize = 0;
- inode->i_bdev->bd_inode->i_size = 0;
+ bdev->bd_inode->i_size = 0;
set_capacity(lo->disk, 0);
if (max_part > 0)
- ioctl_by_bdev(inode->i_bdev, BLKRRPART, 0);
+ ioctl_by_bdev(bdev, BLKRRPART, 0);
return lo->harderror;
case NBD_CLEAR_QUE:
/*
@@ -680,7 +680,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
return 0;
case NBD_PRINT_DEBUG:
printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
- inode->i_bdev->bd_disk->disk_name,
+ bdev->bd_disk->disk_name,
lo->queue_head.next, lo->queue_head.prev,
&lo->queue_head);
return 0;
@@ -691,7 +691,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
static struct block_device_operations nbd_fops =
{
.owner = THIS_MODULE,
- .ioctl = nbd_ioctl,
+ .locked_ioctl = nbd_ioctl,
};
/*
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index b8a994a2b01..e91d4b4b014 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -223,23 +223,24 @@ static int pcd_warned; /* Have we logged a phase warning ? */
/* kernel glue structures */
-static int pcd_block_open(struct inode *inode, struct file *file)
+static int pcd_block_open(struct block_device *bdev, fmode_t mode)
{
- struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(&cd->info, inode, file);
+ struct pcd_unit *cd = bdev->bd_disk->private_data;
+ return cdrom_open(&cd->info, bdev, mode);
}
-static int pcd_block_release(struct inode *inode, struct file *file)
+static int pcd_block_release(struct gendisk *disk, fmode_t mode)
{
- struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(&cd->info, file);
+ struct pcd_unit *cd = disk->private_data;
+ cdrom_release(&cd->info, mode);
+ return 0;
}
-static int pcd_block_ioctl(struct inode *inode, struct file *file,
+static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg)
{
- struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
- return cdrom_ioctl(file, &cd->info, inode, cmd, arg);
+ struct pcd_unit *cd = bdev->bd_disk->private_data;
+ return cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
}
static int pcd_block_media_changed(struct gendisk *disk)
@@ -252,7 +253,7 @@ static struct block_device_operations pcd_bdops = {
.owner = THIS_MODULE,
.open = pcd_block_open,
.release = pcd_block_release,
- .ioctl = pcd_block_ioctl,
+ .locked_ioctl = pcd_block_ioctl,
.media_changed = pcd_block_media_changed,
};
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 5fdfa7c888c..9299455b0af 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -728,9 +728,9 @@ static int pd_special_command(struct pd_unit *disk,
/* kernel glue structures */
-static int pd_open(struct inode *inode, struct file *file)
+static int pd_open(struct block_device *bdev, fmode_t mode)
{
- struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
+ struct pd_unit *disk = bdev->bd_disk->private_data;
disk->access++;
@@ -758,10 +758,10 @@ static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int pd_ioctl(struct inode *inode, struct file *file,
+static int pd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
+ struct pd_unit *disk = bdev->bd_disk->private_data;
switch (cmd) {
case CDROMEJECT:
@@ -773,9 +773,9 @@ static int pd_ioctl(struct inode *inode, struct file *file,
}
}
-static int pd_release(struct inode *inode, struct file *file)
+static int pd_release(struct gendisk *p, fmode_t mode)
{
- struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
+ struct pd_unit *disk = p->private_data;
if (!--disk->access && disk->removable)
pd_special_command(disk, pd_door_unlock);
@@ -809,7 +809,7 @@ static struct block_device_operations pd_fops = {
.owner = THIS_MODULE,
.open = pd_open,
.release = pd_release,
- .ioctl = pd_ioctl,
+ .locked_ioctl = pd_ioctl,
.getgeo = pd_getgeo,
.media_changed = pd_check_media,
.revalidate_disk= pd_revalidate
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index e7fe6ca97dd..bef3b997ba3 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -201,13 +201,13 @@ module_param_array(drive3, int, NULL, 0);
#define ATAPI_READ_10 0x28
#define ATAPI_WRITE_10 0x2a
-static int pf_open(struct inode *inode, struct file *file);
+static int pf_open(struct block_device *bdev, fmode_t mode);
static void do_pf_request(struct request_queue * q);
-static int pf_ioctl(struct inode *inode, struct file *file,
+static int pf_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg);
static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
-static int pf_release(struct inode *inode, struct file *file);
+static int pf_release(struct gendisk *disk, fmode_t mode);
static int pf_detect(void);
static void do_pf_read(void);
@@ -266,7 +266,7 @@ static struct block_device_operations pf_fops = {
.owner = THIS_MODULE,
.open = pf_open,
.release = pf_release,
- .ioctl = pf_ioctl,
+ .locked_ioctl = pf_ioctl,
.getgeo = pf_getgeo,
.media_changed = pf_check_media,
};
@@ -296,16 +296,16 @@ static void __init pf_init_units(void)
}
}
-static int pf_open(struct inode *inode, struct file *file)
+static int pf_open(struct block_device *bdev, fmode_t mode)
{
- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
+ struct pf_unit *pf = bdev->bd_disk->private_data;
pf_identify(pf);
if (pf->media_status == PF_NM)
return -ENODEV;
- if ((pf->media_status == PF_RO) && (file->f_mode & 2))
+ if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE))
return -EROFS;
pf->access++;
@@ -333,9 +333,9 @@ static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
+ struct pf_unit *pf = bdev->bd_disk->private_data;
if (cmd != CDROMEJECT)
return -EINVAL;
@@ -346,9 +346,9 @@ static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
return 0;
}
-static int pf_release(struct inode *inode, struct file *file)
+static int pf_release(struct gendisk *disk, fmode_t mode)
{
- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
+ struct pf_unit *pf = disk->private_data;
if (pf->access <= 0)
return -EINVAL;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5ae229656ea..1e4006e18f0 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -667,7 +667,7 @@ static int pt_open(struct inode *inode, struct file *file)
goto out;
err = -EROFS;
- if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & 2))
+ if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & FMODE_WRITE))
goto out;
if (!(iminor(inode) & 128))
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 195ca7c720f..f20bf359b84 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2320,7 +2320,7 @@ static int pkt_open_write(struct pktcdvd_device *pd)
/*
* called at open time.
*/
-static int pkt_open_dev(struct pktcdvd_device *pd, int write)
+static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
{
int ret;
long lba;
@@ -2332,7 +2332,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
* so bdget() can't fail.
*/
bdget(pd->bdev->bd_dev);
- if ((ret = blkdev_get(pd->bdev, FMODE_READ, O_RDONLY)))
+ if ((ret = blkdev_get(pd->bdev, FMODE_READ)))
goto out;
if ((ret = bd_claim(pd->bdev, pd)))
@@ -2381,7 +2381,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
out_unclaim:
bd_release(pd->bdev);
out_putdev:
- blkdev_put(pd->bdev);
+ blkdev_put(pd->bdev, FMODE_READ);
out:
return ret;
}
@@ -2399,7 +2399,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
bd_release(pd->bdev);
- blkdev_put(pd->bdev);
+ blkdev_put(pd->bdev, FMODE_READ);
pkt_shrink_pktlist(pd);
}
@@ -2411,7 +2411,7 @@ static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
return pkt_devs[dev_minor];
}
-static int pkt_open(struct inode *inode, struct file *file)
+static int pkt_open(struct block_device *bdev, fmode_t mode)
{
struct pktcdvd_device *pd = NULL;
int ret;
@@ -2419,7 +2419,7 @@ static int pkt_open(struct inode *inode, struct file *file)
VPRINTK(DRIVER_NAME": entering open\n");
mutex_lock(&ctl_mutex);
- pd = pkt_find_dev_from_minor(iminor(inode));
+ pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
if (!pd) {
ret = -ENODEV;
goto out;
@@ -2428,20 +2428,20 @@ static int pkt_open(struct inode *inode, struct file *file)
pd->refcnt++;
if (pd->refcnt > 1) {
- if ((file->f_mode & FMODE_WRITE) &&
+ if ((mode & FMODE_WRITE) &&
!test_bit(PACKET_WRITABLE, &pd->flags)) {
ret = -EBUSY;
goto out_dec;
}
} else {
- ret = pkt_open_dev(pd, file->f_mode & FMODE_WRITE);
+ ret = pkt_open_dev(pd, mode & FMODE_WRITE);
if (ret)
goto out_dec;
/*
* needed here as well, since ext2 (among others) may change
* the blocksize at mount time
*/
- set_blocksize(inode->i_bdev, CD_FRAMESIZE);
+ set_blocksize(bdev, CD_FRAMESIZE);
}
mutex_unlock(&ctl_mutex);
@@ -2455,9 +2455,9 @@ out:
return ret;
}
-static int pkt_close(struct inode *inode, struct file *file)
+static int pkt_close(struct gendisk *disk, fmode_t mode)
{
- struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
+ struct pktcdvd_device *pd = disk->private_data;
int ret = 0;
mutex_lock(&ctl_mutex);
@@ -2765,7 +2765,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
bdev = bdget(dev);
if (!bdev)
return -ENOMEM;
- ret = blkdev_get(bdev, FMODE_READ, O_RDONLY | O_NONBLOCK);
+ ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY);
if (ret)
return ret;
@@ -2790,19 +2790,28 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
return 0;
out_mem:
- blkdev_put(bdev);
+ blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
return ret;
}
-static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
- struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
+ struct pktcdvd_device *pd = bdev->bd_disk->private_data;
- VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
+ VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
+ MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
switch (cmd) {
+ case CDROMEJECT:
+ /*
+ * The door gets locked when the device is opened, so we
+ * have to unlock it or else the eject command fails.
+ */
+ if (pd->refcnt == 1)
+ pkt_lock_door(pd, 0);
+ /* fallthru */
/*
* forward selected CDROM ioctls to CD-ROM, for UDF
*/
@@ -2811,16 +2820,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
case CDROM_LAST_WRITTEN:
case CDROM_SEND_PACKET:
case SCSI_IOCTL_SEND_COMMAND:
- return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
-
- case CDROMEJECT:
- /*
- * The door gets locked when the device is opened, so we
- * have to unlock it or else the eject command fails.
- */
- if (pd->refcnt == 1)
- pkt_lock_door(pd, 0);
- return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+ return __blkdev_driver_ioctl(pd->bdev, mode, cmd, arg);
default:
VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
@@ -2849,7 +2849,7 @@ static struct block_device_operations pktcdvd_ops = {
.owner = THIS_MODULE,
.open = pkt_open,
.release = pkt_close,
- .ioctl = pkt_ioctl,
+ .locked_ioctl = pkt_ioctl,
.media_changed = pkt_media_changed,
};
@@ -2975,7 +2975,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
pkt_debugfs_dev_remove(pd);
pkt_sysfs_dev_remove(pd);
- blkdev_put(pd->bdev);
+ blkdev_put(pd->bdev, FMODE_READ|FMODE_WRITE);
remove_proc_entry(pd->name, pkt_proc);
DPRINTK(DRIVER_NAME": writer %s unmapped\n", pd->name);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 730ccea78e4..612965307ba 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -244,10 +244,10 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible);
static void release_drive(struct floppy_state *fs);
static int fd_eject(struct floppy_state *fs);
-static int floppy_ioctl(struct inode *inode, struct file *filp,
+static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long param);
-static int floppy_open(struct inode *inode, struct file *filp);
-static int floppy_release(struct inode *inode, struct file *filp);
+static int floppy_open(struct block_device *bdev, fmode_t mode);
+static int floppy_release(struct gendisk *disk, fmode_t mode);
static int floppy_check_change(struct gendisk *disk);
static int floppy_revalidate(struct gendisk *disk);
@@ -839,10 +839,10 @@ static int fd_eject(struct floppy_state *fs)
static struct floppy_struct floppy_type =
{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
-static int floppy_ioctl(struct inode *inode, struct file *filp,
+static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long param)
{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ struct floppy_state *fs = bdev->bd_disk->private_data;
int err;
if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
@@ -868,9 +868,9 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
return -ENOTTY;
}
-static int floppy_open(struct inode *inode, struct file *filp)
+static int floppy_open(struct block_device *bdev, fmode_t mode)
{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ struct floppy_state *fs = bdev->bd_disk->private_data;
struct swim3 __iomem *sw = fs->swim3;
int n, err = 0;
@@ -904,17 +904,17 @@ static int floppy_open(struct inode *inode, struct file *filp)
swim3_action(fs, SETMFM);
swim3_select(fs, RELAX);
- } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
+ } else if (fs->ref_count == -1 || mode & FMODE_EXCL)
return -EBUSY;
- if (err == 0 && (filp->f_flags & O_NDELAY) == 0
- && (filp->f_mode & 3)) {
- check_disk_change(inode->i_bdev);
+ if (err == 0 && (mode & FMODE_NDELAY) == 0
+ && (mode & (FMODE_READ|FMODE_WRITE))) {
+ check_disk_change(bdev);
if (fs->ejected)
err = -ENXIO;
}
- if (err == 0 && (filp->f_mode & 2)) {
+ if (err == 0 && (mode & FMODE_WRITE)) {
if (fs->write_prot < 0)
fs->write_prot = swim3_readbit(fs, WRITE_PROT);
if (fs->write_prot)
@@ -930,7 +930,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
return err;
}
- if (filp->f_flags & O_EXCL)
+ if (mode & FMODE_EXCL)
fs->ref_count = -1;
else
++fs->ref_count;
@@ -938,9 +938,9 @@ static int floppy_open(struct inode *inode, struct file *filp)
return 0;
}
-static int floppy_release(struct inode *inode, struct file *filp)
+static int floppy_release(struct gendisk *disk, fmode_t mode)
{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ struct floppy_state *fs = disk->private_data;
struct swim3 __iomem *sw = fs->swim3;
if (fs->ref_count > 0 && --fs->ref_count == 0) {
swim3_action(fs, MOTOR_OFF);
@@ -1000,7 +1000,7 @@ static int floppy_revalidate(struct gendisk *disk)
static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
- .ioctl = floppy_ioctl,
+ .locked_ioctl = floppy_ioctl,
.media_changed = floppy_check_change,
.revalidate_disk= floppy_revalidate,
};
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index f60e41833f6..fccac18d311 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1667,10 +1667,9 @@ static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
* This is mostly needed to keep refcounting, but also to support
* media checks on removable media drives.
*/
-static int ub_bd_open(struct inode *inode, struct file *filp)
+static int ub_bd_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ub_lun *lun = disk->private_data;
+ struct ub_lun *lun = bdev->bd_disk->private_data;
struct ub_dev *sc = lun->udev;
unsigned long flags;
int rc;
@@ -1684,19 +1683,19 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
spin_unlock_irqrestore(&ub_lock, flags);
if (lun->removable || lun->readonly)
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
/*
* The sd.c considers ->media_present and ->changed not equivalent,
* under some pretty murky conditions (a failure of READ CAPACITY).
* We may need it one day.
*/
- if (lun->removable && lun->changed && !(filp->f_flags & O_NDELAY)) {
+ if (lun->removable && lun->changed && !(mode & FMODE_NDELAY)) {
rc = -ENOMEDIUM;
goto err_open;
}
- if (lun->readonly && (filp->f_mode & FMODE_WRITE)) {
+ if (lun->readonly && (mode & FMODE_WRITE)) {
rc = -EROFS;
goto err_open;
}
@@ -1710,9 +1709,8 @@ err_open:
/*
*/
-static int ub_bd_release(struct inode *inode, struct file *filp)
+static int ub_bd_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
struct ub_lun *lun = disk->private_data;
struct ub_dev *sc = lun->udev;
@@ -1723,13 +1721,13 @@ static int ub_bd_release(struct inode *inode, struct file *filp)
/*
* The ioctl interface.
*/
-static int ub_bd_ioctl(struct inode *inode, struct file *filp,
+static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
void __user *usermem = (void __user *) arg;
- return scsi_cmd_ioctl(filp, disk->queue, disk, cmd, usermem);
+ return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
}
/*
@@ -1793,7 +1791,7 @@ static struct block_device_operations ub_bd_fops = {
.owner = THIS_MODULE,
.open = ub_bd_open,
.release = ub_bd_release,
- .ioctl = ub_bd_ioctl,
+ .locked_ioctl = ub_bd_ioctl,
.media_changed = ub_bd_media_changed,
.revalidate_disk = ub_bd_revalidate,
};
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 1730d29e604..ecccf65dce2 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -130,15 +130,15 @@ struct viodasd_device {
/*
* External open entry point.
*/
-static int viodasd_open(struct inode *ino, struct file *fil)
+static int viodasd_open(struct block_device *bdev, fmode_t mode)
{
- struct viodasd_device *d = ino->i_bdev->bd_disk->private_data;
+ struct viodasd_device *d = bdev->bd_disk->private_data;
HvLpEvent_Rc hvrc;
struct viodasd_waitevent we;
u16 flags = 0;
if (d->read_only) {
- if ((fil != NULL) && (fil->f_mode & FMODE_WRITE))
+ if (mode & FMODE_WRITE)
return -EROFS;
flags = vioblockflags_ro;
}
@@ -179,9 +179,9 @@ static int viodasd_open(struct inode *ino, struct file *fil)
/*
* External release entry point.
*/
-static int viodasd_release(struct inode *ino, struct file *fil)
+static int viodasd_release(struct gendisk *disk, fmode_t mode)
{
- struct viodasd_device *d = ino->i_bdev->bd_disk->private_data;
+ struct viodasd_device *d = disk->private_data;
HvLpEvent_Rc hvrc;
/* Send the event to OS/400. We DON'T expect a response */
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 6ec5fc05278..85d79a02d48 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -146,11 +146,11 @@ static void do_virtblk_request(struct request_queue *q)
vblk->vq->vq_ops->kick(vblk->vq);
}
-static int virtblk_ioctl(struct inode *inode, struct file *filp,
+static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long data)
{
- return scsi_cmd_ioctl(filp, inode->i_bdev->bd_disk->queue,
- inode->i_bdev->bd_disk, cmd,
+ return scsi_cmd_ioctl(bdev->bd_disk->queue,
+ bdev->bd_disk, mode, cmd,
(void __user *)data);
}
@@ -180,7 +180,7 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
}
static struct block_device_operations virtblk_fops = {
- .ioctl = virtblk_ioctl,
+ .locked_ioctl = virtblk_ioctl,
.owner = THIS_MODULE,
.getgeo = virtblk_getgeo,
};
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 624d30f7da3..64b496fce98 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -132,7 +132,7 @@ static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static struct block_device_operations xd_fops = {
.owner = THIS_MODULE,
- .ioctl = xd_ioctl,
+ .locked_ioctl = xd_ioctl,
.getgeo = xd_getgeo,
};
static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
@@ -343,7 +343,7 @@ static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
}
/* xd_ioctl: handle device ioctl's */
-static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
+static int xd_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long arg)
{
switch (cmd) {
case HDIO_SET_DMA:
diff --git a/drivers/block/xd.h b/drivers/block/xd.h
index cffd44a2038..37cacef16e9 100644
--- a/drivers/block/xd.h
+++ b/drivers/block/xd.h
@@ -105,7 +105,7 @@ static u_char xd_detect (u_char *controller, unsigned int *address);
static u_char xd_initdrives (void (*init_drive)(u_char drive));
static void do_xd_request (struct request_queue * q);
-static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg);
+static int xd_ioctl (struct block_device *bdev,fmode_t mode,unsigned int cmd,unsigned long arg);
static int xd_readwrite (u_char operation,XD_INFO *disk,char *buffer,u_int block,u_int count);
static void xd_recalibrate (u_char drive);
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 1a50ae70f71..b220c686089 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -156,11 +156,10 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
return 0;
}
-static int blkif_ioctl(struct inode *inode, struct file *filep,
+static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
unsigned command, unsigned long argument)
{
- struct blkfront_info *info =
- inode->i_bdev->bd_disk->private_data;
+ struct blkfront_info *info = bdev->bd_disk->private_data;
int i;
dev_dbg(&info->xbdev->dev, "command: 0x%x, argument: 0x%lx\n",
@@ -1014,16 +1013,16 @@ static int blkfront_is_ready(struct xenbus_device *dev)
return info->is_ready;
}
-static int blkif_open(struct inode *inode, struct file *filep)
+static int blkif_open(struct block_device *bdev, fmode_t mode)
{
- struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
+ struct blkfront_info *info = bdev->bd_disk->private_data;
info->users++;
return 0;
}
-static int blkif_release(struct inode *inode, struct file *filep)
+static int blkif_release(struct gendisk *disk, fmode_t mode)
{
- struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
+ struct blkfront_info *info = disk->private_data;
info->users--;
if (info->users == 0) {
/* Check whether we have been instructed to close. We will
@@ -1044,7 +1043,7 @@ static struct block_device_operations xlvbd_block_fops =
.open = blkif_open,
.release = blkif_release,
.getgeo = blkif_getgeo,
- .ioctl = blkif_ioctl,
+ .locked_ioctl = blkif_ioctl,
};
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 4a7a059ebaf..ecab9e67d47 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -870,25 +870,24 @@ static int ace_revalidate_disk(struct gendisk *gd)
return ace->id_result;
}
-static int ace_open(struct inode *inode, struct file *filp)
+static int ace_open(struct block_device *bdev, fmode_t mode)
{
- struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+ struct ace_device *ace = bdev->bd_disk->private_data;
unsigned long flags;
dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
- filp->private_data = ace;
spin_lock_irqsave(&ace->lock, flags);
ace->users++;
spin_unlock_irqrestore(&ace->lock, flags);
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
return 0;
}
-static int ace_release(struct inode *inode, struct file *filp)
+static int ace_release(struct gendisk *disk, fmode_t mode)
{
- struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+ struct ace_device *ace = disk->private_data;
unsigned long flags;
u16 val;
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index be20a67f1fa..80754cdd311 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -137,8 +137,7 @@ get_chipram( void )
return;
}
-static int
-z2_open( struct inode *inode, struct file *filp )
+static int z2_open(struct block_device *bdev, fmode_t mode)
{
int device;
int max_z2_map = ( Z2RAM_SIZE / Z2RAM_CHUNKSIZE ) *
@@ -147,7 +146,7 @@ z2_open( struct inode *inode, struct file *filp )
sizeof( z2ram_map[0] );
int rc = -ENOMEM;
- device = iminor(inode);
+ device = MINOR(bdev->bd_dev);
if ( current_device != -1 && current_device != device )
{
@@ -299,7 +298,7 @@ err_out:
}
static int
-z2_release( struct inode *inode, struct file *filp )
+z2_release(struct gendisk *disk, fmode_t mode)
{
if ( current_device == -1 )
return 0;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index d47f2f80acc..d16b02423d6 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -973,7 +973,7 @@ static int cdrom_close_write(struct cdrom_device_info *cdi)
* is in their own interest: device control becomes a lot easier
* this way.
*/
-int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
+int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t mode)
{
int ret;
@@ -982,14 +982,14 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
/* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */
cdi->use_count++;
- if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS)) {
+ if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
ret = cdi->ops->open(cdi, 1);
} else {
ret = open_for_data(cdi);
if (ret)
goto err;
cdrom_mmc3_profile(cdi);
- if (fp->f_mode & FMODE_WRITE) {
+ if (mode & FMODE_WRITE) {
ret = -EROFS;
if (cdrom_open_write(cdi))
goto err_release;
@@ -1007,7 +1007,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
cdi->name, cdi->use_count);
/* Do this on open. Don't wait for mount, because they might
not be mounting, but opening with O_NONBLOCK */
- check_disk_change(ip->i_bdev);
+ check_disk_change(bdev);
return 0;
err_release:
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
@@ -1184,7 +1184,7 @@ static int check_for_audio_disc(struct cdrom_device_info * cdi,
return 0;
}
-int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
+void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
{
struct cdrom_device_ops *cdo = cdi->ops;
int opened_for_data;
@@ -1205,7 +1205,7 @@ int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
}
opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
- !(fp && fp->f_flags & O_NONBLOCK);
+ !(mode & FMODE_NDELAY);
/*
* flush cache on last write release
@@ -1219,7 +1219,6 @@ int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
cdo->tray_move(cdi, 1);
}
- return 0;
}
static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
@@ -2662,17 +2661,17 @@ static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi,
* these days.
* ATAPI / SCSI specific code now mainly resides in mmc_ioctl().
*/
-int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
- struct inode *ip, unsigned int cmd, unsigned long arg)
+int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
+ fmode_t mode, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int ret;
- struct gendisk *disk = ip->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
/*
* Try the generic SCSI command ioctl's first.
*/
- ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
+ ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
if (ret != -ENOTTY)
return ret;
@@ -2696,7 +2695,7 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
case CDROM_SELECT_DISC:
return cdrom_ioctl_select_disc(cdi, arg);
case CDROMRESET:
- return cdrom_ioctl_reset(cdi, ip->i_bdev);
+ return cdrom_ioctl_reset(cdi, bdev);
case CDROM_LOCKDOOR:
return cdrom_ioctl_lock_door(cdi, arg);
case CDROM_DEBUG:
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index d6ba77a2dd7..9aaa86b232b 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -490,14 +490,14 @@ static struct cdrom_device_ops gdrom_ops = {
.n_minors = 1,
};
-static int gdrom_bdops_open(struct inode *inode, struct file *file)
+static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode)
{
- return cdrom_open(gd.cd_info, inode, file);
+ return cdrom_open(gd.cd_info, bdev, mode);
}
-static int gdrom_bdops_release(struct inode *inode, struct file *file)
+static int gdrom_bdops_release(struct block_device *bdev, fmode_t mode)
{
- return cdrom_release(gd.cd_info, file);
+ return cdrom_release(gd.cd_info, mode);
}
static int gdrom_bdops_mediachanged(struct gendisk *disk)
@@ -505,10 +505,10 @@ static int gdrom_bdops_mediachanged(struct gendisk *disk)
return cdrom_media_changed(gd.cd_info);
}
-static int gdrom_bdops_ioctl(struct inode *inode, struct file *file,
+static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg)
{
- return cdrom_ioctl(file, gd.cd_info, inode, cmd, arg);
+ return cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg);
}
static struct block_device_operations gdrom_bdops = {
@@ -516,7 +516,7 @@ static struct block_device_operations gdrom_bdops = {
.open = gdrom_bdops_open,
.release = gdrom_bdops_release,
.media_changed = gdrom_bdops_mediachanged,
- .ioctl = gdrom_bdops_ioctl,
+ .locked_ioctl = gdrom_bdops_ioctl,
};
static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id)
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 031e0e1a1a3..13929356135 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -151,23 +151,24 @@ static const struct file_operations proc_viocd_operations = {
.release = single_release,
};
-static int viocd_blk_open(struct inode *inode, struct file *file)
+static int viocd_blk_open(struct block_device *bdev, fmode_t mode)
{
- struct disk_info *di = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(&di->viocd_info, inode, file);
+ struct disk_info *di = bdev->bd_disk->private_data;
+ return cdrom_open(&di->viocd_info, bdev, mode);
}
-static int viocd_blk_release(struct inode *inode, struct file *file)
+static int viocd_blk_release(struct gendisk *disk, fmode_t mode)
{
- struct disk_info *di = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(&di->viocd_info, file);
+ struct disk_info *di = disk->private_data;
+ cdrom_release(&di->viocd_info, mode);
+ return 0;
}
-static int viocd_blk_ioctl(struct inode *inode, struct file *file,
+static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg)
{
- struct disk_info *di = inode->i_bdev->bd_disk->private_data;
- return cdrom_ioctl(file, &di->viocd_info, inode, cmd, arg);
+ struct disk_info *di = bdev->bd_disk->private_data;
+ return cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg);
}
static int viocd_blk_media_changed(struct gendisk *disk)
@@ -180,7 +181,7 @@ struct block_device_operations viocd_fops = {
.owner = THIS_MODULE,
.open = viocd_blk_open,
.release = viocd_blk_release,
- .ioctl = viocd_blk_ioctl,
+ .locked_ioctl = viocd_blk_ioctl,
.media_changed = viocd_blk_media_changed,
};
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 31dcd9142d5..dc8d1a90971 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -417,6 +417,6 @@ static void __exit agp_ali_cleanup(void)
module_init(agp_ali_init);
module_exit(agp_ali_cleanup);
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 2812ee2b165..52f4361eb6e 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -772,6 +772,6 @@ module_init(agp_amd64_init);
module_exit(agp_amd64_cleanup);
#endif
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen");
module_param(agp_try_unsupported, bool, 0);
MODULE_LICENSE("GPL");
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index ae2791b926b..f1537eece07 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -561,6 +561,6 @@ static void __exit agp_ati_cleanup(void)
module_init(agp_ati_init);
module_exit(agp_ati_cleanup);
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 3a3cc03d401..8c617ad7497 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -349,7 +349,7 @@ static __init int agp_setup(char *s)
__setup("agp=", agp_setup);
#endif
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_DESCRIPTION("AGP GART driver");
MODULE_LICENSE("GPL and additional rights");
MODULE_ALIAS_MISCDEV(AGPGART_MINOR);
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 1108665913e..9cf6e9bb017 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -2390,5 +2390,5 @@ static void __exit agp_intel_cleanup(void)
module_init(agp_intel_init);
module_exit(agp_intel_cleanup);
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 5bbed3d79db..16acee2de11 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -1,7 +1,7 @@
/*
* Nvidia AGPGART routines.
* Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up
- * to work in 2.5 by Dave Jones <davej@codemonkey.org.uk>
+ * to work in 2.5 by Dave Jones <davej@redhat.com>
*/
#include <linux/module.h>
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index f2492ecf082..db60539bf67 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -20,8 +20,8 @@
#include <linux/agp_backend.h>
#include <linux/log2.h>
-#include <asm-parisc/parisc-device.h>
-#include <asm-parisc/ropes.h>
+#include <asm/parisc-device.h>
+#include <asm/ropes.h>
#include "agp.h"
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 9f4d49e1b59..d3bd243867f 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -595,4 +595,4 @@ module_init(agp_via_init);
module_exit(agp_via_cleanup);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 98821f97583..b97aebd7aeb 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -2071,12 +2071,13 @@ module_init(rs_init)
module_exit(rs_exit)
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
+
/*
* ------------------------------------------------------------
* Serial console driver
* ------------------------------------------------------------
*/
-#ifdef CONFIG_SERIAL_CONSOLE
static void amiga_serial_putc(char c)
{
@@ -2130,6 +2131,7 @@ static int __init amiserial_console_init(void)
return 0;
}
console_initcall(amiserial_console_init);
-#endif
+
+#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
MODULE_LICENSE("GPL");
diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c
index 5329d482b58..0a826d7be10 100644
--- a/drivers/char/ds1286.c
+++ b/drivers/char/ds1286.c
@@ -210,8 +210,8 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
if (sec != 0)
return -EINVAL;
- min = BIN2BCD(min);
- min = BIN2BCD(hrs);
+ min = bin2bcd(min);
+ min = bin2bcd(hrs);
spin_lock(&ds1286_lock);
rtc_write(hrs, RTC_HOURS_ALARM);
@@ -353,7 +353,7 @@ static int ds1286_proc_output(char *buf)
ds1286_get_time(&tm);
hundredth = rtc_read(RTC_HUNDREDTH_SECOND);
- BCD_TO_BIN(hundredth);
+ hundredth = bcd2bin(hundredth);
p += sprintf(p,
"rtc_time\t: %02d:%02d:%02d.%02d\n"
@@ -477,12 +477,12 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
rtc_write(save_control, RTC_CMD);
spin_unlock_irqrestore(&ds1286_lock, flags);
- BCD_TO_BIN(rtc_tm->tm_sec);
- BCD_TO_BIN(rtc_tm->tm_min);
- BCD_TO_BIN(rtc_tm->tm_hour);
- BCD_TO_BIN(rtc_tm->tm_mday);
- BCD_TO_BIN(rtc_tm->tm_mon);
- BCD_TO_BIN(rtc_tm->tm_year);
+ rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+ rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+ rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
/*
* Account for differences between how the RTC uses the values
@@ -531,12 +531,12 @@ static int ds1286_set_time(struct rtc_time *rtc_tm)
if (yrs >= 100)
yrs -= 100;
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hrs);
- BIN_TO_BCD(day);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(yrs);
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
spin_lock_irqsave(&ds1286_lock, flags);
save_control = rtc_read(RTC_CMD);
@@ -572,8 +572,8 @@ static void ds1286_get_alm_time(struct rtc_time *alm_tm)
cmd = rtc_read(RTC_CMD);
spin_unlock_irqrestore(&ds1286_lock, flags);
- BCD_TO_BIN(alm_tm->tm_min);
- BCD_TO_BIN(alm_tm->tm_hour);
+ alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
+ alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
alm_tm->tm_sec = 0;
}
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index c5e67a62395..170693c93c7 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -131,12 +131,12 @@ get_rtc_time(struct rtc_time *rtc_tm)
local_irq_restore(flags);
- BCD_TO_BIN(rtc_tm->tm_sec);
- BCD_TO_BIN(rtc_tm->tm_min);
- BCD_TO_BIN(rtc_tm->tm_hour);
- BCD_TO_BIN(rtc_tm->tm_mday);
- BCD_TO_BIN(rtc_tm->tm_mon);
- BCD_TO_BIN(rtc_tm->tm_year);
+ rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+ rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+ rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
/*
* Account for differences between how the RTC uses the values
@@ -211,12 +211,12 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
else
yrs -= 1900; /* RTC (70, 71, ... 99) */
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hrs);
- BIN_TO_BCD(day);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(yrs);
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
lock_kernel();
local_irq_save(flags);
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 4998b2761e8..cf2461d34e5 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -2477,7 +2477,11 @@ static int pc_send_break(struct tty_struct *tty, int msec)
unsigned long flags;
if (msec == -1)
- return -EOPNOTSUPP;
+ msec = 0xFFFF;
+ else if (msec > 0xFFFE)
+ msec = 0xFFFE;
+ else if (msec < 1)
+ msec = 1;
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index f3cfb4c7612..408f5f92cb4 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -219,7 +219,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
- if (irq >= NR_IRQS) {
+ if (irq >= nr_irqs) {
irq = HPET_MAX_IRQ;
break;
}
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index bf70450a49c..5b819b12675 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -161,7 +161,7 @@ static void hvc_console_print(struct console *co, const char *b,
}
} else {
r = cons_ops[index]->put_chars(vtermnos[index], c, i);
- if (r < 0) {
+ if (r <= 0) {
/* throw away chars on error */
i = 0;
} else if (r > 0) {
@@ -374,6 +374,9 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
if (hp->ops->notifier_del)
hp->ops->notifier_del(hp, hp->data);
+ /* cancel pending tty resize work */
+ cancel_work_sync(&hp->tty_resize);
+
/*
* Chain calls chars_in_buffer() and returns immediately if
* there is no buffered data otherwise sleeps on a wait queue
@@ -399,6 +402,9 @@ static void hvc_hangup(struct tty_struct *tty)
if (!hp)
return;
+ /* cancel pending tty resize work */
+ cancel_work_sync(&hp->tty_resize);
+
spin_lock_irqsave(&hp->lock, flags);
/*
@@ -418,8 +424,8 @@ static void hvc_hangup(struct tty_struct *tty)
spin_unlock_irqrestore(&hp->lock, flags);
- if (hp->ops->notifier_del)
- hp->ops->notifier_del(hp, hp->data);
+ if (hp->ops->notifier_hangup)
+ hp->ops->notifier_hangup(hp, hp->data);
while(temp_open_count) {
--temp_open_count;
@@ -431,7 +437,7 @@ static void hvc_hangup(struct tty_struct *tty)
* Push buffered characters whether they were just recently buffered or waiting
* on a blocked hypervisor. Call this function with hp->lock held.
*/
-static void hvc_push(struct hvc_struct *hp)
+static int hvc_push(struct hvc_struct *hp)
{
int n;
@@ -439,7 +445,7 @@ static void hvc_push(struct hvc_struct *hp)
if (n <= 0) {
if (n == 0) {
hp->do_wakeup = 1;
- return;
+ return 0;
}
/* throw away output on error; this happens when
there is no session connected to the vterm. */
@@ -450,6 +456,8 @@ static void hvc_push(struct hvc_struct *hp)
memmove(hp->outbuf, hp->outbuf + n, hp->n_outbuf);
else
hp->do_wakeup = 1;
+
+ return n;
}
static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -492,6 +500,39 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
return written;
}
+/**
+ * hvc_set_winsz() - Resize the hvc tty terminal window.
+ * @work: work structure.
+ *
+ * The routine shall not be called within an atomic context because it
+ * might sleep.
+ *
+ * Locking: hp->lock
+ */
+static void hvc_set_winsz(struct work_struct *work)
+{
+ struct hvc_struct *hp;
+ unsigned long hvc_flags;
+ struct tty_struct *tty;
+ struct winsize ws;
+
+ hp = container_of(work, struct hvc_struct, tty_resize);
+ if (!hp)
+ return;
+
+ spin_lock_irqsave(&hp->lock, hvc_flags);
+ if (!hp->tty) {
+ spin_unlock_irqrestore(&hp->lock, hvc_flags);
+ return;
+ }
+ ws = hp->ws;
+ tty = tty_kref_get(hp->tty);
+ spin_unlock_irqrestore(&hp->lock, hvc_flags);
+
+ tty_do_resize(tty, tty, &ws);
+ tty_kref_put(tty);
+}
+
/*
* This is actually a contract between the driver and the tty layer outlining
* how much write room the driver can guarantee will be sent OR BUFFERED. This
@@ -538,16 +579,20 @@ int hvc_poll(struct hvc_struct *hp)
char buf[N_INBUF] __ALIGNED__;
unsigned long flags;
int read_total = 0;
+ int written_total = 0;
spin_lock_irqsave(&hp->lock, flags);
/* Push pending writes */
if (hp->n_outbuf > 0)
- hvc_push(hp);
+ written_total = hvc_push(hp);
/* Reschedule us if still some write pending */
- if (hp->n_outbuf > 0)
+ if (hp->n_outbuf > 0) {
poll_mask |= HVC_POLL_WRITE;
+ /* If hvc_push() was not able to write, sleep a few msecs */
+ timeout = (written_total) ? 0 : MIN_TIMEOUT;
+ }
/* No tty attached, just skip */
tty = hp->tty;
@@ -632,6 +677,24 @@ int hvc_poll(struct hvc_struct *hp)
}
EXPORT_SYMBOL_GPL(hvc_poll);
+/**
+ * hvc_resize() - Update terminal window size information.
+ * @hp: HVC console pointer
+ * @ws: Terminal window size structure
+ *
+ * Stores the specified window size information in the hvc structure of @hp.
+ * The function schedule the tty resize update.
+ *
+ * Locking: Locking free; the function MUST be called holding hp->lock
+ */
+void hvc_resize(struct hvc_struct *hp, struct winsize ws)
+{
+ if ((hp->ws.ws_row != ws.ws_row) || (hp->ws.ws_col != ws.ws_col)) {
+ hp->ws = ws;
+ schedule_work(&hp->tty_resize);
+ }
+}
+
/*
* This kthread is either polling or interrupt driven. This is determined by
* calling hvc_poll() who determines whether a console adapter support
@@ -659,10 +722,6 @@ static int khvcd(void *unused)
poll_mask |= HVC_POLL_READ;
if (hvc_kicked)
continue;
- if (poll_mask & HVC_POLL_WRITE) {
- yield();
- continue;
- }
set_current_state(TASK_INTERRUPTIBLE);
if (!hvc_kicked) {
if (poll_mask == 0)
@@ -718,6 +777,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data,
kref_init(&hp->kref);
+ INIT_WORK(&hp->tty_resize, hvc_set_winsz);
spin_lock_init(&hp->lock);
spin_lock(&hvc_structs_lock);
@@ -743,7 +803,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data,
}
EXPORT_SYMBOL_GPL(hvc_alloc);
-int __devexit hvc_remove(struct hvc_struct *hp)
+int hvc_remove(struct hvc_struct *hp)
{
unsigned long flags;
struct tty_struct *tty;
@@ -796,7 +856,7 @@ static int hvc_init(void)
drv->minor_start = HVC_MINOR;
drv->type = TTY_DRIVER_TYPE_SYSTEM;
drv->init_termios = tty_std_termios;
- drv->flags = TTY_DRIVER_REAL_RAW;
+ drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(drv, &hvc_ops);
/* Always start the kthread because there can be hotplug vty adapters
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h
index 9790201718a..8297dbc2e6e 100644
--- a/drivers/char/hvc_console.h
+++ b/drivers/char/hvc_console.h
@@ -27,6 +27,7 @@
#ifndef HVC_CONSOLE_H
#define HVC_CONSOLE_H
#include <linux/kref.h>
+#include <linux/tty.h>
/*
* This is the max number of console adapters that can/will be found as
@@ -56,6 +57,8 @@ struct hvc_struct {
struct hv_ops *ops;
int irq_requested;
int data;
+ struct winsize ws;
+ struct work_struct tty_resize;
struct list_head next;
struct kref kref; /* ref count & hvc_struct lifetime */
};
@@ -65,9 +68,10 @@ struct hv_ops {
int (*get_chars)(uint32_t vtermno, char *buf, int count);
int (*put_chars)(uint32_t vtermno, const char *buf, int count);
- /* Callbacks for notification. Called in open and close */
+ /* Callbacks for notification. Called in open, close and hangup */
int (*notifier_add)(struct hvc_struct *hp, int irq);
void (*notifier_del)(struct hvc_struct *hp, int irq);
+ void (*notifier_hangup)(struct hvc_struct *hp, int irq);
};
/* Register a vterm and a slot index for use as a console (console_init) */
@@ -77,15 +81,19 @@ extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
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 (module_exit or hotplug remove) */
-extern int __devexit hvc_remove(struct hvc_struct *hp);
+extern int hvc_remove(struct hvc_struct *hp);
/* data available */
int hvc_poll(struct hvc_struct *hp);
void hvc_kick(void);
+/* Resize hvc tty terminal window */
+extern void hvc_resize(struct hvc_struct *hp, struct winsize ws);
+
/* 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);
+extern void notifier_hangup_irq(struct hvc_struct *hp, int data);
#if defined(CONFIG_XMON) && defined(CONFIG_SMP)
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c
index 73a59cdb894..d09e5688d44 100644
--- a/drivers/char/hvc_irq.c
+++ b/drivers/char/hvc_irq.c
@@ -42,3 +42,8 @@ void notifier_del_irq(struct hvc_struct *hp, int irq)
free_irq(irq, hp);
hp->irq_requested = 0;
}
+
+void notifier_hangup_irq(struct hvc_struct *hp, int irq)
+{
+ notifier_del_irq(hp, irq);
+}
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c
index b71c610fe5a..b74a2f8ab90 100644
--- a/drivers/char/hvc_iseries.c
+++ b/drivers/char/hvc_iseries.c
@@ -202,6 +202,7 @@ static struct hv_ops hvc_get_put_ops = {
.put_chars = put_chars,
.notifier_add = notifier_add_irq,
.notifier_del = notifier_del_irq,
+ .notifier_hangup = notifier_hangup_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 93f3840c168..019e0b58593 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -82,6 +82,7 @@ static struct hv_ops hvc_get_put_ops = {
.put_chars = hvc_put_chars,
.notifier_add = notifier_add_irq,
.notifier_del = notifier_del_irq,
+ .notifier_hangup = notifier_hangup_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 538ceea5e7d..eba999f8598 100644
--- a/drivers/char/hvc_xen.c
+++ b/drivers/char/hvc_xen.c
@@ -102,6 +102,7 @@ static struct hv_ops hvc_ops = {
.put_chars = write_console,
.notifier_add = notifier_add_irq,
.notifier_del = notifier_del_irq,
+ .notifier_hangup = notifier_hangup_irq,
};
static int __init xen_init(void)
diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c
index ec9d0443d92..2abd881b4cb 100644
--- a/drivers/char/ip27-rtc.c
+++ b/drivers/char/ip27-rtc.c
@@ -130,12 +130,12 @@ static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (yrs >= 100)
yrs -= 100;
- sec = BIN2BCD(sec);
- min = BIN2BCD(min);
- hrs = BIN2BCD(hrs);
- day = BIN2BCD(day);
- mon = BIN2BCD(mon);
- yrs = BIN2BCD(yrs);
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
spin_lock_irq(&rtc_lock);
rtc->control |= M48T35_RTC_SET;
@@ -311,12 +311,12 @@ static void get_rtc_time(struct rtc_time *rtc_tm)
rtc->control &= ~M48T35_RTC_READ;
spin_unlock_irq(&rtc_lock);
- rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
- rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
- rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
- rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
- rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
- rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);
+ rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+ rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+ rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
/*
* Account for differences between how the RTC uses the values
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 39f6357e3b5..8054ee839b3 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -338,7 +338,7 @@ nvram_open(struct inode *inode, struct file *file)
if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
(nvram_open_mode & NVRAM_EXCL) ||
- ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) {
+ ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) {
spin_unlock(&nvram_state_lock);
unlock_kernel();
return -EBUSY;
@@ -346,7 +346,7 @@ nvram_open(struct inode *inode, struct file *file)
if (file->f_flags & O_EXCL)
nvram_open_mode |= NVRAM_EXCL;
- if (file->f_mode & 2)
+ if (file->f_mode & FMODE_WRITE)
nvram_open_mode |= NVRAM_WRITE;
nvram_open_cnt++;
@@ -366,7 +366,7 @@ nvram_release(struct inode *inode, struct file *file)
/* if only one instance is open, clear the EXCL bit */
if (nvram_open_mode & NVRAM_EXCL)
nvram_open_mode &= ~NVRAM_EXCL;
- if (file->f_mode & 2)
+ if (file->f_mode & FMODE_WRITE)
nvram_open_mode &= ~NVRAM_WRITE;
spin_unlock(&nvram_state_lock);
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index b930de50407..3f7da8cf3a8 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -41,7 +41,8 @@ static u8 pc8736x_gpio_shadow[4];
#define SIO_BASE2 0x4E /* alt command-reg to check */
#define SIO_SID 0x20 /* SuperI/O ID Register */
-#define SIO_SID_VALUE 0xe9 /* Expected value in SuperI/O ID Register */
+#define SIO_SID_PC87365 0xe5 /* Expected value in ID Register for PC87365 */
+#define SIO_SID_PC87366 0xe9 /* Expected value in ID Register for PC87366 */
#define SIO_CF1 0x21 /* chip config, bit0 is chip enable */
@@ -91,13 +92,17 @@ static inline int superio_inb(int addr)
static int pc8736x_superio_present(void)
{
+ int id;
+
/* try the 2 possible values, read a hardware reg to verify */
superio_cmd = SIO_BASE1;
- if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+ id = superio_inb(SIO_SID);
+ if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
return superio_cmd;
superio_cmd = SIO_BASE2;
- if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+ id = superio_inb(SIO_SID);
+ if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
return superio_cmd;
return 0;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c8752eaad48..705a839f179 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -558,9 +558,26 @@ struct timer_rand_state {
unsigned dont_count_entropy:1;
};
-static struct timer_rand_state input_timer_state;
static struct timer_rand_state *irq_timer_state[NR_IRQS];
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+ if (irq >= nr_irqs)
+ return NULL;
+
+ return irq_timer_state[irq];
+}
+
+static void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
+{
+ if (irq >= nr_irqs)
+ return;
+
+ irq_timer_state[irq] = state;
+}
+
+static struct timer_rand_state input_timer_state;
+
/*
* This function adds entropy to the entropy "pool" by using timing
* delays. It uses the timer_rand_state structure to make an estimate
@@ -648,11 +665,15 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
void add_interrupt_randomness(int irq)
{
- if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
+ struct timer_rand_state *state;
+
+ state = get_timer_rand_state(irq);
+
+ if (state == NULL)
return;
DEBUG_ENT("irq event %d\n", irq);
- add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
+ add_timer_randomness(state, 0x100 + irq);
}
#ifdef CONFIG_BLOCK
@@ -912,7 +933,12 @@ void rand_initialize_irq(int irq)
{
struct timer_rand_state *state;
- if (irq >= NR_IRQS || irq_timer_state[irq])
+ if (irq >= nr_irqs)
+ return;
+
+ state = get_timer_rand_state(irq);
+
+ if (state)
return;
/*
@@ -921,7 +947,7 @@ void rand_initialize_irq(int irq)
*/
state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
if (state)
- irq_timer_state[irq] = state;
+ set_timer_rand_state(irq, state);
}
#ifdef CONFIG_BLOCK
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index e139372d0e6..96adf28a17e 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -65,7 +65,7 @@ static int raw_open(struct inode *inode, struct file *filp)
if (!bdev)
goto out;
igrab(bdev->bd_inode);
- err = blkdev_get(bdev, filp->f_mode, 0);
+ err = blkdev_get(bdev, filp->f_mode);
if (err)
goto out;
err = bd_claim(bdev, raw_open);
@@ -87,7 +87,7 @@ static int raw_open(struct inode *inode, struct file *filp)
out2:
bd_release(bdev);
out1:
- blkdev_put(bdev);
+ blkdev_put(bdev, filp->f_mode);
out:
mutex_unlock(&raw_mutex);
return err;
@@ -112,7 +112,7 @@ static int raw_release(struct inode *inode, struct file *filp)
mutex_unlock(&raw_mutex);
bd_release(bdev);
- blkdev_put(bdev);
+ blkdev_put(bdev, filp->f_mode);
return 0;
}
@@ -125,7 +125,7 @@ raw_ioctl(struct inode *inode, struct file *filp,
{
struct block_device *bdev = filp->private_data;
- return blkdev_ioctl(bdev->bd_inode, NULL, command, arg);
+ return blkdev_ioctl(bdev, 0, command, arg);
}
static void bind_device(struct raw_config_request *rq)
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 17683de9571..32dc89720d5 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -518,17 +518,17 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
RTC_ALWAYS_BCD) {
if (sec < 60)
- BIN_TO_BCD(sec);
+ sec = bin2bcd(sec);
else
sec = 0xff;
if (min < 60)
- BIN_TO_BCD(min);
+ min = bin2bcd(min);
else
min = 0xff;
if (hrs < 24)
- BIN_TO_BCD(hrs);
+ hrs = bin2bcd(hrs);
else
hrs = 0xff;
}
@@ -614,12 +614,12 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hrs);
- BIN_TO_BCD(day);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(yrs);
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
}
save_control = CMOS_READ(RTC_CONTROL);
@@ -1099,7 +1099,7 @@ no_irq:
spin_unlock_irq(&rtc_lock);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- BCD_TO_BIN(year); /* This should never happen... */
+ year = bcd2bin(year); /* This should never happen... */
if (year < 20) {
epoch = 2000;
@@ -1352,13 +1352,13 @@ static void rtc_get_rtc_time(struct rtc_time *rtc_tm)
spin_unlock_irqrestore(&rtc_lock, flags);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(rtc_tm->tm_sec);
- BCD_TO_BIN(rtc_tm->tm_min);
- BCD_TO_BIN(rtc_tm->tm_hour);
- BCD_TO_BIN(rtc_tm->tm_mday);
- BCD_TO_BIN(rtc_tm->tm_mon);
- BCD_TO_BIN(rtc_tm->tm_year);
- BCD_TO_BIN(rtc_tm->tm_wday);
+ rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+ rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+ rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
+ rtc_tm->tm_wday = bcd2bin(rtc_tm->tm_wday);
}
#ifdef CONFIG_MACH_DECSTATION
@@ -1392,9 +1392,9 @@ static void get_rtc_alm_time(struct rtc_time *alm_tm)
spin_unlock_irq(&rtc_lock);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(alm_tm->tm_sec);
- BCD_TO_BIN(alm_tm->tm_min);
- BCD_TO_BIN(alm_tm->tm_hour);
+ alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
+ alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
+ alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
}
}
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5b8d7a1aa3e..ba4e86281fb 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board,
del_timer(&board->timer);
if (pdev) {
#ifdef CONFIG_PCI
- pci_iounmap(pdev, board->base2);
+ iounmap(board->base2);
pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
#endif
} else {
@@ -2677,7 +2677,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
}
board->hw_base = pci_resource_start(pdev, reg);
board->base2 =
- board->base = pci_iomap(pdev, reg, WINDOW_LEN(board));
+ board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
if (!board->base) {
dev_err(&pdev->dev, "ioremap failed\n");
goto err_reg;
@@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
return 0;
err_unmap:
- pci_iounmap(pdev, board->base2);
+ iounmap(board->base2);
err_reg:
pci_release_region(pdev, reg);
err_flag:
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index dce4cc0e695..ce0d9da52a8 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -168,7 +168,7 @@ static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
static struct sysrq_key_op sysrq_show_timers_op = {
.handler = sysrq_handle_show_timers,
.help_msg = "show-all-timers(Q)",
- .action_msg = "Show Pending Timers",
+ .action_msg = "Show clockevent devices & pending hrtimers (no others)",
};
static void sysrq_handle_mountro(int key, struct tty_struct *tty)
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index e70d13defde..9c47dc48c9f 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1157,7 +1157,7 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
* Once all references to platform device are down to 0,
* release all allocated structures.
*/
-static void tpm_dev_release(struct device *dev)
+void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 553b0e9d8d1..c8f8024cb40 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -90,7 +90,7 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
spin_lock_irqsave(&port->lock, flags);
if (port->tty)
tty_kref_put(port->tty);
- port->tty = tty;
+ port->tty = tty_kref_get(tty);
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL(tty_port_tty_set);
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index d0f4eb6fdb7..3fb0d2c88ba 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -198,6 +198,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
virtio_cons.put_chars = put_chars;
virtio_cons.notifier_add = notifier_add_vio;
virtio_cons.notifier_del = notifier_del_vio;
+ virtio_cons.notifier_hangup = notifier_del_vio;
/* The first argument of hvc_alloc() is the virtual console number, so
* we use zero. The second argument is the parameter for the
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index ffe9b4e3072..54c837288d1 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -641,7 +641,7 @@ static int __devinit giu_probe(struct platform_device *dev)
}
irq = platform_get_irq(dev, 0);
- if (irq < 0 || irq >= NR_IRQS)
+ if (irq < 0 || irq >= nr_irqs)
return -EBUSY;
return cascade_irq(irq, giu_get_irq);
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 71d2ac4e3f4..c20171078d1 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -237,9 +237,12 @@ static int __init parse_pmtmr(char *arg)
if (strict_strtoul(arg, 16, &base))
return -EINVAL;
-
+#ifdef CONFIG_X86_64
+ if (base > UINT_MAX)
+ return -ERANGE;
+#endif
printk(KERN_INFO "PMTMR IOPort override: 0x%04x -> 0x%04lx\n",
- (unsigned int)pmtmr_ioport, base);
+ pmtmr_ioport, base);
pmtmr_ioport = base;
return 1;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 5ce07b517c5..5bed73329ef 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -16,6 +16,7 @@
#include <linux/cpu.h>
#include <linux/cpuidle.h>
#include <linux/ktime.h>
+#include <linux/hrtimer.h>
#include "cpuidle.h"
@@ -56,10 +57,20 @@ static void cpuidle_idle_call(void)
if (pm_idle_old)
pm_idle_old();
else
+#if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE)
+ default_idle();
+#else
local_irq_enable();
+#endif
return;
}
+ /*
+ * run any timers that can be run now, at this point
+ * before calculating the idle duration etc.
+ */
+ hrtimer_peek_ahead_timers();
+
/* ask the governor for the next state */
next_state = cpuidle_curr_governor->select(dev);
if (need_resched())
@@ -67,8 +78,11 @@ static void cpuidle_idle_call(void)
target_state = &dev->states[next_state];
/* enter the state and update stats */
- dev->last_residency = target_state->enter(dev, target_state);
dev->last_state = target_state;
+ dev->last_residency = target_state->enter(dev, target_state);
+ if (dev->last_state)
+ target_state = dev->last_state;
+
target_state->time += (unsigned long long)dev->last_residency;
target_state->usage++;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index cd303901eb5..904e57558bb 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -48,13 +48,13 @@ config DW_DMAC
can be integrated in chips such as the Atmel AT32ap7000.
config FSL_DMA
- bool "Freescale MPC85xx/MPC83xx DMA support"
- depends on PPC
+ tristate "Freescale Elo and Elo Plus DMA support"
+ depends on FSL_SOC
select DMA_ENGINE
---help---
- Enable support for the Freescale DMA engine. Now, it support
- MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
- The MPC8349, MPC8360 is also supported.
+ Enable support for the Freescale Elo and Elo Plus DMA controllers.
+ The Elo is the DMA controller on some 82xx and 83xx parts, and the
+ Elo Plus is the DMA controller on 85xx and 86xx parts.
config MV_XOR
bool "Marvell XOR engine support"
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index a08d1970474..d1e381e35a9 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -325,7 +325,12 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
struct dmatest_thread *thread;
unsigned int i;
- dtc = kmalloc(sizeof(struct dmatest_chan), GFP_ATOMIC);
+ /* Have we already been told about this channel? */
+ list_for_each_entry(dtc, &dmatest_channels, node)
+ if (dtc->chan == chan)
+ return DMA_DUP;
+
+ dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
if (!dtc) {
pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id);
return DMA_NAK;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index c0059ca5834..0b95dcce447 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -370,7 +370,10 @@ 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);
+
+ /* Has this channel already been allocated? */
+ if (fsl_chan->desc_pool)
+ return 1;
/* We need the descriptor to be aligned to 32bytes
* for meeting FSL DMA specification requirement.
@@ -410,6 +413,8 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
}
spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
dma_pool_destroy(fsl_chan->desc_pool);
+
+ fsl_chan->desc_pool = NULL;
}
static struct dma_async_tx_descriptor *
@@ -786,159 +791,29 @@ static void dma_do_tasklet(unsigned long data)
fsl_chan_ld_cleanup(fsl_chan);
}
-static void fsl_dma_callback_test(void *param)
-{
- struct fsl_dma_chan *fsl_chan = param;
- if (fsl_chan)
- dev_dbg(fsl_chan->dev, "selftest: callback is ok!\n");
-}
-
-static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
-{
- struct dma_chan *chan;
- int err = 0;
- dma_addr_t dma_dest, dma_src;
- dma_cookie_t cookie;
- u8 *src, *dest;
- int i;
- size_t test_size;
- struct dma_async_tx_descriptor *tx1, *tx2, *tx3;
-
- test_size = 4096;
-
- src = kmalloc(test_size * 2, GFP_KERNEL);
- if (!src) {
- dev_err(fsl_chan->dev,
- "selftest: Cannot alloc memory for test!\n");
- return -ENOMEM;
- }
-
- dest = src + test_size;
-
- for (i = 0; i < test_size; i++)
- src[i] = (u8) i;
-
- chan = &fsl_chan->common;
-
- if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
- dev_err(fsl_chan->dev,
- "selftest: Cannot alloc resources for DMA\n");
- err = -ENODEV;
- goto out;
- }
-
- /* TX 1 */
- dma_src = dma_map_single(fsl_chan->dev, src, test_size / 2,
- DMA_TO_DEVICE);
- dma_dest = dma_map_single(fsl_chan->dev, dest, test_size / 2,
- DMA_FROM_DEVICE);
- tx1 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 2, 0);
- async_tx_ack(tx1);
-
- cookie = fsl_dma_tx_submit(tx1);
- fsl_dma_memcpy_issue_pending(chan);
- msleep(2);
-
- if (fsl_dma_is_complete(chan, cookie, NULL, NULL) != DMA_SUCCESS) {
- dev_err(fsl_chan->dev, "selftest: Time out!\n");
- err = -ENODEV;
- goto free_resources;
- }
-
- /* Test free and re-alloc channel resources */
- fsl_dma_free_chan_resources(chan);
-
- if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
- dev_err(fsl_chan->dev,
- "selftest: Cannot alloc resources for DMA\n");
- err = -ENODEV;
- goto free_resources;
- }
-
- /* Continue to test
- * TX 2
- */
- dma_src = dma_map_single(fsl_chan->dev, src + test_size / 2,
- test_size / 4, DMA_TO_DEVICE);
- dma_dest = dma_map_single(fsl_chan->dev, dest + test_size / 2,
- test_size / 4, DMA_FROM_DEVICE);
- tx2 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0);
- async_tx_ack(tx2);
-
- /* TX 3 */
- dma_src = dma_map_single(fsl_chan->dev, src + test_size * 3 / 4,
- test_size / 4, DMA_TO_DEVICE);
- dma_dest = dma_map_single(fsl_chan->dev, dest + test_size * 3 / 4,
- test_size / 4, DMA_FROM_DEVICE);
- tx3 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0);
- async_tx_ack(tx3);
-
- /* Interrupt tx test */
- tx1 = fsl_dma_prep_interrupt(chan, 0);
- async_tx_ack(tx1);
- cookie = fsl_dma_tx_submit(tx1);
-
- /* Test exchanging the prepared tx sort */
- cookie = fsl_dma_tx_submit(tx3);
- cookie = fsl_dma_tx_submit(tx2);
-
- if (dma_has_cap(DMA_INTERRUPT, ((struct fsl_dma_device *)
- dev_get_drvdata(fsl_chan->dev->parent))->common.cap_mask)) {
- tx3->callback = fsl_dma_callback_test;
- tx3->callback_param = fsl_chan;
- }
- fsl_dma_memcpy_issue_pending(chan);
- msleep(2);
-
- if (fsl_dma_is_complete(chan, cookie, NULL, NULL) != DMA_SUCCESS) {
- dev_err(fsl_chan->dev, "selftest: Time out!\n");
- err = -ENODEV;
- goto free_resources;
- }
-
- err = memcmp(src, dest, test_size);
- if (err) {
- for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size);
- i++);
- dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%ld is "
- "error! src 0x%x, dest 0x%x\n",
- i, (long)test_size, *(src + i), *(dest + i));
- }
-
-free_resources:
- fsl_dma_free_chan_resources(chan);
-out:
- kfree(src);
- return err;
-}
-
-static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
- const struct of_device_id *match)
+static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ struct device_node *node, u32 feature, const char *compatible)
{
- struct fsl_dma_device *fdev;
struct fsl_dma_chan *new_fsl_chan;
int err;
- fdev = dev_get_drvdata(dev->dev.parent);
- BUG_ON(!fdev);
-
/* alloc channel */
new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL);
if (!new_fsl_chan) {
- dev_err(&dev->dev, "No free memory for allocating "
+ dev_err(fdev->dev, "No free memory for allocating "
"dma channels!\n");
return -ENOMEM;
}
/* get dma channel register base */
- err = of_address_to_resource(dev->node, 0, &new_fsl_chan->reg);
+ err = of_address_to_resource(node, 0, &new_fsl_chan->reg);
if (err) {
- dev_err(&dev->dev, "Can't get %s property 'reg'\n",
- dev->node->full_name);
+ dev_err(fdev->dev, "Can't get %s property 'reg'\n",
+ node->full_name);
goto err_no_reg;
}
- new_fsl_chan->feature = *(u32 *)match->data;
+ new_fsl_chan->feature = feature;
if (!fdev->feature)
fdev->feature = new_fsl_chan->feature;
@@ -948,13 +823,13 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
*/
WARN_ON(fdev->feature != new_fsl_chan->feature);
- new_fsl_chan->dev = &dev->dev;
+ new_fsl_chan->dev = &new_fsl_chan->common.dev;
new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVICE) {
- dev_err(&dev->dev, "There is no %d channel!\n",
+ dev_err(fdev->dev, "There is no %d channel!\n",
new_fsl_chan->id);
err = -EINVAL;
goto err_no_chan;
@@ -988,29 +863,23 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
&fdev->common.channels);
fdev->common.chancnt++;
- new_fsl_chan->irq = irq_of_parse_and_map(dev->node, 0);
+ new_fsl_chan->irq = irq_of_parse_and_map(node, 0);
if (new_fsl_chan->irq != NO_IRQ) {
err = request_irq(new_fsl_chan->irq,
&fsl_dma_chan_do_interrupt, IRQF_SHARED,
"fsldma-channel", new_fsl_chan);
if (err) {
- dev_err(&dev->dev, "DMA channel %s request_irq error "
- "with return %d\n", dev->node->full_name, err);
+ dev_err(fdev->dev, "DMA channel %s request_irq error "
+ "with return %d\n", node->full_name, err);
goto err_no_irq;
}
}
- err = fsl_dma_self_test(new_fsl_chan);
- if (err)
- goto err_self_test;
-
- dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
- match->compatible, new_fsl_chan->irq);
+ dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
+ compatible, new_fsl_chan->irq);
return 0;
-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:
@@ -1020,38 +889,20 @@ err_no_reg:
return err;
}
-const u32 mpc8540_dma_ip_feature = FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN;
-const u32 mpc8349_dma_ip_feature = FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN;
-
-static struct of_device_id of_fsl_dma_chan_ids[] = {
- {
- .compatible = "fsl,eloplus-dma-channel",
- .data = (void *)&mpc8540_dma_ip_feature,
- },
- {
- .compatible = "fsl,elo-dma-channel",
- .data = (void *)&mpc8349_dma_ip_feature,
- },
- {}
-};
-
-static struct of_platform_driver of_fsl_dma_chan_driver = {
- .name = "of-fsl-dma-channel",
- .match_table = of_fsl_dma_chan_ids,
- .probe = of_fsl_dma_chan_probe,
-};
-
-static __init int of_fsl_dma_chan_init(void)
+static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
{
- return of_register_platform_driver(&of_fsl_dma_chan_driver);
+ free_irq(fchan->irq, fchan);
+ list_del(&fchan->common.device_node);
+ iounmap(fchan->reg_base);
+ kfree(fchan);
}
static int __devinit of_fsl_dma_probe(struct of_device *dev,
const struct of_device_id *match)
{
int err;
- unsigned int irq;
struct fsl_dma_device *fdev;
+ struct device_node *child;
fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
if (!fdev) {
@@ -1085,9 +936,9 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
fdev->common.dev = &dev->dev;
- irq = irq_of_parse_and_map(dev->node, 0);
- if (irq != NO_IRQ) {
- err = request_irq(irq, &fsl_dma_do_interrupt, IRQF_SHARED,
+ fdev->irq = irq_of_parse_and_map(dev->node, 0);
+ if (fdev->irq != NO_IRQ) {
+ err = request_irq(fdev->irq, &fsl_dma_do_interrupt, IRQF_SHARED,
"fsldma-device", fdev);
if (err) {
dev_err(&dev->dev, "DMA device request_irq error "
@@ -1097,7 +948,21 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
}
dev_set_drvdata(&(dev->dev), fdev);
- of_platform_bus_probe(dev->node, of_fsl_dma_chan_ids, &dev->dev);
+
+ /* We cannot use of_platform_bus_probe() because there is no
+ * of_platform_bus_remove. Instead, we manually instantiate every DMA
+ * channel object.
+ */
+ for_each_child_of_node(dev->node, child) {
+ if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
+ fsl_dma_chan_probe(fdev, child,
+ FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN,
+ "fsl,eloplus-dma-channel");
+ if (of_device_is_compatible(child, "fsl,elo-dma-channel"))
+ fsl_dma_chan_probe(fdev, child,
+ FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN,
+ "fsl,elo-dma-channel");
+ }
dma_async_device_register(&fdev->common);
return 0;
@@ -1109,6 +974,30 @@ err_no_reg:
return err;
}
+static int of_fsl_dma_remove(struct of_device *of_dev)
+{
+ struct fsl_dma_device *fdev;
+ unsigned int i;
+
+ fdev = dev_get_drvdata(&of_dev->dev);
+
+ dma_async_device_unregister(&fdev->common);
+
+ for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++)
+ if (fdev->chan[i])
+ fsl_dma_chan_remove(fdev->chan[i]);
+
+ if (fdev->irq != NO_IRQ)
+ free_irq(fdev->irq, fdev);
+
+ iounmap(fdev->reg_base);
+
+ kfree(fdev);
+ dev_set_drvdata(&of_dev->dev, NULL);
+
+ return 0;
+}
+
static struct of_device_id of_fsl_dma_ids[] = {
{ .compatible = "fsl,eloplus-dma", },
{ .compatible = "fsl,elo-dma", },
@@ -1116,15 +1005,32 @@ static struct of_device_id of_fsl_dma_ids[] = {
};
static struct of_platform_driver of_fsl_dma_driver = {
- .name = "of-fsl-dma",
+ .name = "fsl-elo-dma",
.match_table = of_fsl_dma_ids,
.probe = of_fsl_dma_probe,
+ .remove = of_fsl_dma_remove,
};
static __init int of_fsl_dma_init(void)
{
- return of_register_platform_driver(&of_fsl_dma_driver);
+ int ret;
+
+ pr_info("Freescale Elo / Elo Plus DMA driver\n");
+
+ ret = of_register_platform_driver(&of_fsl_dma_driver);
+ if (ret)
+ pr_err("fsldma: failed to register platform driver\n");
+
+ return ret;
+}
+
+static void __exit of_fsl_dma_exit(void)
+{
+ of_unregister_platform_driver(&of_fsl_dma_driver);
}
-subsys_initcall(of_fsl_dma_chan_init);
subsys_initcall(of_fsl_dma_init);
+module_exit(of_fsl_dma_exit);
+
+MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 6faf07ba0d0..4f21a512d84 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -114,6 +114,7 @@ struct fsl_dma_device {
struct dma_device common;
struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
u32 feature; /* The same as DMA channels */
+ int irq; /* Channel IRQ */
};
/* Define macros for fsl_dma_chan->feature property */
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index bc8c6e3470c..b0438c4f0c3 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
+#include <linux/i7300_idle.h>
#include "ioatdma.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
@@ -171,6 +172,11 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+#ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL
+ if (i7300_idle_platform_probe(NULL, NULL) == 0) {
+ device->common.chancnt--;
+ }
+#endif
for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
if (!ioat_chan) {
@@ -971,11 +977,9 @@ static struct ioat_desc_sw *ioat_dma_get_next_descriptor(
switch (ioat_chan->device->version) {
case IOAT_VER_1_2:
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;
}
return NULL;
}
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index 0e024fe2d8c..887072f5dc8 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -142,7 +142,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
csrow->mtype = MEM_XDR;
- csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ csrow->edac_mode = EDAC_SECDED;
dev_dbg(mci->dev,
"Initialized on node %d, chanmask=0x%x,"
" first_page=0x%lx, nr_pages=0x%x\n",
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index deb154aa47c..4353414a0b7 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -732,7 +732,6 @@ static int __init ibft_create_attribute(struct ibft_kobject *kobj_data,
attr->attr.name = name;
attr->attr.mode = S_IRUSR;
- attr->attr.owner = THIS_MODULE;
attr->hdr = hdr;
attr->show = show;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index dbd42d6c93a..7f2ee27fe76 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -127,6 +127,13 @@ config GPIO_PCF857X
This driver provides an in-kernel interface to those GPIOs using
platform-neutral GPIO calls.
+config GPIO_TWL4030
+ tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
+ depends on TWL4030_CORE
+ help
+ Say yes here to access the GPIO signals of various multi-function
+ power management chips from Texas Instruments.
+
comment "PCI GPIO expanders:"
config GPIO_BT8XX
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 01b4bbde195..6aafdeb9ad0 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -9,4 +9,5 @@ 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_TWL4030) += twl4030-gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9112830107a..faa1cc66e9c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -248,7 +248,7 @@ static ssize_t gpio_value_show(struct device *dev,
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else
- status = sprintf(buf, "%d\n", gpio_get_value_cansleep(gpio));
+ status = sprintf(buf, "%d\n", !!gpio_get_value_cansleep(gpio));
mutex_unlock(&sysfs_lock);
return status;
@@ -1105,7 +1105,7 @@ int gpio_get_value_cansleep(unsigned gpio)
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio);
- return chip->get(chip, gpio - chip->base);
+ return chip->get ? chip->get(chip, gpio - chip->base) : 0;
}
EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
@@ -1143,7 +1143,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
if (!is_out) {
int irq = gpio_to_irq(gpio);
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = irq_to_desc(irq);
/* This races with request_irq(), set_irq_type(),
* and set_irq_wake() ... but those are "rare".
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
new file mode 100644
index 00000000000..37d3eec8730
--- /dev/null
+++ b/drivers/gpio/twl4030-gpio.c
@@ -0,0 +1,521 @@
+/*
+ * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
+ *
+ * Copyright (C) 2006-2007 Texas Instruments, Inc.
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * Code re-arranged and cleaned up by:
+ * Syed Mohammed Khasim <x0khasim@ti.com>
+ *
+ * Initial Code:
+ * Andy Lowe / Nishanth Menon
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/i2c/twl4030.h>
+
+
+/*
+ * The GPIO "subchip" supports 18 GPIOs which can be configured as
+ * inputs or outputs, with pullups or pulldowns on each pin. Each
+ * GPIO can trigger interrupts on either or both edges.
+ *
+ * GPIO interrupts can be fed to either of two IRQ lines; this is
+ * intended to support multiple hosts.
+ *
+ * There are also two LED pins used sometimes as output-only GPIOs.
+ */
+
+
+static struct gpio_chip twl_gpiochip;
+static int twl4030_gpio_irq_base;
+
+/* genirq interfaces are not available to modules */
+#ifdef MODULE
+#define is_module() true
+#else
+#define is_module() false
+#endif
+
+/* GPIO_CTRL Fields */
+#define MASK_GPIO_CTRL_GPIO0CD1 BIT(0)
+#define MASK_GPIO_CTRL_GPIO1CD2 BIT(1)
+#define MASK_GPIO_CTRL_GPIO_ON BIT(2)
+
+/* Mask for GPIO registers when aggregated into a 32-bit integer */
+#define GPIO_32_MASK 0x0003ffff
+
+/* Data structures */
+static DEFINE_MUTEX(gpio_lock);
+
+/* store usage of each GPIO. - each bit represents one GPIO */
+static unsigned int gpio_usage_count;
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * To configure TWL4030 GPIO module registers
+ */
+static inline int gpio_twl4030_write(u8 address, u8 data)
+{
+ return twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
+ * PWMs A and B are dedicated to LEDs A and B, respectively.
+ */
+
+#define TWL4030_LED_LEDEN 0x0
+
+/* LEDEN bits */
+#define LEDEN_LEDAON BIT(0)
+#define LEDEN_LEDBON BIT(1)
+#define LEDEN_LEDAEXT BIT(2)
+#define LEDEN_LEDBEXT BIT(3)
+#define LEDEN_LEDAPWM BIT(4)
+#define LEDEN_LEDBPWM BIT(5)
+#define LEDEN_PWM_LENGTHA BIT(6)
+#define LEDEN_PWM_LENGTHB BIT(7)
+
+#define TWL4030_PWMx_PWMxON 0x0
+#define TWL4030_PWMx_PWMxOFF 0x1
+
+#define PWMxON_LENGTH BIT(7)
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * To read a TWL4030 GPIO module register
+ */
+static inline int gpio_twl4030_read(u8 address)
+{
+ u8 data;
+ int ret = 0;
+
+ ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
+ return (ret < 0) ? ret : data;
+}
+
+/*----------------------------------------------------------------------*/
+
+static u8 cached_leden; /* protected by gpio_lock */
+
+/* The LED lines are open drain outputs ... a FET pulls to GND, so an
+ * external pullup is needed. We could also expose the integrated PWM
+ * as a LED brightness control; we initialize it as "always on".
+ */
+static void twl4030_led_set_value(int led, int value)
+{
+ u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM;
+ int status;
+
+ if (led)
+ mask <<= 1;
+
+ mutex_lock(&gpio_lock);
+ if (value)
+ cached_leden &= ~mask;
+ else
+ cached_leden |= mask;
+ status = twl4030_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+ TWL4030_LED_LEDEN);
+ mutex_unlock(&gpio_lock);
+}
+
+static int twl4030_set_gpio_direction(int gpio, int is_input)
+{
+ u8 d_bnk = gpio >> 3;
+ u8 d_msk = BIT(gpio & 0x7);
+ u8 reg = 0;
+ u8 base = REG_GPIODATADIR1 + d_bnk;
+ int ret = 0;
+
+ mutex_lock(&gpio_lock);
+ ret = gpio_twl4030_read(base);
+ if (ret >= 0) {
+ if (is_input)
+ reg = ret & ~d_msk;
+ else
+ reg = ret | d_msk;
+
+ ret = gpio_twl4030_write(base, reg);
+ }
+ mutex_unlock(&gpio_lock);
+ return ret;
+}
+
+static int twl4030_set_gpio_dataout(int gpio, int enable)
+{
+ u8 d_bnk = gpio >> 3;
+ u8 d_msk = BIT(gpio & 0x7);
+ u8 base = 0;
+
+ if (enable)
+ base = REG_SETGPIODATAOUT1 + d_bnk;
+ else
+ base = REG_CLEARGPIODATAOUT1 + d_bnk;
+
+ return gpio_twl4030_write(base, d_msk);
+}
+
+static int twl4030_get_gpio_datain(int gpio)
+{
+ u8 d_bnk = gpio >> 3;
+ u8 d_off = gpio & 0x7;
+ u8 base = 0;
+ int ret = 0;
+
+ if (unlikely((gpio >= TWL4030_GPIO_MAX)
+ || !(gpio_usage_count & BIT(gpio))))
+ return -EPERM;
+
+ base = REG_GPIODATAIN1 + d_bnk;
+ ret = gpio_twl4030_read(base);
+ if (ret > 0)
+ ret = (ret >> d_off) & 0x1;
+
+ return ret;
+}
+
+/*
+ * Configure debounce timing value for a GPIO pin on TWL4030
+ */
+int twl4030_set_gpio_debounce(int gpio, int enable)
+{
+ u8 d_bnk = gpio >> 3;
+ u8 d_msk = BIT(gpio & 0x7);
+ u8 reg = 0;
+ u8 base = 0;
+ int ret = 0;
+
+ if (unlikely((gpio >= TWL4030_GPIO_MAX)
+ || !(gpio_usage_count & BIT(gpio))))
+ return -EPERM;
+
+ base = REG_GPIO_DEBEN1 + d_bnk;
+ mutex_lock(&gpio_lock);
+ ret = gpio_twl4030_read(base);
+ if (ret >= 0) {
+ if (enable)
+ reg = ret | d_msk;
+ else
+ reg = ret & ~d_msk;
+
+ ret = gpio_twl4030_write(base, reg);
+ }
+ mutex_unlock(&gpio_lock);
+ return ret;
+}
+EXPORT_SYMBOL(twl4030_set_gpio_debounce);
+
+/*----------------------------------------------------------------------*/
+
+static int twl_request(struct gpio_chip *chip, unsigned offset)
+{
+ int status = 0;
+
+ mutex_lock(&gpio_lock);
+
+ /* Support the two LED outputs as output-only GPIOs. */
+ if (offset >= TWL4030_GPIO_MAX) {
+ u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
+ | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
+ u8 module = TWL4030_MODULE_PWMA;
+
+ offset -= TWL4030_GPIO_MAX;
+ if (offset) {
+ ledclr_mask <<= 1;
+ module = TWL4030_MODULE_PWMB;
+ }
+
+ /* initialize PWM to always-drive */
+ status = twl4030_i2c_write_u8(module, 0x7f,
+ TWL4030_PWMx_PWMxOFF);
+ if (status < 0)
+ goto done;
+ status = twl4030_i2c_write_u8(module, 0x7f,
+ TWL4030_PWMx_PWMxON);
+ if (status < 0)
+ goto done;
+
+ /* init LED to not-driven (high) */
+ module = TWL4030_MODULE_LED;
+ status = twl4030_i2c_read_u8(module, &cached_leden,
+ TWL4030_LED_LEDEN);
+ if (status < 0)
+ goto done;
+ cached_leden &= ~ledclr_mask;
+ status = twl4030_i2c_write_u8(module, cached_leden,
+ TWL4030_LED_LEDEN);
+ if (status < 0)
+ goto done;
+
+ status = 0;
+ goto done;
+ }
+
+ /* on first use, turn GPIO module "on" */
+ if (!gpio_usage_count) {
+ struct twl4030_gpio_platform_data *pdata;
+ u8 value = MASK_GPIO_CTRL_GPIO_ON;
+
+ /* optionally have the first two GPIOs switch vMMC1
+ * and vMMC2 power supplies based on card presence.
+ */
+ pdata = chip->dev->platform_data;
+ value |= pdata->mmc_cd & 0x03;
+
+ status = gpio_twl4030_write(REG_GPIO_CTRL, value);
+ }
+
+ if (!status)
+ gpio_usage_count |= (0x1 << offset);
+
+done:
+ mutex_unlock(&gpio_lock);
+ return status;
+}
+
+static void twl_free(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset >= TWL4030_GPIO_MAX) {
+ twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
+ return;
+ }
+
+ mutex_lock(&gpio_lock);
+
+ gpio_usage_count &= ~BIT(offset);
+
+ /* on last use, switch off GPIO module */
+ if (!gpio_usage_count)
+ gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
+
+ mutex_unlock(&gpio_lock);
+}
+
+static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ return (offset < TWL4030_GPIO_MAX)
+ ? twl4030_set_gpio_direction(offset, 1)
+ : -EINVAL;
+}
+
+static int twl_get(struct gpio_chip *chip, unsigned offset)
+{
+ int status = 0;
+
+ if (offset < TWL4030_GPIO_MAX)
+ status = twl4030_get_gpio_datain(offset);
+ else if (offset == TWL4030_GPIO_MAX)
+ status = cached_leden & LEDEN_LEDAON;
+ else
+ status = cached_leden & LEDEN_LEDBON;
+ return (status < 0) ? 0 : status;
+}
+
+static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (offset < TWL4030_GPIO_MAX) {
+ twl4030_set_gpio_dataout(offset, value);
+ return twl4030_set_gpio_direction(offset, 0);
+ } else {
+ twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
+ return 0;
+ }
+}
+
+static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (offset < TWL4030_GPIO_MAX)
+ twl4030_set_gpio_dataout(offset, value);
+ else
+ twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
+}
+
+static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX))
+ ? (twl4030_gpio_irq_base + offset)
+ : -EINVAL;
+}
+
+static struct gpio_chip twl_gpiochip = {
+ .label = "twl4030",
+ .owner = THIS_MODULE,
+ .request = twl_request,
+ .free = twl_free,
+ .direction_input = twl_direction_in,
+ .get = twl_get,
+ .direction_output = twl_direction_out,
+ .set = twl_set,
+ .to_irq = twl_to_irq,
+ .can_sleep = 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+{
+ u8 message[6];
+ unsigned i, gpio_bit;
+
+ /* For most pins, a pulldown was enabled by default.
+ * We should have data that's specific to this board.
+ */
+ for (gpio_bit = 1, i = 1; i < 6; i++) {
+ u8 bit_mask;
+ unsigned j;
+
+ for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) {
+ if (ups & gpio_bit)
+ bit_mask |= 1 << (j + 1);
+ else if (downs & gpio_bit)
+ bit_mask |= 1 << (j + 0);
+ }
+ message[i] = bit_mask;
+ }
+
+ return twl4030_i2c_write(TWL4030_MODULE_GPIO, message,
+ REG_GPIOPUPDCTR1, 5);
+}
+
+static int gpio_twl4030_remove(struct platform_device *pdev);
+
+static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+{
+ struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+
+ /* maybe setup IRQs */
+ if (pdata->irq_base) {
+ if (is_module()) {
+ dev_err(&pdev->dev,
+ "can't dispatch IRQs from modules\n");
+ goto no_irqs;
+ }
+ ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
+ if (ret < 0)
+ return ret;
+ WARN_ON(ret != pdata->irq_base);
+ twl4030_gpio_irq_base = ret;
+ }
+
+no_irqs:
+ /*
+ * NOTE: boards may waste power if they don't set pullups
+ * and pulldowns correctly ... default for non-ULPI pins is
+ * pulldown, and some other pins may have external pullups
+ * or pulldowns. Careful!
+ */
+ ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+ if (ret)
+ dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+ pdata->pullups, pdata->pulldowns,
+ ret);
+
+ twl_gpiochip.base = pdata->gpio_base;
+ twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
+ twl_gpiochip.dev = &pdev->dev;
+
+ /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+ * is (still) clear if use_leds is set.
+ */
+ if (pdata->use_leds)
+ twl_gpiochip.ngpio += 2;
+
+ ret = gpiochip_add(&twl_gpiochip);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "could not register gpiochip, %d\n",
+ ret);
+ twl_gpiochip.ngpio = 0;
+ gpio_twl4030_remove(pdev);
+ } else if (pdata->setup) {
+ int status;
+
+ status = pdata->setup(&pdev->dev,
+ pdata->gpio_base, TWL4030_GPIO_MAX);
+ if (status)
+ dev_dbg(&pdev->dev, "setup --> %d\n", status);
+ }
+
+ return ret;
+}
+
+static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
+{
+ struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+ int status;
+
+ if (pdata->teardown) {
+ status = pdata->teardown(&pdev->dev,
+ pdata->gpio_base, TWL4030_GPIO_MAX);
+ if (status) {
+ dev_dbg(&pdev->dev, "teardown --> %d\n", status);
+ return status;
+ }
+ }
+
+ status = gpiochip_remove(&twl_gpiochip);
+ if (status < 0)
+ return status;
+
+ if (is_module())
+ return 0;
+
+ /* REVISIT no support yet for deregistering all the IRQs */
+ WARN_ON(1);
+ return -EIO;
+}
+
+/* Note: this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl4030_gpio");
+
+static struct platform_driver gpio_twl4030_driver = {
+ .driver.name = "twl4030_gpio",
+ .driver.owner = THIS_MODULE,
+ .probe = gpio_twl4030_probe,
+ .remove = __devexit_p(gpio_twl4030_remove),
+};
+
+static int __init gpio_twl4030_init(void)
+{
+ return platform_driver_register(&gpio_twl4030_driver);
+}
+subsys_initcall(gpio_twl4030_init);
+
+static void __exit gpio_twl4030_exit(void)
+{
+ platform_driver_unregister(&gpio_twl4030_driver);
+}
+module_exit(gpio_twl4030_exit);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPIO interface for TWL4030");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 9097500de5f..a8b33c2ec8d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -6,7 +6,7 @@
#
menuconfig DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
- depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && SHMEM
+ depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c
index 1839c57663c..80be1cab62a 100644
--- a/drivers/gpu/drm/drm_drawable.c
+++ b/drivers/gpu/drm/drm_drawable.c
@@ -76,11 +76,18 @@ int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_draw *draw = data;
unsigned long irqflags;
+ struct drm_drawable_info *info;
spin_lock_irqsave(&dev->drw_lock, irqflags);
- drm_free(drm_get_drawable_info(dev, draw->handle),
- sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+ info = drm_get_drawable_info(dev, draw->handle);
+ if (info == NULL) {
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ return -EINVAL;
+ }
+ drm_free(info->rects, info->num_rects * sizeof(struct drm_clip_rect),
+ DRM_MEM_BUFS);
+ drm_free(info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
idr_remove(&dev->drw_idr, draw->handle);
@@ -111,7 +118,9 @@ int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file
switch (update->type) {
case DRM_DRAWABLE_CLIPRECTS:
- if (update->num != info->num_rects) {
+ if (update->num == 0)
+ rects = NULL;
+ else if (update->num != info->num_rects) {
rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
DRM_MEM_BUFS);
} else
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 90f5a8d9bdc..920b72fbc95 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -64,6 +64,8 @@
#define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t)
#define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t)
+#define DRM_IOCTL_UPDATE_DRAW32 DRM_IOW( 0x3f, drm_update_draw32_t)
+
#define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
typedef struct drm_version_32 {
@@ -952,6 +954,37 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
DRM_IOCTL_SG_FREE, (unsigned long)request);
}
+typedef struct drm_update_draw32 {
+ drm_drawable_t handle;
+ unsigned int type;
+ unsigned int num;
+ /* 64-bit version has a 32-bit pad here */
+ u64 data; /**< Pointer */
+} __attribute__((packed)) drm_update_draw32_t;
+
+static int compat_drm_update_draw(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_update_draw32_t update32;
+ struct drm_update_draw __user *request;
+ int err;
+
+ if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) ||
+ __put_user(update32.handle, &request->handle) ||
+ __put_user(update32.type, &request->type) ||
+ __put_user(update32.num, &request->num) ||
+ __put_user(update32.data, &request->data))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
+ return err;
+}
+
struct drm_wait_vblank_request32 {
enum drm_vblank_seq_type type;
unsigned int sequence;
@@ -1033,6 +1066,7 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = {
#endif
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
+ [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
};
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 4091b9e291f..212a94f715b 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -594,11 +594,14 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
goto done;
}
+ /* Get a refcount on the vblank, which will be released by
+ * drm_vbl_send_signals().
+ */
ret = drm_vblank_get(dev, crtc);
if (ret) {
drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
DRM_MEM_DRIVER);
- return ret;
+ goto done;
}
atomic_inc(&dev->vbl_signal_pending);
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index a4caf95485d..888159e03d2 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -232,6 +232,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
}
return 0;
}
+EXPORT_SYMBOL(drm_lock_take);
/**
* This takes a lock forcibly and hands it to context. Should ONLY be used
@@ -299,6 +300,7 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
wake_up_interruptible(&lock_data->lock_queue);
return 0;
}
+EXPORT_SYMBOL(drm_lock_free);
/**
* If we get here, it means that the process has called DRM_IOCTL_LOCK
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index d490db4c0de..ae73b7f7249 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -522,12 +522,12 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)
struct drm_gem_object *obj = ptr;
struct drm_gem_name_info_data *nid = data;
- DRM_INFO("name %d size %d\n", obj->name, obj->size);
+ DRM_INFO("name %d size %zd\n", obj->name, obj->size);
if (nid->eof)
return 0;
nid->len += sprintf(&nid->buf[nid->len],
- "%6d%9d%8d%9d\n",
+ "%6d %8zd %7d %8d\n",
obj->name, obj->size,
atomic_read(&obj->handlecount.refcount),
atomic_read(&obj->refcount.refcount));
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index db34780edbb..01de536e021 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -844,8 +844,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
* correctly in testing on 945G.
* This may be a side effect of MSI having been made available for PEG
* and the registers being closely associated.
+ *
+ * According to chipset errata, on the 965GM, MSI interrupts may
+ * be lost or delayed
*/
- if (!IS_I945G(dev) && !IS_I945GM(dev))
+ if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev))
if (pci_enable_msi(dev->pdev))
DRM_ERROR("failed to enable MSI\n");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eae4ed3956e..f20ffe17df7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -90,7 +90,7 @@ struct mem_block {
typedef struct _drm_i915_vbl_swap {
struct list_head head;
drm_drawable_t drw_id;
- unsigned int plane;
+ unsigned int pipe;
unsigned int sequence;
} drm_i915_vbl_swap_t;
@@ -240,6 +240,9 @@ typedef struct drm_i915_private {
u8 saveDACDATA[256*3]; /* 256 3-byte colors */
u8 saveCR[37];
+ /** Work task for vblank-related ring access */
+ struct work_struct vblank_work;
+
struct {
struct drm_mm gtt_space;
@@ -285,9 +288,6 @@ typedef struct drm_i915_private {
*/
struct delayed_work retire_work;
- /** Work task for vblank-related ring access */
- struct work_struct vblank_work;
-
uint32_t next_gem_seqno;
/**
@@ -441,7 +441,7 @@ extern int i915_irq_wait(struct drm_device *dev, void *data,
void i915_user_irq_get(struct drm_device *dev);
void i915_user_irq_put(struct drm_device *dev);
-extern void i915_gem_vblank_work_handler(struct work_struct *work);
+extern void i915_vblank_work_handler(struct work_struct *work);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(struct drm_device * dev);
extern int i915_driver_irq_postinstall(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9ac73dd1b42..17ae330ff26 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -171,6 +171,37 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
return 0;
}
+/*
+ * Try to write quickly with an atomic kmap. Return true on success.
+ *
+ * If this fails (which includes a partial write), we'll redo the whole
+ * thing with the slow version.
+ *
+ * This is a workaround for the low performance of iounmap (approximate
+ * 10% cpu cost on normal 3D workloads). kmap_atomic on HIGHMEM kernels
+ * happens to let us map card memory without taking IPIs. When the vmap
+ * rework lands we should be able to dump this hack.
+ */
+static inline int fast_user_write(unsigned long pfn, char __user *user_data,
+ int l, int o)
+{
+#ifdef CONFIG_HIGHMEM
+ unsigned long unwritten;
+ char *vaddr_atomic;
+
+ vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0);
+#if WATCH_PWRITE
+ DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
+ i, o, l, pfn, vaddr_atomic);
+#endif
+ unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o, user_data, l);
+ kunmap_atomic(vaddr_atomic, KM_USER0);
+ return !unwritten;
+#else
+ return 0;
+#endif
+}
+
static int
i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
struct drm_i915_gem_pwrite *args,
@@ -180,12 +211,7 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
ssize_t remain;
loff_t offset;
char __user *user_data;
- char __iomem *vaddr;
- char *vaddr_atomic;
- int i, o, l;
int ret = 0;
- unsigned long pfn;
- unsigned long unwritten;
user_data = (char __user *) (uintptr_t) args->data_ptr;
remain = args->size;
@@ -209,6 +235,9 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
obj_priv->dirty = 1;
while (remain > 0) {
+ unsigned long pfn;
+ int i, o, l;
+
/* Operation in this page
*
* i = page number
@@ -223,25 +252,10 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
pfn = (dev->agp->base >> PAGE_SHIFT) + i;
-#ifdef CONFIG_HIGHMEM
- /* This is a workaround for the low performance of iounmap
- * (approximate 10% cpu cost on normal 3D workloads).
- * kmap_atomic on HIGHMEM kernels happens to let us map card
- * memory without taking IPIs. When the vmap rework lands
- * we should be able to dump this hack.
- */
- vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0);
-#if WATCH_PWRITE
- DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
- i, o, l, pfn, vaddr_atomic);
-#endif
- unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o,
- user_data, l);
- kunmap_atomic(vaddr_atomic, KM_USER0);
+ if (!fast_user_write(pfn, user_data, l, o)) {
+ unsigned long unwritten;
+ char __iomem *vaddr;
- if (unwritten)
-#endif /* CONFIG_HIGHMEM */
- {
vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE);
#if WATCH_PWRITE
DRM_INFO("pwrite slow i %d o %d l %d "
@@ -2550,8 +2564,6 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->mm.request_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler);
- INIT_WORK(&dev_priv->mm.vblank_work,
- i915_gem_vblank_work_handler);
dev_priv->mm.next_gem_seqno = 1;
i915_gem_detect_bit_6_swizzle(dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
index 15d4160415b..93de15b4c9a 100644
--- a/drivers/gpu/drm/i915/i915_gem_proc.c
+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
@@ -192,7 +192,12 @@ static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
*start = &buf[offset];
*eof = 0;
- DRM_PROC_PRINT("Current sequence: %d\n", i915_get_gem_seqno(dev));
+ if (dev_priv->hw_status_page != NULL) {
+ DRM_PROC_PRINT("Current sequence: %d\n",
+ i915_get_gem_seqno(dev));
+ } else {
+ DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
+ }
DRM_PROC_PRINT("Waiter sequence: %d\n",
dev_priv->mm.waiting_gem_seqno);
DRM_PROC_PRINT("IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
@@ -230,8 +235,12 @@ static int i915_interrupt_info(char *buf, char **start, off_t offset,
I915_READ(PIPEBSTAT));
DRM_PROC_PRINT("Interrupts received: %d\n",
atomic_read(&dev_priv->irq_received));
- DRM_PROC_PRINT("Current sequence: %d\n",
- i915_get_gem_seqno(dev));
+ if (dev_priv->hw_status_page != NULL) {
+ DRM_PROC_PRINT("Current sequence: %d\n",
+ i915_get_gem_seqno(dev));
+ } else {
+ DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
+ }
DRM_PROC_PRINT("Waiter sequence: %d\n",
dev_priv->mm.waiting_gem_seqno);
DRM_PROC_PRINT("IRQ sequence: %d\n",
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index baae511c785..26f48932a51 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -60,43 +60,6 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
}
/**
- * i915_get_pipe - return the the pipe associated with a given plane
- * @dev: DRM device
- * @plane: plane to look for
- *
- * The Intel Mesa & 2D drivers call the vblank routines with a plane number
- * rather than a pipe number, since they may not always be equal. This routine
- * maps the given @plane back to a pipe number.
- */
-static int
-i915_get_pipe(struct drm_device *dev, int plane)
-{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 dspcntr;
-
- dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
-
- return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
-}
-
-/**
- * i915_get_plane - return the the plane associated with a given pipe
- * @dev: DRM device
- * @pipe: pipe to look for
- *
- * The Intel Mesa & 2D drivers call the vblank routines with a plane number
- * rather than a plane number, since they may not always be equal. This routine
- * maps the given @pipe back to a plane number.
- */
-static int
-i915_get_plane(struct drm_device *dev, int pipe)
-{
- if (i915_get_pipe(dev, 0) == pipe)
- return 0;
- return 1;
-}
-
-/**
* i915_pipe_enabled - check if a pipe is enabled
* @dev: DRM device
* @pipe: pipe to check
@@ -121,6 +84,9 @@ i915_pipe_enabled(struct drm_device *dev, int pipe)
* Emit blits for scheduled buffer swaps.
*
* This function will be called with the HW lock held.
+ * Because this function must grab the ring mutex (dev->struct_mutex),
+ * it can no longer run at soft irq time. We'll fix this when we do
+ * the DRI2 swap buffer work.
*/
static void i915_vblank_tasklet(struct drm_device *dev)
{
@@ -141,6 +107,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
RING_LOCALS;
+ mutex_lock(&dev->struct_mutex);
+
if (IS_I965G(dev) && sarea_priv->front_tiled) {
cmd |= XY_SRC_COPY_BLT_DST_TILED;
dst_pitch >>= 2;
@@ -165,7 +133,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
drm_i915_vbl_swap_t *vbl_swap =
list_entry(list, drm_i915_vbl_swap_t, head);
- int pipe = i915_get_pipe(dev, vbl_swap->plane);
+ int pipe = vbl_swap->pipe;
if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
continue;
@@ -179,20 +147,19 @@ static void i915_vblank_tasklet(struct drm_device *dev)
drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
- if (!drw) {
- spin_unlock(&dev->drw_lock);
- drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
- spin_lock(&dev_priv->swaps_lock);
- continue;
- }
-
list_for_each(hit, &hits) {
drm_i915_vbl_swap_t *swap_cmp =
list_entry(hit, drm_i915_vbl_swap_t, head);
struct drm_drawable_info *drw_cmp =
drm_get_drawable_info(dev, swap_cmp->drw_id);
- if (drw_cmp &&
+ /* Make sure both drawables are still
+ * around and have some rectangles before
+ * we look inside to order them for the
+ * blts below.
+ */
+ if (drw_cmp && drw_cmp->num_rects > 0 &&
+ drw && drw->num_rects > 0 &&
drw_cmp->rects[0].y1 > drw->rects[0].y1) {
list_add_tail(list, hit);
break;
@@ -212,6 +179,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
if (nhits == 0) {
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+ mutex_unlock(&dev->struct_mutex);
return;
}
@@ -265,18 +233,21 @@ static void i915_vblank_tasklet(struct drm_device *dev)
drm_i915_vbl_swap_t *swap_hit =
list_entry(hit, drm_i915_vbl_swap_t, head);
struct drm_clip_rect *rect;
- int num_rects, plane;
+ int num_rects, pipe;
unsigned short top, bottom;
drw = drm_get_drawable_info(dev, swap_hit->drw_id);
+ /* The drawable may have been destroyed since
+ * the vblank swap was queued
+ */
if (!drw)
continue;
rect = drw->rects;
- plane = swap_hit->plane;
- top = upper[plane];
- bottom = lower[plane];
+ pipe = swap_hit->pipe;
+ top = upper[pipe];
+ bottom = lower[pipe];
for (num_rects = drw->num_rects; num_rects--; rect++) {
int y1 = max(rect->y1, top);
@@ -302,6 +273,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
}
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ mutex_unlock(&dev->struct_mutex);
list_for_each_safe(hit, tmp, &hits) {
drm_i915_vbl_swap_t *swap_hit =
@@ -313,15 +285,16 @@ static void i915_vblank_tasklet(struct drm_device *dev)
}
}
-u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+/* Called from drm generic code, passed a 'crtc', which
+ * we use as a pipe index
+ */
+u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long high_frame;
unsigned long low_frame;
u32 high1, high2, low, count;
- int pipe;
- pipe = i915_get_pipe(dev, plane);
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
@@ -350,18 +323,37 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
}
void
-i915_gem_vblank_work_handler(struct work_struct *work)
+i915_vblank_work_handler(struct work_struct *work)
{
- drm_i915_private_t *dev_priv;
- struct drm_device *dev;
+ drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+ vblank_work);
+ struct drm_device *dev = dev_priv->dev;
+ unsigned long irqflags;
- dev_priv = container_of(work, drm_i915_private_t,
- mm.vblank_work);
- dev = dev_priv->dev;
+ if (dev->lock.hw_lock == NULL) {
+ i915_vblank_tasklet(dev);
+ return;
+ }
+
+ spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+ dev->locked_tasklet_func = i915_vblank_tasklet;
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
+ /* Try to get the lock now, if this fails, the lock
+ * holder will execute the tasklet during unlock
+ */
+ if (!drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT))
+ return;
+
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+
+ spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+ dev->locked_tasklet_func = NULL;
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
- mutex_lock(&dev->struct_mutex);
i915_vblank_tasklet(dev);
- mutex_unlock(&dev->struct_mutex);
+ drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
}
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
@@ -398,7 +390,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
PIPE_VBLANK_INTERRUPT_STATUS)) {
vblank++;
- drm_handle_vblank(dev, i915_get_plane(dev, 0));
+ drm_handle_vblank(dev, 0);
}
I915_WRITE(PIPEASTAT, pipea_stats);
@@ -416,7 +408,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
PIPE_VBLANK_INTERRUPT_STATUS)) {
vblank++;
- drm_handle_vblank(dev, i915_get_plane(dev, 1));
+ drm_handle_vblank(dev, 1);
}
if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
@@ -441,12 +433,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (iir & I915_ASLE_INTERRUPT)
opregion_asle_intr(dev);
- if (vblank && dev_priv->swaps_pending > 0) {
- if (dev_priv->ring.ring_obj == NULL)
- drm_locked_tasklet(dev, i915_vblank_tasklet);
- else
- schedule_work(&dev_priv->mm.vblank_work);
- }
+ if (vblank && dev_priv->swaps_pending > 0)
+ schedule_work(&dev_priv->vblank_work);
return IRQ_HANDLED;
}
@@ -481,22 +469,24 @@ static int i915_emit_irq(struct drm_device * dev)
void i915_user_irq_get(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long irqflags;
- spin_lock(&dev_priv->user_irq_lock);
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
- spin_unlock(&dev_priv->user_irq_lock);
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
void i915_user_irq_put(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long irqflags;
- spin_lock(&dev_priv->user_irq_lock);
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
- spin_unlock(&dev_priv->user_irq_lock);
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
@@ -578,74 +568,95 @@ int i915_irq_wait(struct drm_device *dev, void *data,
return i915_wait_irq(dev, irqwait->irq_seq);
}
-int i915_enable_vblank(struct drm_device *dev, int plane)
+/* Called from drm generic code, passed 'crtc' which
+ * we use as a pipe index
+ */
+int i915_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- int pipe = i915_get_pipe(dev, plane);
u32 pipestat_reg = 0;
u32 pipestat;
+ u32 interrupt = 0;
+ unsigned long irqflags;
switch (pipe) {
case 0:
pipestat_reg = PIPEASTAT;
- i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
+ interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
break;
case 1:
pipestat_reg = PIPEBSTAT;
- i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+ interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
break;
default:
DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
pipe);
- break;
+ return 0;
}
- if (pipestat_reg) {
- pipestat = I915_READ(pipestat_reg);
- if (IS_I965G(dev))
- pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
- else
- pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
- /* Clear any stale interrupt status */
- pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS);
- I915_WRITE(pipestat_reg, pipestat);
- }
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ /* Enabling vblank events in IMR comes before PIPESTAT write, or
+ * there's a race where the PIPESTAT vblank bit gets set to 1, so
+ * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in
+ * ISR flashes to 1, but the IIR bit doesn't get set to 1 because
+ * IMR masks it. It doesn't ever get set after we clear the masking
+ * in IMR because the ISR bit is edge, not level-triggered, on the
+ * OR of PIPESTAT bits.
+ */
+ i915_enable_irq(dev_priv, interrupt);
+ pipestat = I915_READ(pipestat_reg);
+ if (IS_I965G(dev))
+ pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ else
+ pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
+ /* Clear any stale interrupt status */
+ pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+ PIPE_VBLANK_INTERRUPT_STATUS);
+ I915_WRITE(pipestat_reg, pipestat);
+ (void) I915_READ(pipestat_reg); /* Posting read */
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
return 0;
}
-void i915_disable_vblank(struct drm_device *dev, int plane)
+/* Called from drm generic code, passed 'crtc' which
+ * we use as a pipe index
+ */
+void i915_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- int pipe = i915_get_pipe(dev, plane);
u32 pipestat_reg = 0;
u32 pipestat;
+ u32 interrupt = 0;
+ unsigned long irqflags;
switch (pipe) {
case 0:
pipestat_reg = PIPEASTAT;
- i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
+ interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
break;
case 1:
pipestat_reg = PIPEBSTAT;
- i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+ interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
break;
default:
DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
pipe);
+ return;
break;
}
- if (pipestat_reg) {
- pipestat = I915_READ(pipestat_reg);
- pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- /* Clear any stale interrupt status */
- pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS);
- I915_WRITE(pipestat_reg, pipestat);
- }
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ i915_disable_irq(dev_priv, interrupt);
+ pipestat = I915_READ(pipestat_reg);
+ pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ /* Clear any stale interrupt status */
+ pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+ PIPE_VBLANK_INTERRUPT_STATUS);
+ I915_WRITE(pipestat_reg, pipestat);
+ (void) I915_READ(pipestat_reg); /* Posting read */
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
/* Set the vblank monitor pipe
@@ -687,8 +698,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_vblank_swap_t *swap = data;
- drm_i915_vbl_swap_t *vbl_swap;
- unsigned int pipe, seqtype, curseq, plane;
+ drm_i915_vbl_swap_t *vbl_swap, *vbl_old;
+ unsigned int pipe, seqtype, curseq;
unsigned long irqflags;
struct list_head *list;
int ret;
@@ -709,8 +720,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
return -EINVAL;
}
- plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
- pipe = i915_get_pipe(dev, plane);
+ pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
@@ -751,44 +761,52 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
}
}
+ vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+
+ if (!vbl_swap) {
+ DRM_ERROR("Failed to allocate memory to queue swap\n");
+ drm_vblank_put(dev, pipe);
+ return -ENOMEM;
+ }
+
+ vbl_swap->drw_id = swap->drawable;
+ vbl_swap->pipe = pipe;
+ vbl_swap->sequence = swap->sequence;
+
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
list_for_each(list, &dev_priv->vbl_swaps.head) {
- vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+ vbl_old = list_entry(list, drm_i915_vbl_swap_t, head);
- if (vbl_swap->drw_id == swap->drawable &&
- vbl_swap->plane == plane &&
- vbl_swap->sequence == swap->sequence) {
+ if (vbl_old->drw_id == swap->drawable &&
+ vbl_old->pipe == pipe &&
+ vbl_old->sequence == swap->sequence) {
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+ drm_vblank_put(dev, pipe);
+ drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
DRM_DEBUG("Already scheduled\n");
return 0;
}
}
- spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-
- if (dev_priv->swaps_pending >= 100) {
+ if (dev_priv->swaps_pending >= 10) {
DRM_DEBUG("Too many swaps queued\n");
+ DRM_DEBUG(" pipe 0: %d pipe 1: %d\n",
+ drm_vblank_count(dev, 0),
+ drm_vblank_count(dev, 1));
+
+ list_for_each(list, &dev_priv->vbl_swaps.head) {
+ vbl_old = list_entry(list, drm_i915_vbl_swap_t, head);
+ DRM_DEBUG("\tdrw %x pipe %d seq %x\n",
+ vbl_old->drw_id, vbl_old->pipe,
+ vbl_old->sequence);
+ }
+ spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
drm_vblank_put(dev, pipe);
+ drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
return -EBUSY;
}
- vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER);
-
- if (!vbl_swap) {
- DRM_ERROR("Failed to allocate memory to queue swap\n");
- drm_vblank_put(dev, pipe);
- return -ENOMEM;
- }
-
- DRM_DEBUG("\n");
-
- vbl_swap->drw_id = swap->drawable;
- vbl_swap->plane = plane;
- vbl_swap->sequence = swap->sequence;
-
- spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
-
list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head);
dev_priv->swaps_pending++;
@@ -815,6 +833,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
spin_lock_init(&dev_priv->swaps_lock);
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+ INIT_WORK(&dev_priv->vblank_work, i915_vblank_work_handler);
dev_priv->swaps_pending = 0;
/* Set initial unmasked IRQs to just the selected vblank pipes. */
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f5999a91614..b4fd8ca701a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -247,7 +247,6 @@ config HID_SUNPLUS
config THRUSTMASTER_FF
tristate "ThrustMaster devices support"
- default m
depends on USB_HID
select INPUT_FF_MEMLESS
help
@@ -256,7 +255,6 @@ config THRUSTMASTER_FF
config ZEROPLUS_FF
tristate "Zeroplus based game controller support"
- default m
depends on USB_HID
select INPUT_FF_MEMLESS
help
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index fd7f896b34f..c6ab4ba60c5 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -312,13 +312,6 @@ static int apple_probe(struct hid_device *hdev,
unsigned int connect_mask = HID_CONNECT_DEFAULT;
int ret;
- /* return something else or move to hid layer? device will reside
- allocated */
- if (id->bus == BUS_USB && (quirks & APPLE_IGNORE_MOUSE) &&
- to_usb_interface(hdev->dev.parent)->cur_altsetting->
- desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
- return -ENODEV;
-
asc = kzalloc(sizeof(*asc), GFP_KERNEL);
if (asc == NULL) {
dev_err(&hdev->dev, "can't alloc apple descriptor\n");
@@ -367,38 +360,32 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+ APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+ APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+ APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS},
+ APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
.driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
@@ -406,14 +393,12 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
.driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
@@ -422,25 +407,21 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
- .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
- .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
- .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
- .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
- .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
- .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
- .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
- APPLE_IGNORE_MOUSE },
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
/* Apple wireless Mighty Mouse */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 721a36d9758..743e6f8cb20 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1264,6 +1264,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
@@ -1275,8 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
@@ -1295,6 +1294,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
@@ -1406,6 +1406,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)},
{ HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
@@ -1541,6 +1542,40 @@ static const struct hid_device_id hid_ignore_list[] = {
{ }
};
+/**
+ * hid_mouse_ignore_list - mouse devices which should not be handled by the hid layer
+ *
+ * There are composite devices for which we want to ignore only a certain
+ * interface. This is a list of devices for which only the mouse interface will
+ * be ignored. This allows a dedicated driver to take care of the interface.
+ */
+static const struct hid_device_id hid_mouse_ignore_list[] = {
+ /* appletouch driver */
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+ { }
+};
+
static bool hid_ignore(struct hid_device *hdev)
{
switch (hdev->vendor) {
@@ -1557,6 +1592,10 @@ static bool hid_ignore(struct hid_device *hdev)
break;
}
+ if (hdev->type == HID_TYPE_USBMOUSE &&
+ hid_match_id(hdev, hid_mouse_ignore_list))
+ return true;
+
return !!hid_match_id(hdev, hid_ignore_list);
}
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
index ac5120f542c..04a0afec52a 100644
--- a/drivers/hid/hid-gyration.c
+++ b/drivers/hid/hid-gyration.c
@@ -4,9 +4,9 @@
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
* Copyright (c) 2007 Paul Walmsley
* Copyright (c) 2008 Jiri Slaby
+ * Copyright (c) 2006-2008 Jiri Kosina
*/
/*
@@ -40,6 +40,7 @@ static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case 0x025: gy_map_key_clear(KEY_PVR); break;
case 0x046: gy_map_key_clear(KEY_MEDIA); break;
case 0x047: gy_map_key_clear(KEY_MP3); break;
+ case 0x048: gy_map_key_clear(KEY_MEDIA); break;
case 0x049: gy_map_key_clear(KEY_CAMERA); break;
case 0x04a: gy_map_key_clear(KEY_VIDEO); break;
@@ -68,6 +69,7 @@ static int gyration_event(struct hid_device *hdev, struct hid_field *field,
static const struct hid_device_id gyration_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ }
};
MODULE_DEVICE_TABLE(hid, gyration_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index d9a1ba920c2..a0d6a6cb184 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -89,6 +89,7 @@
#define USB_VENDOR_ID_ASUS 0x0b05
#define USB_DEVICE_ID_ASUS_LCM 0x1726
+#define USB_DEVICE_ID_ASUS_LCM2 0x175b
#define USB_VENDOR_ID_ATEN 0x0557
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
@@ -236,6 +237,7 @@
#define USB_VENDOR_ID_GYRATION 0x0c16
#define USB_DEVICE_ID_GYRATION_REMOTE 0x0002
+#define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
#define USB_VENDOR_ID_HAPP 0x078b
#define USB_DEVICE_ID_UGCI_DRIVING 0x0010
@@ -268,8 +270,6 @@
#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_FIRST 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
@@ -350,6 +350,7 @@
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
#define USB_VENDOR_ID_SONY 0x054c
+#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 406d8c82abf..2bae340eafe 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -287,11 +287,6 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3),
- .driver_data = LG_INVERT_HWHEEL },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150),
- .driver_data = LG_INVERT_HWHEEL },
-
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
.driver_data = LG_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 3af8095a7de..86e563b8d64 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -4,9 +4,9 @@
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
* Copyright (c) 2007 Paul Walmsley
* Copyright (c) 2008 Jiri Slaby
+ * Copyright (c) 2006-2008 Jiri Kosina
*/
/*
@@ -23,6 +23,26 @@
#include "hid-ids.h"
+#define VAIO_RDESC_CONSTANT 0x0001
+
+struct sony_sc {
+ unsigned long quirks;
+};
+
+/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
+static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ struct sony_sc *sc = hid_get_drvdata(hdev);
+
+ if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
+ rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
+ dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report "
+ "descriptor\n");
+ rdesc[55] = 0x06;
+ }
+}
+
/*
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
* to "operational". Without this, the ps3 controller will not report any
@@ -56,6 +76,17 @@ static int sony_set_operational(struct hid_device *hdev)
static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
+ unsigned long quirks = id->driver_data;
+ struct sony_sc *sc;
+
+ sc = kzalloc(sizeof(*sc), GFP_KERNEL);
+ if (sc == NULL) {
+ dev_err(&hdev->dev, "can't alloc apple descriptor\n");
+ return -ENOMEM;
+ }
+
+ sc->quirks = quirks;
+ hid_set_drvdata(hdev, sc);
ret = hid_parse(hdev);
if (ret) {
@@ -78,11 +109,20 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
err_stop:
hid_hw_stop(hdev);
err_free:
+ kfree(sc);
return ret;
}
+static void sony_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+}
+
static const struct hid_device_id sony_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
+ .driver_data = VAIO_RDESC_CONSTANT },
{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);
@@ -91,6 +131,8 @@ static struct hid_driver sony_driver = {
.name = "sony",
.id_table = sony_devices,
.probe = sony_probe,
+ .remove = sony_remove,
+ .report_fixup = sony_report_fixup,
};
static int sony_init(void)
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index af3edb98df4..894d52e05bf 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -264,6 +264,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
default:
ret = -ENOTTY;
}
+ unlock_kernel();
return ret;
}
@@ -403,7 +404,7 @@ out:
return result;
}
-void __exit hidraw_exit(void)
+void hidraw_exit(void)
{
dev_t dev_id = MKDEV(hidraw_major, 0);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 705a43cdeea..42bdd83444c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -972,6 +972,9 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
hid->product = le16_to_cpu(dev->descriptor.idProduct);
hid->name[0] = 0;
+ if (intf->cur_altsetting->desc.bInterfaceProtocol ==
+ USB_INTERFACE_PROTOCOL_MOUSE)
+ hid->type = HID_TYPE_USBMOUSE;
if (dev->manufacturer)
strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index babd65dd46a..3ac320785fc 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -436,8 +436,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
if (copy_to_user(user_arg, uref, sizeof(*uref)))
goto fault;
- kfree(uref_multi);
- return 0;
+ goto goodreturn;
default:
if (cmd != HIDIOCGUSAGE &&
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index d9e7a49d6cb..70bb854086d 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -178,7 +178,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM", 26, 1, 1, 1, 0 },
{ "CPU Fan", 32, 2, 60, 1, 0 },
{ "NB Fan", 33, 2, 60, 1, 0 },
@@ -200,7 +200,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM1", 26, 1, 1, 1, 0 },
{ "PWM2", 27, 1, 1, 1, 0 },
{ "PWM3", 28, 1, 1, 1, 0 },
@@ -229,7 +229,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM", 26, 1, 1, 1, 0 },
{ "CPU Fan", 32, 2, 60, 1, 0 },
{ "NB Fan", 33, 2, 60, 1, 0 },
@@ -250,7 +250,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM", 26, 1, 1, 1, 0 },
{ "CPU Fan", 32, 2, 60, 1, 0 },
{ "NB Fan", 33, 2, 60, 1, 0 },
@@ -342,7 +342,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM1", 26, 1, 1, 1, 0 },
{ "PWM2", 27, 1, 1, 1, 0 },
{ "PWM3", 28, 1, 1, 1, 0 },
@@ -371,7 +371,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM", 26, 1, 1, 1, 0 },
{ "CPU Fan", 32, 2, 60, 1, 0 },
{ "NB Fan", 33, 2, 60, 1, 0 },
@@ -402,7 +402,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0016, NULL /* AW9D-MAX, need DMI string */, {
+ { 0x0016, "AW9D-MAX (Intel i975-ICH7)", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -416,7 +416,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM1", 26, 1, 1, 1, 0 },
{ "PWM2", 27, 1, 1, 1, 0 },
{ "PWM3", 28, 1, 1, 1, 0 },
@@ -446,7 +446,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "ATX +3.3V", 10, 0, 20, 1, 0 },
{ "ATX 5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 26, 1, 1, 1, 0 },
+ { "System", 26, 1, 1, 1, 0 },
{ "PWM", 27, 1, 1, 1, 0 },
{ "CPU FAN", 32, 2, 60, 1, 0 },
{ "SYS FAN", 34, 2, 60, 1, 0 },
@@ -469,7 +469,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM Phase1", 26, 1, 1, 1, 0 },
{ "PWM Phase2", 27, 1, 1, 1, 0 },
{ "PWM Phase3", 28, 1, 1, 1, 0 },
@@ -487,7 +487,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "DDR2", 13, 0, 20, 1, 0 },
{ "DDR2 VTT", 14, 0, 10, 1, 0 },
{ "CPU VTT", 3, 0, 20, 1, 0 },
- { "NB 1.2V ", 4, 0, 10, 1, 0 },
+ { "NB 1.2V", 4, 0, 10, 1, 0 },
{ "SB 1.5V", 6, 0, 10, 1, 0 },
{ "HyperTransport", 5, 0, 10, 1, 0 },
{ "ATX +12V (24-Pin)", 12, 0, 60, 1, 0 },
@@ -496,7 +496,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "ATX +3.3V", 10, 0, 20, 1, 0 },
{ "ATX 5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
{ "PWM Phase1", 26, 1, 1, 1, 0 },
{ "PWM Phase2", 27, 1, 1, 1, 0 },
{ "PWM Phase3", 28, 1, 1, 1, 0 },
@@ -523,8 +523,8 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "+3.3V", 10, 0, 20, 1, 0 },
{ "5VSB", 11, 0, 30, 1, 0 },
{ "CPU", 24, 1, 1, 1, 0 },
- { "System ", 25, 1, 1, 1, 0 },
- { "PWM ", 26, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM", 26, 1, 1, 1, 0 },
{ "PWM Phase2", 27, 1, 1, 1, 0 },
{ "PWM Phase3", 28, 1, 1, 1, 0 },
{ "PWM Phase4", 29, 1, 1, 1, 0 },
@@ -947,7 +947,7 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
if (!abituguru3_motherboards[i].dmi_name) {
printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
"not detected using DMI. Please send the output of "
- "\"dmidecode\" to the abituguru3 maintainer"
+ "\"dmidecode\" to the abituguru3 maintainer "
"(see MAINTAINERS)\n");
}
#endif
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
index 3a0b6313647..b9a8ea30c99 100644
--- a/drivers/hwmon/adt7473.c
+++ b/drivers/hwmon/adt7473.c
@@ -319,35 +319,24 @@ out:
}
/*
- * On this chip, voltages are given as a count of steps between a minimum
- * and maximum voltage, not a direct voltage.
+ * Conversions
*/
-static const int volt_convert_table[][2] = {
- {2997, 3},
- {4395, 4},
+
+/* IN are scaled acording to built-in resistors */
+static const int adt7473_scaling[] = { /* .001 Volts */
+ 2250, 3300
};
+#define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from))
static int decode_volt(int volt_index, u8 raw)
{
- int cmax = volt_convert_table[volt_index][0];
- int cmin = volt_convert_table[volt_index][1];
- return ((raw * (cmax - cmin)) / 255) + cmin;
+ return SCALE(raw, 192, adt7473_scaling[volt_index]);
}
static u8 encode_volt(int volt_index, int cooked)
{
- int cmax = volt_convert_table[volt_index][0];
- int cmin = volt_convert_table[volt_index][1];
- u8 x;
-
- if (cooked > cmax)
- cooked = cmax;
- else if (cooked < cmin)
- cooked = cmin;
-
- x = ((cooked - cmin) * 255) / (cmax - cmin);
-
- return x;
+ int raw = SCALE(cooked, adt7473_scaling[volt_index], 192);
+ return SENSORS_LIMIT(raw, 0, 255);
}
static ssize_t show_volt_min(struct device *dev,
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index b06b8e090a2..bc011da79e1 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -49,6 +49,9 @@
#define APPLESMC_MAX_DATA_LENGTH 32
+#define APPLESMC_MIN_WAIT 0x0040
+#define APPLESMC_MAX_WAIT 0x8000
+
#define APPLESMC_STATUS_MASK 0x0f
#define APPLESMC_READ_CMD 0x10
#define APPLESMC_WRITE_CMD 0x11
@@ -57,8 +60,8 @@
#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
-#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */
-#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
+#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */
+#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
@@ -104,6 +107,15 @@ static const char* temperature_sensors_sets[][36] = {
/* Set 6: Macbook3 set */
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
"Th0S", "Th1H", NULL },
+/* Set 7: Macbook Air */
+ { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP",
+ "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL },
+/* Set 8: Macbook Pro 4,1 (Penryn) */
+ { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H",
+ "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
+/* Set 9: Macbook Pro 3,1 (Santa Rosa) */
+ { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P",
+ "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
};
/* List of keys used to read/write fan speeds */
@@ -163,25 +175,25 @@ static unsigned int key_at_index;
static struct workqueue_struct *applesmc_led_wq;
/*
- * __wait_status - Wait up to 2ms for the status port to get a certain value
+ * __wait_status - Wait up to 32ms for the status port to get a certain value
* (masked with 0x0f), returning zero if the value is obtained. Callers must
* hold applesmc_lock.
*/
static int __wait_status(u8 val)
{
- unsigned int i;
+ int us;
val = val & APPLESMC_STATUS_MASK;
- for (i = 0; i < 200; i++) {
+ for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
+ udelay(us);
if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
if (debug)
printk(KERN_DEBUG
- "Waited %d us for status %x\n",
- i*10, val);
+ "Waited %d us for status %x\n",
+ 2 * us - APPLESMC_MIN_WAIT, val);
return 0;
}
- udelay(10);
}
printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
@@ -191,6 +203,25 @@ static int __wait_status(u8 val)
}
/*
+ * special treatment of command port - on newer macbooks, it seems necessary
+ * to resend the command byte before polling the status again. Callers must
+ * hold applesmc_lock.
+ */
+static int send_command(u8 cmd)
+{
+ int us;
+ for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
+ outb(cmd, APPLESMC_CMD_PORT);
+ udelay(us);
+ if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
+ return 0;
+ }
+ printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
+ cmd, inb(APPLESMC_CMD_PORT));
+ return -EIO;
+}
+
+/*
* applesmc_read_key - reads len bytes from a given key, and put them in buffer.
* Returns zero on success or a negative error on failure. Callers must
* hold applesmc_lock.
@@ -205,8 +236,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
return -EINVAL;
}
- outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_READ_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
@@ -249,8 +279,7 @@ static int applesmc_write_key(const char* key, u8* buffer, u8 len)
return -EINVAL;
}
- outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_WRITE_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
@@ -284,8 +313,7 @@ static int applesmc_get_key_at_index(int index, char* key)
readkey[2] = index >> 8;
readkey[3] = index;
- outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
@@ -315,8 +343,7 @@ static int applesmc_get_key_type(char* key, char* type)
{
int i;
- outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
@@ -325,7 +352,7 @@ static int applesmc_get_key_type(char* key, char* type)
return -EIO;
}
- outb(5, APPLESMC_DATA_PORT);
+ outb(6, APPLESMC_DATA_PORT);
for (i = 0; i < 6; i++) {
if (__wait_status(0x05))
@@ -527,17 +554,27 @@ out:
static ssize_t applesmc_light_show(struct device *dev,
struct device_attribute *attr, char *sysfsbuf)
{
+ static int data_length;
int ret;
u8 left = 0, right = 0;
- u8 buffer[6];
+ u8 buffer[10], query[6];
mutex_lock(&applesmc_lock);
- ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, 6);
+ if (!data_length) {
+ ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query);
+ if (ret)
+ goto out;
+ data_length = clamp_val(query[0], 0, 10);
+ printk(KERN_INFO "applesmc: light sensor data length set to "
+ "%d\n", data_length);
+ }
+
+ ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
left = buffer[2];
if (ret)
goto out;
- ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, 6);
+ ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
right = buffer[2];
out:
@@ -1233,39 +1270,57 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 0, .light = 0, .temperature_set = 5 },
/* MacBook3: accelerometer and temperature set 6 */
{ .accelerometer = 1, .light = 0, .temperature_set = 6 },
+/* MacBook Air: accelerometer, backlight and temperature set 7 */
+ { .accelerometer = 1, .light = 1, .temperature_set = 7 },
+/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */
+ { .accelerometer = 1, .light = 1, .temperature_set = 8 },
+/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
+ { .accelerometer = 1, .light = 1, .temperature_set = 9 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
* So we need to put "Apple MacBook Pro" before "Apple MacBook". */
static __initdata struct dmi_system_id applesmc_whitelist[] = {
+ { applesmc_dmi_match, "Apple MacBook Air", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
+ &applesmc_dmi_data[7]},
+ { applesmc_dmi_match, "Apple MacBook Pro 4", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") },
+ &applesmc_dmi_data[8]},
+ { applesmc_dmi_match, "Apple MacBook Pro 3", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") },
+ &applesmc_dmi_data[9]},
{ applesmc_dmi_match, "Apple MacBook Pro", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
- (void*)&applesmc_dmi_data[0]},
+ &applesmc_dmi_data[0]},
{ applesmc_dmi_match, "Apple MacBook (v2)", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
- (void*)&applesmc_dmi_data[1]},
+ &applesmc_dmi_data[1]},
{ applesmc_dmi_match, "Apple MacBook (v3)", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
- (void*)&applesmc_dmi_data[6]},
+ &applesmc_dmi_data[6]},
{ applesmc_dmi_match, "Apple MacBook", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
- (void*)&applesmc_dmi_data[2]},
+ &applesmc_dmi_data[2]},
{ applesmc_dmi_match, "Apple Macmini", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
- (void*)&applesmc_dmi_data[3]},
+ &applesmc_dmi_data[3]},
{ applesmc_dmi_match, "Apple MacPro2", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
- (void*)&applesmc_dmi_data[4]},
+ &applesmc_dmi_data[4]},
{ applesmc_dmi_match, "Apple iMac", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
- (void*)&applesmc_dmi_data[5]},
+ &applesmc_dmi_data[5]},
{ .ident = NULL }
};
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index c54eff92be4..bfc296145bb 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -180,6 +180,7 @@ static struct vrm_model vrm_models[] = {
{X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
{X86_VENDOR_AMD, 0xF, 0x3F, ANY, 24}, /* Athlon 64, Opteron */
{X86_VENDOR_AMD, 0xF, ANY, ANY, 25}, /* NPT family 0Fh */
+ {X86_VENDOR_AMD, 0x10, ANY, ANY, 25}, /* NPT family 10h */
{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */
{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 3edeebc0b83..96a70186672 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -12,9 +12,9 @@
* made by National Semiconductor. Both have an increased remote
* temperature measurement accuracy (1 degree), and the LM99
* additionally shifts remote temperatures (measured and limits) by 16
- * degrees, which allows for higher temperatures measurement. The
- * driver doesn't handle it since it can be done easily in user-space.
+ * degrees, which allows for higher temperatures measurement.
* Note that there is no way to differentiate between both chips.
+ * When device is auto-detected, the driver will assume an LM99.
*
* This driver also supports the LM86, another sensor chip made by
* National Semiconductor. It is exactly similar to the LM90 except it
@@ -169,8 +169,8 @@ static const struct i2c_device_id lm90_id[] = {
{ "adt7461", adt7461 },
{ "lm90", lm90 },
{ "lm86", lm86 },
- { "lm89", lm99 },
- { "lm99", lm99 }, /* Missing temperature offset */
+ { "lm89", lm86 },
+ { "lm99", lm99 },
{ "max6646", max6646 },
{ "max6647", max6646 },
{ "max6649", max6646 },
@@ -366,6 +366,10 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
else
temp = temp_from_s8(data->temp8[attr->index]);
+ /* +16 degrees offset for temp2 for the LM99 */
+ if (data->kind == lm99 && attr->index == 3)
+ temp += 16000;
+
return sprintf(buf, "%d\n", temp);
}
@@ -385,6 +389,10 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
long val = simple_strtol(buf, NULL, 10);
int nr = attr->index;
+ /* +16 degrees offset for temp2 for the LM99 */
+ if (data->kind == lm99 && attr->index == 3)
+ val -= 16000;
+
mutex_lock(&data->update_lock);
if (data->kind == adt7461)
data->temp8[nr] = temp_to_u8_adt7461(data, val);
@@ -411,6 +419,10 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
else
temp = temp_from_s16(data->temp11[attr->index]);
+ /* +16 degrees offset for temp2 for the LM99 */
+ if (data->kind == lm99 && attr->index <= 2)
+ temp += 16000;
+
return sprintf(buf, "%d\n", temp);
}
@@ -432,6 +444,10 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
long val = simple_strtol(buf, NULL, 10);
int nr = attr->index;
+ /* +16 degrees offset for temp2 for the LM99 */
+ if (data->kind == lm99 && attr->index <= 2)
+ val -= 16000;
+
mutex_lock(&data->update_lock);
if (data->kind == adt7461)
data->temp11[nr] = temp_to_u16_adt7461(data, val);
@@ -461,9 +477,15 @@ static ssize_t show_temphyst(struct device *dev, struct device_attribute *devatt
if (data->kind == adt7461)
temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
+ else if (data->kind == max6646)
+ temp = temp_from_u8(data->temp8[attr->index]);
else
temp = temp_from_s8(data->temp8[attr->index]);
+ /* +16 degrees offset for temp2 for the LM99 */
+ if (data->kind == lm99 && attr->index == 3)
+ temp += 16000;
+
return sprintf(buf, "%d\n", temp - temp_from_s8(data->temp_hyst));
}
@@ -473,12 +495,19 @@ static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
struct i2c_client *client = to_i2c_client(dev);
struct lm90_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10);
- long hyst;
+ int temp;
mutex_lock(&data->update_lock);
- hyst = temp_from_s8(data->temp8[2]) - val;
+ if (data->kind == adt7461)
+ temp = temp_from_u8_adt7461(data, data->temp8[2]);
+ else if (data->kind == max6646)
+ temp = temp_from_u8(data->temp8[2]);
+ else
+ temp = temp_from_s8(data->temp8[2]);
+
+ data->temp_hyst = hyst_to_reg(temp - val);
i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
- hyst_to_reg(hyst));
+ data->temp_hyst);
mutex_unlock(&data->update_lock);
return count;
}
@@ -682,6 +711,15 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
} else
if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
kind = lm99;
+ dev_info(&adapter->dev,
+ "Assuming LM99 chip at "
+ "0x%02x\n", address);
+ dev_info(&adapter->dev,
+ "If it is an LM89, pass "
+ "force_lm86=%d,0x%02x when "
+ "loading the lm90 driver\n",
+ i2c_adapter_id(adapter),
+ address);
} else
if (address == 0x4C
&& (chip_id & 0xF0) == 0x10) { /* LM86 */
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 9b462bb13fa..5fbfa34c110 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -75,7 +75,8 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
#define FSCM 0x09 /* Logical device: fans */
#define VLM 0x0d /* Logical device: voltages */
#define TMS 0x0e /* Logical device: temperatures */
-static const u8 logdev[3] = { FSCM, VLM, TMS };
+#define LDNI_MAX 3
+static const u8 logdev[LDNI_MAX] = { FSCM, VLM, TMS };
#define LD_FAN 0
#define LD_IN 1
@@ -489,11 +490,66 @@ static struct sensor_device_attribute in_max[] = {
SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
};
+/* (temp & vin) channel status register alarm bits (pdf sec.11.5.12) */
+#define CHAN_ALM_MIN 0x02 /* min limit crossed */
+#define CHAN_ALM_MAX 0x04 /* max limit exceeded */
+#define TEMP_ALM_CRIT 0x08 /* temp crit exceeded (temp only) */
+
+/* show_in_min/max_alarm() reads data from the per-channel status
+ register (sec 11.5.12), not the vin event status registers (sec
+ 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms) */
+
+static ssize_t show_in_min_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
+}
+static ssize_t show_in_max_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
+}
+
+static struct sensor_device_attribute in_min_alarm[] = {
+ SENSOR_ATTR(in0_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 0),
+ SENSOR_ATTR(in1_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 1),
+ SENSOR_ATTR(in2_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 2),
+ SENSOR_ATTR(in3_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 3),
+ SENSOR_ATTR(in4_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 4),
+ SENSOR_ATTR(in5_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 5),
+ SENSOR_ATTR(in6_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 6),
+ SENSOR_ATTR(in7_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 7),
+ SENSOR_ATTR(in8_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 8),
+ SENSOR_ATTR(in9_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 9),
+ SENSOR_ATTR(in10_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 10),
+};
+static struct sensor_device_attribute in_max_alarm[] = {
+ SENSOR_ATTR(in0_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 0),
+ SENSOR_ATTR(in1_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 1),
+ SENSOR_ATTR(in2_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 2),
+ SENSOR_ATTR(in3_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 3),
+ SENSOR_ATTR(in4_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 4),
+ SENSOR_ATTR(in5_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 5),
+ SENSOR_ATTR(in6_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 6),
+ SENSOR_ATTR(in7_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 7),
+ SENSOR_ATTR(in8_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 8),
+ SENSOR_ATTR(in9_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 9),
+ SENSOR_ATTR(in10_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 10),
+};
+
#define VIN_UNIT_ATTRS(X) \
&in_input[X].dev_attr.attr, \
&in_status[X].dev_attr.attr, \
&in_min[X].dev_attr.attr, \
- &in_max[X].dev_attr.attr
+ &in_max[X].dev_attr.attr, \
+ &in_min_alarm[X].dev_attr.attr, \
+ &in_max_alarm[X].dev_attr.attr
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -658,12 +714,68 @@ static struct sensor_device_attribute therm_crit[] = {
show_therm_crit, set_therm_crit, 2+11),
};
+/* show_therm_min/max_alarm() reads data from the per-channel voltage
+ status register (sec 11.5.12) */
+
+static ssize_t show_therm_min_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
+}
+static ssize_t show_therm_max_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
+}
+static ssize_t show_therm_crit_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->in_status[nr] & TEMP_ALM_CRIT));
+}
+
+static struct sensor_device_attribute therm_min_alarm[] = {
+ SENSOR_ATTR(temp4_min_alarm, S_IRUGO,
+ show_therm_min_alarm, NULL, 0+11),
+ SENSOR_ATTR(temp5_min_alarm, S_IRUGO,
+ show_therm_min_alarm, NULL, 1+11),
+ SENSOR_ATTR(temp6_min_alarm, S_IRUGO,
+ show_therm_min_alarm, NULL, 2+11),
+};
+static struct sensor_device_attribute therm_max_alarm[] = {
+ SENSOR_ATTR(temp4_max_alarm, S_IRUGO,
+ show_therm_max_alarm, NULL, 0+11),
+ SENSOR_ATTR(temp5_max_alarm, S_IRUGO,
+ show_therm_max_alarm, NULL, 1+11),
+ SENSOR_ATTR(temp6_max_alarm, S_IRUGO,
+ show_therm_max_alarm, NULL, 2+11),
+};
+static struct sensor_device_attribute therm_crit_alarm[] = {
+ SENSOR_ATTR(temp4_crit_alarm, S_IRUGO,
+ show_therm_crit_alarm, NULL, 0+11),
+ SENSOR_ATTR(temp5_crit_alarm, S_IRUGO,
+ show_therm_crit_alarm, NULL, 1+11),
+ SENSOR_ATTR(temp6_crit_alarm, S_IRUGO,
+ show_therm_crit_alarm, NULL, 2+11),
+};
+
#define THERM_UNIT_ATTRS(X) \
&therm_input[X].dev_attr.attr, \
&therm_status[X].dev_attr.attr, \
&therm_min[X].dev_attr.attr, \
&therm_max[X].dev_attr.attr, \
- &therm_crit[X].dev_attr.attr
+ &therm_crit[X].dev_attr.attr, \
+ &therm_min_alarm[X].dev_attr.attr, \
+ &therm_max_alarm[X].dev_attr.attr, \
+ &therm_crit_alarm[X].dev_attr.attr
static struct attribute * pc8736x_therm_attr_array[] = {
THERM_UNIT_ATTRS(0),
@@ -790,12 +902,76 @@ static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *att
}
static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
+/* show_temp_min/max_alarm() reads data from the per-channel status
+ register (sec 12.3.7), not the temp event status registers (sec
+ 12.3.2) that show_temp_alarm() reads (via data->temp_alarms) */
+
+static ssize_t show_temp_min_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN));
+}
+static ssize_t show_temp_max_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX));
+}
+static ssize_t show_temp_crit_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_ALM_CRIT));
+}
+
+static struct sensor_device_attribute temp_min_alarm[] = {
+ SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 0),
+ SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1),
+ SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2),
+};
+static struct sensor_device_attribute temp_max_alarm[] = {
+ SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0),
+ SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1),
+ SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2),
+};
+static struct sensor_device_attribute temp_crit_alarm[] = {
+ SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0),
+ SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1),
+ SENSOR_ATTR(temp3_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 2),
+};
+
+#define TEMP_FAULT 0x40 /* open diode */
+static ssize_t show_temp_fault(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct pc87360_data *data = pc87360_update_device(dev);
+ unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+ return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_FAULT));
+}
+static struct sensor_device_attribute temp_fault[] = {
+ SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0),
+ SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1),
+ SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2),
+};
+
#define TEMP_UNIT_ATTRS(X) \
&temp_input[X].dev_attr.attr, \
&temp_status[X].dev_attr.attr, \
&temp_min[X].dev_attr.attr, \
&temp_max[X].dev_attr.attr, \
- &temp_crit[X].dev_attr.attr
+ &temp_crit[X].dev_attr.attr, \
+ &temp_min_alarm[X].dev_attr.attr, \
+ &temp_max_alarm[X].dev_attr.attr, \
+ &temp_crit_alarm[X].dev_attr.attr, \
+ &temp_fault[X].dev_attr.attr
static struct attribute * pc8736x_temp_attr_array[] = {
TEMP_UNIT_ATTRS(0),
@@ -809,8 +985,8 @@ static const struct attribute_group pc8736x_temp_group = {
.attrs = pc8736x_temp_attr_array,
};
-static ssize_t show_name(struct device *dev, struct device_attribute
- *devattr, char *buf)
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
struct pc87360_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", data->name);
@@ -955,7 +1131,7 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data);
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < LDNI_MAX; i++) {
if (((data->address[i] = extra_isa[i]))
&& !request_region(extra_isa[i], PC87360_EXTENT,
pc87360_driver.driver.name)) {
@@ -1031,7 +1207,15 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
|| (err = device_create_file(dev,
&temp_crit[i].dev_attr))
|| (err = device_create_file(dev,
- &temp_status[i].dev_attr)))
+ &temp_status[i].dev_attr))
+ || (err = device_create_file(dev,
+ &temp_min_alarm[i].dev_attr))
+ || (err = device_create_file(dev,
+ &temp_max_alarm[i].dev_attr))
+ || (err = device_create_file(dev,
+ &temp_crit_alarm[i].dev_attr))
+ || (err = device_create_file(dev,
+ &temp_fault[i].dev_attr)))
goto ERROR3;
}
if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
@@ -1131,6 +1315,16 @@ static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
mutex_unlock(&(data->lock));
}
+/* (temp & vin) channel conversion status register flags (pdf sec.11.5.12) */
+#define CHAN_CNVRTD 0x80 /* new data ready */
+#define CHAN_ENA 0x01 /* enabled channel (temp or vin) */
+#define CHAN_ALM_ENA 0x10 /* propagate to alarms-reg ?? (chk val!) */
+#define CHAN_READY (CHAN_ENA|CHAN_CNVRTD) /* sample ready mask */
+
+#define TEMP_OTS_OE 0x20 /* OTS Output Enable */
+#define VIN_RW1C_MASK (CHAN_READY|CHAN_ALM_MAX|CHAN_ALM_MIN) /* 0x87 */
+#define TEMP_RW1C_MASK (VIN_RW1C_MASK|TEMP_ALM_CRIT|TEMP_FAULT) /* 0xCF */
+
static void pc87360_init_device(struct platform_device *pdev,
int use_thermistors)
{
@@ -1152,11 +1346,12 @@ static void pc87360_init_device(struct platform_device *pdev,
nr = data->innr < 11 ? data->innr : 11;
for (i = 0; i < nr; i++) {
+ reg = pc87360_read_value(data, LD_IN, i,
+ PC87365_REG_IN_STATUS);
+ dev_dbg(&pdev->dev, "bios in%d status:0x%02x\n", i, reg);
if (init >= init_in[i]) {
/* Forcibly enable voltage channel */
- reg = pc87360_read_value(data, LD_IN, i,
- PC87365_REG_IN_STATUS);
- if (!(reg & 0x01)) {
+ if (!(reg & CHAN_ENA)) {
dev_dbg(&pdev->dev, "Forcibly "
"enabling in%d\n", i);
pc87360_write_value(data, LD_IN, i,
@@ -1168,19 +1363,24 @@ static void pc87360_init_device(struct platform_device *pdev,
/* We can't blindly trust the Super-I/O space configuration bit,
most BIOS won't set it properly */
+ dev_dbg(&pdev->dev, "bios thermistors:%d\n", use_thermistors);
for (i = 11; i < data->innr; i++) {
reg = pc87360_read_value(data, LD_IN, i,
PC87365_REG_TEMP_STATUS);
- use_thermistors = use_thermistors || (reg & 0x01);
+ use_thermistors = use_thermistors || (reg & CHAN_ENA);
+ /* thermistors are temp[4-6], measured on vin[11-14] */
+ dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i-7, reg);
}
+ dev_dbg(&pdev->dev, "using thermistors:%d\n", use_thermistors);
i = use_thermistors ? 2 : 0;
for (; i < data->tempnr; i++) {
+ reg = pc87360_read_value(data, LD_TEMP, i,
+ PC87365_REG_TEMP_STATUS);
+ dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i+1, reg);
if (init >= init_temp[i]) {
/* Forcibly enable temperature channel */
- reg = pc87360_read_value(data, LD_TEMP, i,
- PC87365_REG_TEMP_STATUS);
- if (!(reg & 0x01)) {
+ if (!(reg & CHAN_ENA)) {
dev_dbg(&pdev->dev, "Forcibly "
"enabling temp%d\n", i+1);
pc87360_write_value(data, LD_TEMP, i,
@@ -1197,7 +1397,7 @@ static void pc87360_init_device(struct platform_device *pdev,
diodes */
reg = pc87360_read_value(data, LD_TEMP,
(i-11)/2, PC87365_REG_TEMP_STATUS);
- if (reg & 0x01) {
+ if (reg & CHAN_ENA) {
dev_dbg(&pdev->dev, "Skipping "
"temp%d, pin already in use "
"by temp%d\n", i-7, (i-11)/2);
@@ -1207,7 +1407,7 @@ static void pc87360_init_device(struct platform_device *pdev,
/* Forcibly enable thermistor channel */
reg = pc87360_read_value(data, LD_IN, i,
PC87365_REG_IN_STATUS);
- if (!(reg & 0x01)) {
+ if (!(reg & CHAN_ENA)) {
dev_dbg(&pdev->dev, "Forcibly "
"enabling temp%d\n", i-7);
pc87360_write_value(data, LD_IN, i,
@@ -1221,7 +1421,8 @@ static void pc87360_init_device(struct platform_device *pdev,
if (data->innr) {
reg = pc87360_read_value(data, LD_IN, NO_BANK,
PC87365_REG_IN_CONFIG);
- if (reg & 0x01) {
+ dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg);
+ if (reg & CHAN_ENA) {
dev_dbg(&pdev->dev, "Forcibly "
"enabling monitoring (VLM)\n");
pc87360_write_value(data, LD_IN, NO_BANK,
@@ -1233,7 +1434,8 @@ static void pc87360_init_device(struct platform_device *pdev,
if (data->tempnr) {
reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
PC87365_REG_TEMP_CONFIG);
- if (reg & 0x01) {
+ dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg);
+ if (reg & CHAN_ENA) {
dev_dbg(&pdev->dev, "Forcibly enabling "
"monitoring (TMS)\n");
pc87360_write_value(data, LD_TEMP, NO_BANK,
@@ -1336,11 +1538,11 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
pc87360_write_value(data, LD_IN, i,
PC87365_REG_IN_STATUS,
data->in_status[i]);
- if ((data->in_status[i] & 0x81) == 0x81) {
+ if ((data->in_status[i] & CHAN_READY) == CHAN_READY) {
data->in[i] = pc87360_read_value(data, LD_IN,
i, PC87365_REG_IN);
}
- if (data->in_status[i] & 0x01) {
+ if (data->in_status[i] & CHAN_ENA) {
data->in_min[i] = pc87360_read_value(data,
LD_IN, i,
PC87365_REG_IN_MIN);
@@ -1373,12 +1575,12 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
pc87360_write_value(data, LD_TEMP, i,
PC87365_REG_TEMP_STATUS,
data->temp_status[i]);
- if ((data->temp_status[i] & 0x81) == 0x81) {
+ if ((data->temp_status[i] & CHAN_READY) == CHAN_READY) {
data->temp[i] = pc87360_read_value(data,
LD_TEMP, i,
PC87365_REG_TEMP);
}
- if (data->temp_status[i] & 0x01) {
+ if (data->temp_status[i] & CHAN_ENA) {
data->temp_min[i] = pc87360_read_value(data,
LD_TEMP, i,
PC87365_REG_TEMP_MIN);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index d4d1b859d4f..fc12bd412e3 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1968,7 +1968,7 @@ exit:
return res;
}
-static void __exit
+static void
w83781d_isa_unregister(void)
{
if (pdev) {
@@ -2017,7 +2017,7 @@ w83781d_isa_register(void)
return 0;
}
-static void __exit
+static void
w83781d_isa_unregister(void)
{
}
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 1e328d19cd6..3e01992230b 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -135,7 +135,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
*status = get_pcf(adap, 1);
#ifndef STUB_I2C
while (timeout-- && (*status & I2C_PCF_PIN)) {
- adap->waitforpin();
+ adap->waitforpin(adap->data);
*status = get_pcf(adap, 1);
}
if (*status & I2C_PCF_LAB) {
@@ -208,7 +208,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
return -ENXIO;
}
- printk(KERN_DEBUG "i2c-algo-pcf.o: deteted and initialized PCF8584.\n");
+ printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n");
return 0;
}
@@ -331,13 +331,16 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
int i;
int ret=0, timeout, status;
+ if (adap->xfer_begin)
+ adap->xfer_begin(adap->data);
/* Check for bus busy */
timeout = wait_for_bb(adap);
if (timeout) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
"Timeout waiting for BB in pcf_xfer\n");)
- return -EIO;
+ i = -EIO;
+ goto out;
}
for (i = 0;ret >= 0 && i < num; i++) {
@@ -359,12 +362,14 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
if (timeout) {
if (timeout == -EINTR) {
/* arbitration lost */
- return (-EINTR);
+ i = -EINTR;
+ goto out;
}
i2c_stop(adap);
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
"for PIN(1) in pcf_xfer\n");)
- return (-EREMOTEIO);
+ i = -EREMOTEIO;
+ goto out;
}
#ifndef STUB_I2C
@@ -372,7 +377,8 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
if (status & I2C_PCF_LRB) {
i2c_stop(adap);
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
- return (-EREMOTEIO);
+ i = -EREMOTEIO;
+ goto out;
}
#endif
@@ -404,6 +410,9 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
}
}
+out:
+ if (adap->xfer_end)
+ adap->xfer_end(adap->data);
return (i);
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index acadbc51fc0..7f95905bbb9 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -97,6 +97,7 @@ config I2C_I801
ICH9
Tolapai
ICH10
+ PCH
This driver can also be built as a module. If so, the module
will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 1ea39254dac..424dad6f18d 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -332,10 +332,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
int error;
u8 temp;
- /* driver_data might come from user-space, so check it */
- if (id->driver_data >= ARRAY_SIZE(chipname))
- return -EINVAL;
-
if (amd756_ioport) {
dev_err(&pdev->dev, "Only one device supported "
"(you have a strange motherboard, btw)\n");
@@ -412,7 +408,6 @@ static struct pci_driver amd756_driver = {
.id_table = amd756_ids,
.probe = amd756_probe,
.remove = __devexit_p(amd756_remove),
- .dynids.use_driver_data = 1,
};
static int __init amd756_init(void)
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 8164de1f4d7..228f7572306 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -423,7 +423,6 @@ static const struct i2c_adapter cpm_ops = {
.owner = THIS_MODULE,
.name = "i2c-cpm",
.algo = &cpm_i2c_algo,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
};
static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 7f38c01fb3a..0ed3ccb81b6 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -104,7 +104,8 @@ static int pcf_isa_getclock(void *data)
return (clock);
}
-static void pcf_isa_waitforpin(void) {
+static void pcf_isa_waitforpin(void *data)
+{
DEFINE_WAIT(wait);
int timeout = 2;
unsigned long flags;
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 1098f21ace1..648aa7baff8 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -123,7 +123,7 @@ static int __devinit hydra_probe(struct pci_dev *dev,
hydra_adap.name))
return -EBUSY;
- hydra_bit_data.data = ioremap(base, pci_resource_len(dev, 0));
+ hydra_bit_data.data = pci_ioremap_bar(dev, 0);
if (hydra_bit_data.data == NULL) {
release_mem_region(base+offsetof(struct Hydra, CachePD), 4);
return -ENODEV;
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index dc7ea32b69a..5123eb69a97 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -41,6 +41,7 @@
Tolapai 0x5032 32 hard yes yes yes
ICH10 0x3a30 32 hard yes yes yes
ICH10 0x3a60 32 hard yes yes yes
+ PCH 0x3b30 32 hard yes yes yes
Features supported by this driver:
Software PEC no
@@ -576,6 +577,7 @@ static struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) },
{ 0, }
};
@@ -599,6 +601,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
case PCI_DEVICE_ID_INTEL_ICH10_4:
case PCI_DEVICE_ID_INTEL_ICH10_5:
+ case PCI_DEVICE_ID_INTEL_PCH_SMBUS:
i801_features |= FEATURE_I2C_BLOCK_READ;
/* fall through */
case PCI_DEVICE_ID_INTEL_82801DB_3:
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 73dc52e114e..9f194d9efd9 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -332,10 +332,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
unsigned char temp;
int error = -ENODEV;
- /* driver_data might come from user-space, so check it */
- if (id->driver_data & 1 || id->driver_data > 0xff)
- return -EINVAL;
-
/* Determine the address of the SMBus areas */
if (force_addr) {
vt596_smba = force_addr & 0xfff0;
@@ -483,7 +479,6 @@ static struct pci_driver vt596_driver = {
.name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
- .dynids.use_driver_data = 1,
};
static int __init i2c_vt596_init(void)
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 17356827b93..4c35702830c 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -1,6 +1,8 @@
#
# Miscellaneous I2C chip drivers configuration
#
+# *** DEPRECATED! Do not add new entries! See Makefile ***
+#
menu "Miscellaneous I2C Chip support"
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index ca520fa143d..23d2a31b0a6 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -1,7 +1,8 @@
#
# Makefile for miscellaneous I2C chip drivers.
#
-# Think twice before you add a new driver to this directory.
+# Do not add new drivers to this directory! It is DEPRECATED.
+#
# Device drivers are better grouped according to the functionality they
# implement rather than to the bus they are connected to. In particular:
# * Hardware monitoring chip drivers go to drivers/hwmon
diff --git a/drivers/i2c/chips/at24.c b/drivers/i2c/chips/at24.c
index 2a4acb26956..d4775528abc 100644
--- a/drivers/i2c/chips/at24.c
+++ b/drivers/i2c/chips/at24.c
@@ -460,7 +460,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
*/
at24->bin.attr.name = "eeprom";
at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
- at24->bin.attr.owner = THIS_MODULE;
at24->bin.read = at24_bin_read;
at24->bin.size = chip.byte_len;
diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c
index 23be4d42cb0..f3ee4a1abb7 100644
--- a/drivers/i2c/chips/ds1682.c
+++ b/drivers/i2c/chips/ds1682.c
@@ -190,7 +190,6 @@ static struct bin_attribute ds1682_eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = DS1682_EEPROM_SIZE,
.read = ds1682_eeprom_read,
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
index 176126d3a01..4b364bae6b3 100644
--- a/drivers/i2c/chips/menelaus.c
+++ b/drivers/i2c/chips/menelaus.c
@@ -832,52 +832,52 @@ static irqreturn_t menelaus_irq(int irq, void *_menelaus)
static void menelaus_to_time(char *regs, struct rtc_time *t)
{
- t->tm_sec = BCD2BIN(regs[0]);
- t->tm_min = BCD2BIN(regs[1]);
+ t->tm_sec = bcd2bin(regs[0]);
+ t->tm_min = bcd2bin(regs[1]);
if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
- t->tm_hour = BCD2BIN(regs[2] & 0x1f) - 1;
+ t->tm_hour = bcd2bin(regs[2] & 0x1f) - 1;
if (regs[2] & RTC_HR_PM)
t->tm_hour += 12;
} else
- t->tm_hour = BCD2BIN(regs[2] & 0x3f);
- t->tm_mday = BCD2BIN(regs[3]);
- t->tm_mon = BCD2BIN(regs[4]) - 1;
- t->tm_year = BCD2BIN(regs[5]) + 100;
+ t->tm_hour = bcd2bin(regs[2] & 0x3f);
+ t->tm_mday = bcd2bin(regs[3]);
+ t->tm_mon = bcd2bin(regs[4]) - 1;
+ t->tm_year = bcd2bin(regs[5]) + 100;
}
static int time_to_menelaus(struct rtc_time *t, int regnum)
{
int hour, status;
- status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_sec));
+ status = menelaus_write_reg(regnum++, bin2bcd(t->tm_sec));
if (status < 0)
goto fail;
- status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_min));
+ status = menelaus_write_reg(regnum++, bin2bcd(t->tm_min));
if (status < 0)
goto fail;
if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
hour = t->tm_hour + 1;
if (hour > 12)
- hour = RTC_HR_PM | BIN2BCD(hour - 12);
+ hour = RTC_HR_PM | bin2bcd(hour - 12);
else
- hour = BIN2BCD(hour);
+ hour = bin2bcd(hour);
} else
- hour = BIN2BCD(t->tm_hour);
+ hour = bin2bcd(t->tm_hour);
status = menelaus_write_reg(regnum++, hour);
if (status < 0)
goto fail;
- status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mday));
+ status = menelaus_write_reg(regnum++, bin2bcd(t->tm_mday));
if (status < 0)
goto fail;
- status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mon + 1));
+ status = menelaus_write_reg(regnum++, bin2bcd(t->tm_mon + 1));
if (status < 0)
goto fail;
- status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_year - 100));
+ status = menelaus_write_reg(regnum++, bin2bcd(t->tm_year - 100));
if (status < 0)
goto fail;
@@ -914,7 +914,7 @@ static int menelaus_read_time(struct device *dev, struct rtc_time *t)
}
menelaus_to_time(regs, t);
- t->tm_wday = BCD2BIN(regs[6]);
+ t->tm_wday = bcd2bin(regs[6]);
return 0;
}
@@ -927,7 +927,7 @@ static int menelaus_set_time(struct device *dev, struct rtc_time *t)
status = time_to_menelaus(t, MENELAUS_RTC_SEC);
if (status < 0)
return status;
- status = menelaus_write_reg(MENELAUS_RTC_WKDAY, BIN2BCD(t->tm_wday));
+ status = menelaus_write_reg(MENELAUS_RTC_WKDAY, bin2bcd(t->tm_wday));
if (status < 0) {
dev_err(&the_menelaus->client->dev, "rtc write reg %02x "
"err %d\n", MENELAUS_RTC_WKDAY, status);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 42e852d79ff..5a485c22660 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -266,6 +266,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->dev.platform_data = info->platform_data;
+ if (info->archdata)
+ client->dev.archdata = *info->archdata;
+
client->flags = info->flags;
client->addr = info->addr;
client->irq = info->irq;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 74a369a6116..6d7401772a8 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -84,21 +84,40 @@ config BLK_DEV_IDE_SATA
If unsure, say N.
-config BLK_DEV_IDEDISK
- tristate "Include IDE/ATA-2 DISK support"
- ---help---
- This will include enhanced support for MFM/RLL/IDE hard disks. If
- you have a MFM/RLL/IDE disk, and there is no special reason to use
- the old hard disk driver instead, say Y. If you have an SCSI-only
- system, you can say N here.
+config IDE_GD
+ tristate "generic ATA/ATAPI disk support"
+ default y
+ help
+ Support for ATA/ATAPI disks (including ATAPI floppy drives).
- To compile this driver as a module, choose M here: the
- module will be called ide-disk.
- Do not compile this driver as a module if your root file system
- (the one containing the directory /) is located on the IDE disk.
+ To compile this driver as a module, choose M here.
+ The module will be called ide-gd_mod.
+
+ If unsure, say Y.
+
+config IDE_GD_ATA
+ bool "ATA disk support"
+ depends on IDE_GD
+ default y
+ help
+ This will include support for ATA hard disks.
If unsure, say Y.
+config IDE_GD_ATAPI
+ bool "ATAPI floppy support"
+ depends on IDE_GD
+ select IDE_ATAPI
+ help
+ This will include support for ATAPI floppy drives
+ (i.e. Iomega ZIP or MKE LS-120).
+
+ For information about jumper settings and the question
+ of when a ZIP drive uses a partition table, see
+ <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>.
+
+ If unsure, say N.
+
config BLK_DEV_IDECS
tristate "PCMCIA IDE support"
depends on PCMCIA
@@ -163,29 +182,6 @@ config BLK_DEV_IDETAPE
To compile this driver as a module, choose M here: the
module will be called ide-tape.
-config BLK_DEV_IDEFLOPPY
- tristate "Include IDE/ATAPI FLOPPY support"
- select IDE_ATAPI
- ---help---
- If you have an IDE floppy drive which uses the ATAPI protocol,
- answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy
- drives, similar to the SCSI protocol.
-
- The LS-120 and the IDE/ATAPI Iomega ZIP drive are also supported by
- this driver. For information about jumper settings and the question
- of when a ZIP drive uses a partition table, see
- <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>.
- (ATAPI PD-CD/CDR drives are not supported by this driver; support
- for PD-CD/CDR drives is available if you answer Y to
- "SCSI emulation support", below).
-
- If you say Y here, the FLOPPY drive will be identified along with
- other IDE devices, as "hdb" or "hdc", or something similar (check
- the boot messages with dmesg).
-
- To compile this driver as a module, choose M here: the
- module will be called ide-floppy.
-
config BLK_DEV_IDESCSI
tristate "SCSI emulation support (DEPRECATED)"
depends on SCSI
@@ -332,7 +328,7 @@ config IDEPCI_PCIBUS_ORDER
# TODO: split it on per host driver config options (or module parameters)
config BLK_DEV_OFFBOARD
bool "Boot off-board chipsets first support (DEPRECATED)"
- depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT34X || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001)
+ depends on BLK_DEV_IDEPCI && (BLK_DEV_AEC62XX || BLK_DEV_GENERIC || BLK_DEV_HPT366 || BLK_DEV_PDC202XX_NEW || BLK_DEV_PDC202XX_OLD || BLK_DEV_TC86C001)
help
Normally, IDE controllers built into the motherboard (on-board
controllers) are assigned to ide0 and ide1 while those on add-in PCI
@@ -482,28 +478,6 @@ config BLK_DEV_CS5535
It is safe to say Y to this question.
-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
- interrupt. The HPT343 chipset in its current form is a non-bootable
- controller; the HPT345/HPT363 chipset is a bootable (needs BIOS FIX)
- PCI UDMA controllers. This driver requires dynamic tuning of the
- chipset during the ide-probe at boot time. It is reported to support
- DVD II drives, by the manufacturer.
-
-config HPT34X_AUTODMA
- bool "HPT34X AUTODMA support (EXPERIMENTAL)"
- depends on BLK_DEV_HPT34X && EXPERIMENTAL
- help
- This is a dangerous thing to attempt currently! Please read the
- comments at the top of <file:drivers/ide/pci/hpt34x.c>. If you say Y
- here, then say Y to "Use DMA by default when available" as well.
-
- If unsure, say N.
-
config BLK_DEV_HPT366
tristate "HPT36X/37X chipset support"
select BLK_DEV_IDEDMA_PCI
@@ -746,6 +720,16 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
default "128"
depends on BLK_DEV_IDE_AU1XXX
+config BLK_DEV_IDE_TX4938
+ tristate "TX4938 internal IDE support"
+ depends on SOC_TX4938
+ select IDE_TIMINGS
+
+config BLK_DEV_IDE_TX4939
+ tristate "TX4939 internal IDE support"
+ depends on SOC_TX4939
+ select BLK_DEV_IDEDMA_SFF
+
config IDE_ARM
tristate "ARM IDE support"
depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index ceaf779054e..7818d402b18 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -18,47 +18,98 @@ ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
obj-$(CONFIG_IDE) += ide-core.o
-ifeq ($(CONFIG_IDE_ARM), y)
- ide-arm-core-y += arm/ide_arm.o
- obj-y += ide-arm-core.o
-endif
+obj-$(CONFIG_IDE_ARM) += ide_arm.o
+
+obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
+obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
+obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
+obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
+obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
+obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o
+
+obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o
+obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o
+obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o
+obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o
+obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o
+
+obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o
+obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o
+obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o
+obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o
+obj-$(CONFIG_BLK_DEV_CELLEB) += scc_pata.o
+obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
+obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
+obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
+obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o
+obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o
+obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o
+obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o
+obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
+obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o
+obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o
+obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o
+obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
+obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
+obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o
+obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o
+obj-$(CONFIG_BLK_DEV_PIIX) += piix.o
+obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
+obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o
+obj-$(CONFIG_BLK_DEV_SGIIOC4) += sgiioc4.o
+obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
+obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
+obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
+obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o
+obj-$(CONFIG_BLK_DEV_TC86C001) += tc86c001.o
+obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o
+obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
+obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
-obj-$(CONFIG_IDE) += legacy/ pci/
+# Must appear at the end of the block
+obj-$(CONFIG_BLK_DEV_GENERIC) += ide-pci-generic.o
obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o
-ifeq ($(CONFIG_BLK_DEV_CMD640), y)
- cmd640-core-y += pci/cmd640.o
- obj-y += cmd640-core.o
-endif
+obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o
+
+obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
+
+obj-$(CONFIG_IDE_H8300) += ide-h8300.o
-obj-$(CONFIG_IDE) += ppc/
-obj-$(CONFIG_IDE_H8300) += h8300/
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
-ide-disk_mod-y += ide-disk.o ide-disk_ioctl.o
+ide-gd_mod-y += ide-gd.o
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
-ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o
+ifeq ($(CONFIG_IDE_GD_ATA), y)
+ ide-gd_mod-y += ide-disk.o ide-disk_ioctl.o
+ifeq ($(CONFIG_IDE_PROC_FS), y)
+ ide-gd_mod-y += ide-disk_proc.o
+endif
+endif
+
+ifeq ($(CONFIG_IDE_GD_ATAPI), y)
+ ide-gd_mod-y += ide-floppy.o ide-floppy_ioctl.o
ifeq ($(CONFIG_IDE_PROC_FS), y)
- ide-disk_mod-y += ide-disk_proc.o
- ide-floppy_mod-y += ide-floppy_proc.o
+ ide-gd_mod-y += ide-floppy_proc.o
+endif
endif
-obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk_mod.o
+obj-$(CONFIG_IDE_GD) += ide-gd_mod.o
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
-obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
-ifeq ($(CONFIG_BLK_DEV_IDECS), y)
- ide-cs-core-y += legacy/ide-cs.o
- obj-y += ide-cs-core.o
-endif
+obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
-ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
- ide-platform-core-y += legacy/ide_platform.o
- obj-y += ide-platform-core.o
-endif
+obj-$(CONFIG_BLK_DEV_PLATFORM) += ide_platform.o
+
+obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
+obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o
+
+obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
-obj-$(CONFIG_IDE) += arm/ mips/
+obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o
+obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/aec62xx.c
index 4142c698e0d..4142c698e0d 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/aec62xx.c
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/ali14xx.c
index 90da1f953ed..90da1f953ed 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/ali14xx.c
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/alim15x3.c
index daf9dce39e5..daf9dce39e5 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/alim15x3.c
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/amd74xx.c
index 81ec73134ed..81ec73134ed 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/amd74xx.c
diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
deleted file mode 100644
index 5bc26053afa..00000000000
--- a/drivers/ide/arm/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-
-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
-obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o
-
-ifeq ($(CONFIG_IDE_ARM), m)
- obj-m += ide_arm.o
-endif
-
-EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/atiixp.c
index b2735d28f5c..b2735d28f5c 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/atiixp.c
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 0ec8fd1e4dc..0ec8fd1e4dc 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/buddha.c
index c5a3c9ef6a5..c5a3c9ef6a5 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/buddha.c
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/cmd640.c
index e4306647d00..e4306647d00 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/cmd640.c
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/cmd64x.c
index 935385c77e0..935385c77e0 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/cmd64x.c
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/cs5520.c
index 5efb467f8fa..5efb467f8fa 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/cs5520.c
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/cs5530.c
index 53f079cc00a..53f079cc00a 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/cs5530.c
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/cs5535.c
index 983d957a018..983d957a018 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/cs5535.c
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/cy82c693.c
index 5297f07d293..5297f07d293 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/cy82c693.c
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/delkin_cb.c
index 8689a706f53..8f1b2d9f051 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/delkin_cb.c
@@ -46,10 +46,27 @@ static const struct ide_port_ops delkin_cb_port_ops = {
.quirkproc = ide_undecoded_slave,
};
+static unsigned int delkin_cb_init_chipset(struct pci_dev *dev)
+{
+ unsigned long base = pci_resource_start(dev, 0);
+ int i;
+
+ outb(0x02, base + 0x1e); /* set nIEN to block interrupts */
+ inb(base + 0x17); /* read status to clear interrupts */
+
+ for (i = 0; i < sizeof(setup); ++i) {
+ if (setup[i])
+ outb(setup[i], base + i);
+ }
+
+ return 0;
+}
+
static const struct ide_port_info delkin_cb_port_info = {
.port_ops = &delkin_cb_port_ops,
.host_flags = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS |
IDE_HFLAG_NO_DMA,
+ .init_chipset = delkin_cb_init_chipset,
};
static int __devinit
@@ -57,7 +74,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
struct ide_host *host;
unsigned long base;
- int i, rc;
+ int rc;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
rc = pci_enable_device(dev);
@@ -72,12 +89,8 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
return rc;
}
base = pci_resource_start(dev, 0);
- outb(0x02, base + 0x1e); /* set nIEN to block interrupts */
- inb(base + 0x17); /* read status to clear interrupts */
- for (i = 0; i < sizeof(setup); ++i) {
- if (setup[i])
- outb(setup[i], base + i);
- }
+
+ delkin_cb_init_chipset(dev);
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
@@ -110,6 +123,40 @@ delkin_cb_remove (struct pci_dev *dev)
pci_disable_device(dev);
}
+#ifdef CONFIG_PM
+static int delkin_cb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ return 0;
+}
+
+static int delkin_cb_resume(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ int rc;
+
+ pci_set_power_state(dev, PCI_D0);
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ pci_restore_state(dev);
+ pci_set_master(dev);
+
+ if (host->init_chipset)
+ host->init_chipset(dev);
+
+ return 0;
+}
+#else
+#define delkin_cb_suspend NULL
+#define delkin_cb_resume NULL
+#endif
+
static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -122,6 +169,8 @@ static struct pci_driver delkin_cb_pci_driver = {
.id_table = delkin_cb_pci_tbl,
.probe = delkin_cb_probe,
.remove = delkin_cb_remove,
+ .suspend = delkin_cb_suspend,
+ .resume = delkin_cb_resume,
};
static int __init delkin_cb_init(void)
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/dtc2278.c
index 689b2e49341..689b2e49341 100644
--- a/drivers/ide/legacy/dtc2278.c
+++ b/drivers/ide/dtc2278.c
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/falconide.c
index 39d500d84b0..39d500d84b0 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/falconide.c
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/gayle.c
index 69150688656..69150688656 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/gayle.c
diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile
deleted file mode 100644
index 5eba16f423f..00000000000
--- a/drivers/ide/h8300/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-
-obj-$(CONFIG_IDE_H8300) += ide-h8300.o
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/hpt366.c
index 9cf171cb937..a7909e9c720 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -3,7 +3,7 @@
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
* Portions Copyright (C) 2007 Bartlomiej Zolnierkiewicz
- * Portions Copyright (C) 2005-2007 MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2008 MontaVista Software, Inc.
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
* Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
@@ -748,26 +748,24 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
- if (drive->quirk_list) {
- if (info->chip_type >= HPT370) {
- u8 scr1 = 0;
-
- pci_read_config_byte(dev, 0x5a, &scr1);
- if (((scr1 & 0x10) >> 4) != mask) {
- if (mask)
- scr1 |= 0x10;
- else
- scr1 &= ~0x10;
- pci_write_config_byte(dev, 0x5a, scr1);
- }
- } else {
+ if (drive->quirk_list == 0)
+ return;
+
+ if (info->chip_type >= HPT370) {
+ u8 scr1 = 0;
+
+ pci_read_config_byte(dev, 0x5a, &scr1);
+ if (((scr1 & 0x10) >> 4) != mask) {
if (mask)
- disable_irq(hwif->irq);
+ scr1 |= 0x10;
else
- enable_irq (hwif->irq);
+ scr1 &= ~0x10;
+ pci_write_config_byte(dev, 0x5a, scr1);
}
- } else
- outb(ATA_DEVCTL_OBS | (mask ? 2 : 0), hwif->io_ports.ctl_addr);
+ } else if (mask)
+ disable_irq(hwif->irq);
+ else
+ enable_irq(hwif->irq);
}
/*
@@ -1289,7 +1287,6 @@ static u8 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 = hpt3xx_get_info(hwif->dev);
int serialize = HPT_SERIALIZE_IO;
u8 chip_type = info->chip_type;
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/ht6560b.c
index c7e5c2246b7..c7e5c2246b7 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/ht6560b.c
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/icside.c
index 76bdc9a27f6..2d848010499 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/icside.c
@@ -690,9 +690,9 @@ static int __init icside_init(void)
return ecard_register_driver(&icside_driver);
}
-static void __exit icside_exit(void);
+static void __exit icside_exit(void)
{
- ecard_unregister_driver(&icside_driver);
+ ecard_remove_driver(&icside_driver);
}
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/ide-4drives.c
index 9e85b1ec960..9e85b1ec960 100644
--- a/drivers/ide/legacy/ide-4drives.c
+++ b/drivers/ide/ide-4drives.c
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 2e305714c20..4e58b9e7a58 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -191,7 +191,7 @@ int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
{
struct ide_atapi_pc pc;
- if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK)
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
return 0;
ide_init_pc(&pc);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 3308b1cd3a3..48b5eda3ab4 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -99,7 +99,7 @@ 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)
{
- drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+ drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
@@ -340,8 +340,8 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
}
ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
- "rq->cmd_type: 0x%x, err: 0x%x\n", __func__, stat,
- good_stat, rq->cmd_type, err);
+ "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x, err: 0x%x\n",
+ __func__, stat, good_stat, rq->cmd[0], rq->cmd_type, err);
if (blk_sense_request(rq)) {
/*
@@ -843,13 +843,10 @@ static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
rq->q->prep_rq_fn(rq->q, rq);
}
-/*
- * All other packet commands.
- */
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
{
-
- ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, rq->cmd[0]: 0x%x\n",
+ __func__, rq->cmd[0]);
/*
* Some of the trailing request sense fields are optional,
@@ -876,7 +873,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
if (!sense)
sense = &local_sense;
- ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
+ ide_debug_log(IDE_DBG_PC, "Call %s, cmd[0]: 0x%x, write: 0x%x, "
"timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
timeout, cmd_flags);
@@ -1177,8 +1174,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
unsigned short sectors_per_frame =
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
- ide_debug_log(IDE_DBG_RQ, "Call %s, write: 0x%x, secs_per_frame: %u\n",
- __func__, write, sectors_per_frame);
+ ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
+ "secs_per_frame: %u\n",
+ __func__, rq->cmd[0], write, sectors_per_frame);
if (write) {
/* disk has become write protected */
@@ -1221,7 +1219,8 @@ static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
- ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd_type: 0x%x\n", __func__,
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, "
+ "rq->cmd_type: 0x%x\n", __func__, rq->cmd[0],
rq->cmd_type);
if (blk_pc_request(rq))
@@ -1257,9 +1256,6 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
}
}
-/*
- * cdrom driver request routine.
- */
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
sector_t block)
{
@@ -1267,8 +1263,10 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
ide_handler_t *fn;
int xferlen;
- ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd_type: 0x%x, block: %llu\n",
- __func__, rq->cmd_type, (unsigned long long)block);
+ ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, "
+ "rq->cmd_type: 0x%x, block: %llu\n",
+ __func__, rq->cmd[0], rq->cmd_type,
+ (unsigned long long)block);
if (blk_fs_request(rq)) {
if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
@@ -1412,6 +1410,10 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
*capacity = 1 + be32_to_cpu(capbuf.lba);
*sectors_per_frame = blocklen >> SECTOR_BITS;
+
+ ide_debug_log(IDE_DBG_PROBE, "%s: cap: %lu, sectors_per_frame: %lu\n",
+ __func__, *capacity, *sectors_per_frame);
+
return 0;
}
@@ -1643,6 +1645,9 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
}
+ ide_debug_log(IDE_DBG_PROBE, "%s: curspeed: %u, maxspeed: %u\n",
+ __func__, curspeed, maxspeed);
+
cd->current_speed = (curspeed + (176/2)) / 176;
cd->max_speed = (maxspeed + (176/2)) / 176;
}
@@ -1732,7 +1737,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return 0;
if ((buf[8 + 6] & 0x01) == 0)
- drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
if (buf[8 + 6] & 0x08)
drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
if (buf[8 + 3] & 0x01)
@@ -1777,7 +1782,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
printk(KERN_CONT " DVD%s%s",
(cdi->mask & CDC_DVD_R) ? "" : "-R",
- (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
+ (cdi->mask & CDC_DVD_RAM) ? "" : "/RAM");
if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
printk(KERN_CONT " CD%s%s",
@@ -1908,6 +1913,16 @@ static const struct ide_proc_devset idecd_settings[] = {
IDE_PROC_DEVSET(dsc_overlap, 0, 1),
{ 0 },
};
+
+static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
+{
+ return idecd_proc;
+}
+
+static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive)
+{
+ return idecd_settings;
+}
#endif
static const struct cd_list_entry ide_cd_quirks_list[] = {
@@ -1951,6 +1966,7 @@ static const struct cd_list_entry ide_cd_quirks_list[] = {
{ "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE },
+ { "TEAC CD-ROM CD-224E", NULL, IDE_AFLAG_NO_AUTOCLOSE },
{ NULL, NULL, 0 }
};
@@ -1986,8 +2002,8 @@ static int ide_cdrom_setup(ide_drive_t *drive)
if (!drive->queue->unplug_delay)
drive->queue->unplug_delay = 1;
- drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
- ide_cd_flags(id);
+ drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
+ drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id);
if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
fw_rev[4] == '1' && fw_rev[6] <= '2')
@@ -2069,22 +2085,20 @@ static ide_driver_t ide_cdrom_driver = {
.end_request = ide_end_request,
.error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idecd_proc,
- .settings = idecd_settings,
+ .proc_entries = ide_cd_proc_entries,
+ .proc_devsets = ide_cd_proc_devsets,
#endif
};
-static int idecd_open(struct inode *inode, struct file *file)
+static int idecd_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct cdrom_info *info;
+ struct cdrom_info *info = ide_cd_get(bdev->bd_disk);
int rc = -ENOMEM;
- info = ide_cd_get(disk);
if (!info)
return -ENXIO;
- rc = cdrom_open(&info->devinfo, inode, file);
+ rc = cdrom_open(&info->devinfo, bdev, mode);
if (rc < 0)
ide_cd_put(info);
@@ -2092,12 +2106,11 @@ static int idecd_open(struct inode *inode, struct file *file)
return rc;
}
-static int idecd_release(struct inode *inode, struct file *file)
+static int idecd_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
- cdrom_release(&info->devinfo, file);
+ cdrom_release(&info->devinfo, mode);
ide_cd_put(info);
@@ -2143,10 +2156,9 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
return 0;
}
-static int idecd_ioctl(struct inode *inode, struct file *file,
+static int idecd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
int err;
@@ -2159,9 +2171,9 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
break;
}
- err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
+ err = generic_ide_ioctl(info->drive, bdev, cmd, arg);
if (err == -EINVAL)
- err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
+ err = cdrom_ioctl(&info->devinfo, bdev, mode, cmd, arg);
return err;
}
@@ -2186,7 +2198,7 @@ static struct block_device_operations idecd_ops = {
.owner = THIS_MODULE,
.open = idecd_open,
.release = idecd_release,
- .ioctl = idecd_ioctl,
+ .locked_ioctl = idecd_ioctl,
.media_changed = idecd_media_changed,
.revalidate_disk = idecd_revalidate_disk
};
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 74231b41f61..df3df0041eb 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -86,8 +86,8 @@ int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
if (slot_nr == CDSL_CURRENT) {
(void) cdrom_check_status(drive, NULL);
- retval = (drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED) ? 1 : 0;
- drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
+ retval = (drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED) ? 1 : 0;
+ drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
return retval;
} else {
return -EINVAL;
@@ -136,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 (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK) {
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) {
stat = 0;
} else {
unsigned char cmd[BLK_MAX_CDB];
@@ -157,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);
- drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
stat = 0;
}
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/ide-cs.c
index cb199c815b5..cb199c815b5 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/ide-cs.c
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 3853bde8eed..e5adebe8ac2 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -14,9 +14,6 @@
* This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
*/
-#define IDEDISK_VERSION "1.18"
-
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
@@ -39,46 +36,8 @@
#include <asm/io.h>
#include <asm/div64.h>
-#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
-#define IDE_DISK_MINORS (1 << PARTN_BITS)
-#else
-#define IDE_DISK_MINORS 0
-#endif
-
#include "ide-disk.h"
-static DEFINE_MUTEX(idedisk_ref_mutex);
-
-#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
-
-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 (ide_device_get(idkp->drive))
- idkp = NULL;
- else
- kref_get(&idkp->kref);
- }
- mutex_unlock(&idedisk_ref_mutex);
- return idkp;
-}
-
-static void ide_disk_put(struct ide_disk_obj *idkp)
-{
- ide_drive_t *drive = idkp->drive;
-
- mutex_lock(&idedisk_ref_mutex);
- kref_put(&idkp->kref, ide_disk_release);
- ide_device_put(drive);
- mutex_unlock(&idedisk_ref_mutex);
-}
-
static const u8 ide_rw_cmds[] = {
ATA_CMD_READ_MULTI,
ATA_CMD_WRITE_MULTI,
@@ -374,7 +333,7 @@ static void idedisk_check_hpa(ide_drive_t *drive)
}
}
-static void init_idedisk_capacity(ide_drive_t *drive)
+static int ide_disk_get_capacity(ide_drive_t *drive)
{
u16 *id = drive->id;
int lba;
@@ -403,11 +362,28 @@ static void init_idedisk_capacity(ide_drive_t *drive)
if (ata_id_hpa_enabled(id))
idedisk_check_hpa(drive);
}
-}
-sector_t ide_disk_capacity(ide_drive_t *drive)
-{
- return drive->capacity64;
+ /* limit drive capacity to 137GB if LBA48 cannot be used */
+ if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
+ drive->capacity64 > 1ULL << 28) {
+ printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
+ "%llu sectors (%llu MB)\n",
+ drive->name, (unsigned long long)drive->capacity64,
+ sectors_to_MB(drive->capacity64));
+ drive->capacity64 = 1ULL << 28;
+ }
+
+ if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
+ (drive->dev_flags & IDE_DFLAG_LBA48)) {
+ if (drive->capacity64 > 1ULL << 28) {
+ printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
+ " will be used for accessing sectors "
+ "> %u\n", drive->name, 1 << 28);
+ } else
+ drive->dev_flags &= ~IDE_DFLAG_LBA48;
+ }
+
+ return 0;
}
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
@@ -508,7 +484,7 @@ static void update_ordered(ide_drive_t *drive)
* time we have trimmed the drive capacity if LBA48 is
* not available so we don't need to recheck that.
*/
- capacity = ide_disk_capacity(drive);
+ capacity = ide_gd_capacity(drive);
barrier = ata_id_flush_enabled(id) &&
(drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
@@ -616,9 +592,15 @@ ide_ext_devset_rw(wcache, wcache);
ide_ext_devset_rw_sync(nowerr, nowerr);
-static void idedisk_setup(ide_drive_t *drive)
+static int ide_disk_check(ide_drive_t *drive, const char *s)
+{
+ return 1;
+}
+
+static void ide_disk_setup(ide_drive_t *drive)
{
struct ide_disk_obj *idkp = drive->driver_data;
+ struct request_queue *q = drive->queue;
ide_hwif_t *hwif = drive->hwif;
u16 *id = drive->id;
char *m = (char *)&id[ATA_ID_PROD];
@@ -645,40 +627,23 @@ static void idedisk_setup(ide_drive_t *drive)
if (max_s > hwif->rqsize)
max_s = hwif->rqsize;
- blk_queue_max_sectors(drive->queue, max_s);
+ blk_queue_max_sectors(q, max_s);
}
printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
- drive->queue->max_sectors / 2);
+ q->max_sectors / 2);
- /* calculate drive capacity, and select LBA if possible */
- init_idedisk_capacity(drive);
-
- /* limit drive capacity to 137GB if LBA48 cannot be used */
- if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
- drive->capacity64 > 1ULL << 28) {
- printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
- "%llu sectors (%llu MB)\n",
- drive->name, (unsigned long long)drive->capacity64,
- sectors_to_MB(drive->capacity64));
- drive->capacity64 = 1ULL << 28;
- }
+ if (ata_id_is_ssd(id) || ata_id_is_cfa(id))
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
- if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
- (drive->dev_flags & IDE_DFLAG_LBA48)) {
- if (drive->capacity64 > 1ULL << 28) {
- printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
- " will be used for accessing sectors "
- "> %u\n", drive->name, 1 << 28);
- } else
- drive->dev_flags &= ~IDE_DFLAG_LBA48;
- }
+ /* calculate drive capacity, and select LBA if possible */
+ ide_disk_get_capacity(drive);
/*
* if possible, give fdisk access to more of the drive,
* by correcting bios_cyls:
*/
- capacity = ide_disk_capacity(drive);
+ capacity = ide_gd_capacity(drive);
if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
if (ata_id_lba48_enabled(drive->id)) {
@@ -718,9 +683,17 @@ static void idedisk_setup(ide_drive_t *drive)
drive->dev_flags |= IDE_DFLAG_WCACHE;
set_wcache(drive, 1);
+
+ if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
+ (drive->head == 0 || drive->head > 16)) {
+ printk(KERN_ERR "%s: invalid geometry: %d physical heads?\n",
+ drive->name, drive->head);
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
+ } else
+ drive->dev_flags |= IDE_DFLAG_ATTACH;
}
-static void ide_cacheflush_p(ide_drive_t *drive)
+static void ide_disk_flush(ide_drive_t *drive)
{
if (ata_id_flush_enabled(drive->id) == 0 ||
(drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
@@ -730,267 +703,40 @@ static void ide_cacheflush_p(ide_drive_t *drive)
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
}
-static void ide_disk_remove(ide_drive_t *drive)
-{
- struct ide_disk_obj *idkp = drive->driver_data;
- struct gendisk *g = idkp->disk;
-
- ide_proc_unregister_driver(drive, idkp->driver);
-
- del_gendisk(g);
-
- ide_cacheflush_p(drive);
-
- ide_disk_put(idkp);
-}
-
-static void ide_disk_release(struct kref *kref)
-{
- struct ide_disk_obj *idkp = to_ide_disk(kref);
- ide_drive_t *drive = idkp->drive;
- struct gendisk *g = idkp->disk;
-
- drive->driver_data = NULL;
- g->private_data = NULL;
- put_disk(g);
- kfree(idkp);
-}
-
-static int ide_disk_probe(ide_drive_t *drive);
-
-/*
- * On HPA drives the capacity needs to be
- * reinitilized on resume otherwise the disk
- * can not be used and a hard reset is required
- */
-static void ide_disk_resume(ide_drive_t *drive)
-{
- if (ata_id_hpa_enabled(drive->id))
- init_idedisk_capacity(drive);
-}
-
-static void ide_device_shutdown(ide_drive_t *drive)
+static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk)
{
-#ifdef CONFIG_ALPHA
- /* On Alpha, halt(8) doesn't actually turn the machine off,
- it puts you into the sort of firmware monitor. Typically,
- it's used to boot another kernel image, so it's not much
- different from reboot(8). Therefore, we don't need to
- spin down the disk in this case, especially since Alpha
- firmware doesn't handle disks in standby mode properly.
- On the other hand, it's reasonably safe to turn the power
- off when the shutdown process reaches the firmware prompt,
- as the firmware initialization takes rather long time -
- at least 10 seconds, which should be sufficient for
- the disk to expire its write cache. */
- if (system_state != SYSTEM_POWER_OFF) {
-#else
- if (system_state == SYSTEM_RESTART) {
-#endif
- ide_cacheflush_p(drive);
- return;
- }
-
- printk(KERN_INFO "Shutdown: %s\n", drive->name);
-
- drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
+ return 0;
}
-static ide_driver_t idedisk_driver = {
- .gen_driver = {
- .owner = THIS_MODULE,
- .name = "ide-disk",
- .bus = &ide_bus_type,
- },
- .probe = ide_disk_probe,
- .remove = ide_disk_remove,
- .resume = ide_disk_resume,
- .shutdown = ide_device_shutdown,
- .version = IDEDISK_VERSION,
- .do_request = ide_do_rw_disk,
- .end_request = ide_end_request,
- .error = __ide_error,
-#ifdef CONFIG_IDE_PROC_FS
- .proc = ide_disk_proc,
- .settings = ide_disk_settings,
-#endif
-};
-
-static int idedisk_set_doorlock(ide_drive_t *drive, int on)
+static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk,
+ int on)
{
ide_task_t task;
+ int ret;
+
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
+ return 0;
memset(&task, 0, sizeof(task));
task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- return ide_no_data_taskfile(drive, &task);
-}
-
-static int idedisk_open(struct inode *inode, struct file *filp)
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_disk_obj *idkp;
- ide_drive_t *drive;
-
- idkp = ide_disk_get(disk);
- if (idkp == NULL)
- return -ENXIO;
-
- drive = idkp->drive;
-
- idkp->openers++;
-
- if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
- check_disk_change(inode->i_bdev);
- /*
- * Ignore the return code from door_lock,
- * since the open() has already succeeded,
- * and the door_lock is irrelevant at this point.
- */
- if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
- idedisk_set_doorlock(drive, 1))
- drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
- }
- return 0;
-}
-
-static int idedisk_release(struct inode *inode, struct file *filp)
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_disk_obj *idkp = ide_disk_g(disk);
- ide_drive_t *drive = idkp->drive;
-
- if (idkp->openers == 1)
- ide_cacheflush_p(drive);
-
- if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
- if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
- idedisk_set_doorlock(drive, 0))
- drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
- }
-
- idkp->openers--;
-
- ide_disk_put(idkp);
-
- return 0;
-}
-
-static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
- ide_drive_t *drive = idkp->drive;
-
- geo->heads = drive->bios_head;
- geo->sectors = drive->bios_sect;
- geo->cylinders = (u16)drive->bios_cyl; /* truncate */
- return 0;
-}
-
-static int idedisk_media_changed(struct gendisk *disk)
-{
- struct ide_disk_obj *idkp = ide_disk_g(disk);
- ide_drive_t *drive = idkp->drive;
-
- /* do not scan partitions twice if this is a removable device */
- if (drive->dev_flags & IDE_DFLAG_ATTACH) {
- drive->dev_flags &= ~IDE_DFLAG_ATTACH;
- return 0;
- }
+ ret = ide_no_data_taskfile(drive, &task);
- /* if removable, always assume it was changed */
- return !!(drive->dev_flags & IDE_DFLAG_REMOVABLE);
-}
+ if (ret)
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
-static int idedisk_revalidate_disk(struct gendisk *disk)
-{
- struct ide_disk_obj *idkp = ide_disk_g(disk);
- set_capacity(disk, ide_disk_capacity(idkp->drive));
- return 0;
+ return ret;
}
-static struct block_device_operations idedisk_ops = {
- .owner = THIS_MODULE,
- .open = idedisk_open,
- .release = idedisk_release,
- .ioctl = ide_disk_ioctl,
- .getgeo = idedisk_getgeo,
- .media_changed = idedisk_media_changed,
- .revalidate_disk = idedisk_revalidate_disk
+const struct ide_disk_ops ide_ata_disk_ops = {
+ .check = ide_disk_check,
+ .get_capacity = ide_disk_get_capacity,
+ .setup = ide_disk_setup,
+ .flush = ide_disk_flush,
+ .init_media = ide_disk_init_media,
+ .set_doorlock = ide_disk_set_doorlock,
+ .do_request = ide_do_rw_disk,
+ .end_request = ide_end_request,
+ .ioctl = ide_disk_ioctl,
};
-
-MODULE_DESCRIPTION("ATA DISK Driver");
-
-static int ide_disk_probe(ide_drive_t *drive)
-{
- struct ide_disk_obj *idkp;
- struct gendisk *g;
-
- /* strstr("foo", "") is non-NULL */
- if (!strstr("ide-disk", drive->driver_req))
- goto failed;
-
- if (drive->media != ide_disk)
- goto failed;
-
- idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
- if (!idkp)
- goto failed;
-
- g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
- if (!g)
- goto out_free_idkp;
-
- ide_init_disk(g, drive);
-
- kref_init(&idkp->kref);
-
- idkp->drive = drive;
- idkp->driver = &idedisk_driver;
- idkp->disk = g;
-
- g->private_data = &idkp->driver;
-
- drive->driver_data = idkp;
-
- idedisk_setup(drive);
- if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
- (drive->head == 0 || drive->head > 16)) {
- printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
- drive->name, drive->head);
- drive->dev_flags &= ~IDE_DFLAG_ATTACH;
- } else
- drive->dev_flags |= IDE_DFLAG_ATTACH;
-
- g->minors = IDE_DISK_MINORS;
- g->driverfs_dev = &drive->gendev;
- g->flags |= GENHD_FL_EXT_DEVT;
- if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
- g->flags = GENHD_FL_REMOVABLE;
- set_capacity(g, ide_disk_capacity(drive));
- g->fops = &idedisk_ops;
- add_disk(g);
- return 0;
-
-out_free_idkp:
- kfree(idkp);
-failed:
- return -ENODEV;
-}
-
-static void __exit idedisk_exit(void)
-{
- driver_unregister(&idedisk_driver.gen_driver);
-}
-
-static int __init idedisk_init(void)
-{
- return driver_register(&idedisk_driver.gen_driver);
-}
-
-MODULE_ALIAS("ide:*m-disk*");
-MODULE_ALIAS("ide-disk");
-module_init(idedisk_init);
-module_exit(idedisk_exit);
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.h b/drivers/ide/ide-disk.h
index a82fa435566..d511dab7c4a 100644
--- a/drivers/ide/ide-disk.h
+++ b/drivers/ide/ide-disk.h
@@ -1,19 +1,11 @@
#ifndef __IDE_DISK_H
#define __IDE_DISK_H
-struct ide_disk_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
-};
-
-#define ide_disk_g(disk) \
- container_of((disk)->private_data, struct ide_disk_obj, driver)
+#include "ide-gd.h"
+#ifdef CONFIG_IDE_GD_ATA
/* ide-disk.c */
-sector_t ide_disk_capacity(ide_drive_t *);
+extern const struct ide_disk_ops ide_ata_disk_ops;
ide_decl_devset(address);
ide_decl_devset(multcount);
ide_decl_devset(nowerr);
@@ -21,12 +13,17 @@ ide_decl_devset(wcache);
ide_decl_devset(acoustic);
/* ide-disk_ioctl.c */
-int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+int ide_disk_ioctl(ide_drive_t *, struct block_device *, fmode_t, unsigned int,
+ unsigned long);
#ifdef CONFIG_IDE_PROC_FS
/* ide-disk_proc.c */
extern ide_proc_entry_t ide_disk_proc[];
extern const struct ide_proc_devset ide_disk_settings[];
#endif
+#else
+#define ide_disk_proc NULL
+#define ide_disk_settings NULL
+#endif
#endif /* __IDE_DISK_H */
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
index a6cf1a03a80..7b783dd7c0b 100644
--- a/drivers/ide/ide-disk_ioctl.c
+++ b/drivers/ide/ide-disk_ioctl.c
@@ -13,17 +13,14 @@ static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
{ 0 }
};
-int ide_disk_ioctl(struct inode *inode, struct file *file,
+int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
- struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
- ide_drive_t *drive = idkp->drive;
int err;
err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
if (err != -EOPNOTSUPP)
return err;
- return generic_ide_ioctl(drive, file, bdev, cmd, arg);
+ return generic_ide_ioctl(drive, bdev, cmd, arg);
}
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
index 4724976afe7..1146f4204c6 100644
--- a/drivers/ide/ide-disk_proc.c
+++ b/drivers/ide/ide-disk_proc.c
@@ -56,7 +56,7 @@ static int proc_idedisk_read_capacity
ide_drive_t*drive = (ide_drive_t *)data;
int len;
- len = sprintf(page, "%llu\n", (long long)ide_disk_capacity(drive));
+ len = sprintf(page, "%llu\n", (long long)ide_gd_capacity(drive));
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
index 0903782689e..cac431f0df1 100644
--- a/drivers/ide/ide-dma-sff.c
+++ b/drivers/ide/ide-dma-sff.c
@@ -130,7 +130,7 @@ int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
xcount = bcount & 0xffff;
if (is_trm290)
xcount = ((xcount >> 2) - 1) << 16;
- if (xcount == 0x0000) {
+ else if (xcount == 0x0000) {
if (count++ >= PRD_ENTRIES)
goto use_pio_instead;
*table++ = cpu_to_le32(0x8000);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index cf0aa25470e..aeb1ad782f5 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -15,12 +15,6 @@
* Documentation/ide/ChangeLog.ide-floppy.1996-2002
*/
-#define DRV_NAME "ide-floppy"
-#define PFX DRV_NAME ": "
-
-#define IDEFLOPPY_VERSION "1.00"
-
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
@@ -49,19 +43,6 @@
#include "ide-floppy.h"
-/* module parameters */
-static unsigned long debug_mask;
-module_param(debug_mask, ulong, 0644);
-
-/* define to see debug info */
-#define IDEFLOPPY_DEBUG_LOG 0
-
-#if IDEFLOPPY_DEBUG_LOG
-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
-#else
-#define ide_debug_log(lvl, fmt, args...) do {} while (0)
-#endif
-
/*
* After each failed packet command we issue a request sense command and retry
* the packet command IDEFLOPPY_MAX_PC_RETRIES times.
@@ -83,43 +64,13 @@ module_param(debug_mask, ulong, 0644);
/* Error code returned in rq->errors to the higher part of the driver. */
#define IDEFLOPPY_ERROR_GENERAL 101
-static DEFINE_MUTEX(idefloppy_ref_mutex);
-
-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_drv_g(disk, ide_floppy_obj);
- if (floppy) {
- if (ide_device_get(floppy->drive))
- floppy = NULL;
- else
- kref_get(&floppy->kref);
- }
- mutex_unlock(&idefloppy_ref_mutex);
- return floppy;
-}
-
-static void ide_floppy_put(struct ide_floppy_obj *floppy)
-{
- ide_drive_t *drive = floppy->drive;
-
- mutex_lock(&idefloppy_ref_mutex);
- kref_put(&floppy->kref, idefloppy_cleanup_obj);
- ide_device_put(drive);
- mutex_unlock(&idefloppy_ref_mutex);
-}
-
/*
* Used to finish servicing a request. For read/write requests, we will call
* ide_end_request to pass to the next buffer.
*/
-static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
int error;
@@ -161,12 +112,12 @@ static void idefloppy_update_buffers(ide_drive_t *drive,
struct bio *bio = rq->bio;
while ((bio = rq->bio) != NULL)
- idefloppy_end_request(drive, 1, 0);
+ ide_floppy_end_request(drive, 1, 0);
}
static void ide_floppy_callback(ide_drive_t *drive, int dsc)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct ide_atapi_pc *pc = drive->pc;
int uptodate = pc->error ? 0 : 1;
@@ -200,10 +151,10 @@ static void ide_floppy_callback(ide_drive_t *drive, int dsc)
"Aborting request!\n");
}
- idefloppy_end_request(drive, uptodate, 0);
+ ide_floppy_end_request(drive, uptodate, 0);
}
-static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+static void ide_floppy_report_error(struct ide_disk_obj *floppy,
struct ide_atapi_pc *pc)
{
/* supress error messages resulting from Medium not present */
@@ -222,7 +173,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
if (floppy->failed_pc == NULL &&
pc->c[0] != GPCMD_REQUEST_SENSE)
@@ -286,7 +237,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc, struct request *rq,
unsigned long sector)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
int block = sector / floppy->bs_factor;
int blocks = rq->nr_sectors / floppy->bs_factor;
int cmd = rq_data_dir(rq);
@@ -310,7 +261,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive,
pc->flags |= PC_FLAG_DMA_OK;
}
-static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
+static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy,
struct ide_atapi_pc *pc, struct request *rq)
{
ide_init_pc(pc);
@@ -329,13 +280,12 @@ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
pc->req_xfer = pc->buf_size = rq->data_len;
}
-static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
- struct request *rq, sector_t block_s)
+static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
+ struct request *rq, sector_t block)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
struct ide_atapi_pc *pc;
- unsigned long block = (unsigned long)block_s;
ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
"errors: %d\n",
@@ -353,7 +303,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
else
printk(KERN_ERR PFX "%s: I/O error\n", drive->name);
- idefloppy_end_request(drive, 0, 0);
+ ide_floppy_end_request(drive, 0, 0);
return ide_stopped;
}
if (blk_fs_request(rq)) {
@@ -361,11 +311,11 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
(rq->nr_sectors % floppy->bs_factor)) {
printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
drive->name);
- idefloppy_end_request(drive, 0, 0);
+ ide_floppy_end_request(drive, 0, 0);
return ide_stopped;
}
pc = &floppy->queued_pc;
- idefloppy_create_rw_cmd(drive, pc, rq, block);
+ idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
} else if (blk_special_request(rq)) {
pc = (struct ide_atapi_pc *) rq->buffer;
} else if (blk_pc_request(rq)) {
@@ -373,7 +323,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
idefloppy_blockpc_cmd(floppy, pc, rq);
} else {
blk_dump_rq_flags(rq, PFX "unsupported command in queue");
- idefloppy_end_request(drive, 0, 0);
+ ide_floppy_end_request(drive, 0, 0);
return ide_stopped;
}
@@ -394,7 +344,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
*/
static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct gendisk *disk = floppy->disk;
struct ide_atapi_pc pc;
u8 *page;
@@ -410,11 +360,11 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
}
if (pc.buf[3] & 0x80)
- drive->atapi_flags |= IDE_AFLAG_WP;
+ drive->dev_flags |= IDE_DFLAG_WP;
else
- drive->atapi_flags &= ~IDE_AFLAG_WP;
+ drive->dev_flags &= ~IDE_DFLAG_WP;
- set_disk_ro(disk, !!(drive->atapi_flags & IDE_AFLAG_WP));
+ set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP));
page = &pc.buf[8];
@@ -445,7 +395,9 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
drive->name, lba_capacity, capacity);
floppy->blocks = floppy->block_size ?
capacity / floppy->block_size : 0;
+ drive->capacity64 = floppy->blocks * floppy->bs_factor;
}
+
return 0;
}
@@ -455,7 +407,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
*/
static int ide_floppy_get_capacity(ide_drive_t *drive)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct gendisk *disk = floppy->disk;
struct ide_atapi_pc pc;
u8 *cap_desc;
@@ -466,7 +418,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
drive->bios_head = drive->bios_sect = 0;
floppy->blocks = 0;
floppy->bs_factor = 1;
- set_capacity(floppy->disk, 0);
+ drive->capacity64 = 0;
ide_floppy_create_read_capacity_cmd(&pc);
if (ide_queue_pc_tail(drive, disk, &pc)) {
@@ -523,6 +475,8 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
"non 512 bytes block size not "
"fully supported\n",
drive->name);
+ drive->capacity64 =
+ floppy->blocks * floppy->bs_factor;
rc = 0;
}
break;
@@ -547,21 +501,12 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
(void) ide_floppy_get_flexible_disk_page(drive);
- set_capacity(disk, floppy->blocks * floppy->bs_factor);
-
return rc;
}
-sector_t ide_floppy_capacity(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- unsigned long capacity = floppy->blocks * floppy->bs_factor;
-
- return capacity;
-}
-
-static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
+static void ide_floppy_setup(ide_drive_t *drive)
{
+ struct ide_disk_obj *floppy = drive->driver_data;
u16 *id = drive->id;
drive->pc_callback = ide_floppy_callback;
@@ -592,252 +537,42 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
blk_queue_max_sectors(drive->queue, 64);
drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
/* IOMEGA Clik! drives do not support lock/unlock commands */
- drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
}
(void) ide_floppy_get_capacity(drive);
ide_proc_register_driver(drive, floppy->driver);
-}
-static void ide_floppy_remove(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct gendisk *g = floppy->disk;
-
- ide_proc_unregister_driver(drive, floppy->driver);
-
- del_gendisk(g);
-
- ide_floppy_put(floppy);
+ drive->dev_flags |= IDE_DFLAG_ATTACH;
}
-static void idefloppy_cleanup_obj(struct kref *kref)
+static void ide_floppy_flush(ide_drive_t *drive)
{
- struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj);
- ide_drive_t *drive = floppy->drive;
- struct gendisk *g = floppy->disk;
-
- drive->driver_data = NULL;
- g->private_data = NULL;
- put_disk(g);
- kfree(floppy);
}
-static int ide_floppy_probe(ide_drive_t *);
-
-static ide_driver_t idefloppy_driver = {
- .gen_driver = {
- .owner = THIS_MODULE,
- .name = "ide-floppy",
- .bus = &ide_bus_type,
- },
- .probe = ide_floppy_probe,
- .remove = ide_floppy_remove,
- .version = IDEFLOPPY_VERSION,
- .do_request = idefloppy_do_request,
- .end_request = idefloppy_end_request,
- .error = __ide_error,
-#ifdef CONFIG_IDE_PROC_FS
- .proc = ide_floppy_proc,
- .settings = ide_floppy_settings,
-#endif
-};
-
-static int idefloppy_open(struct inode *inode, struct file *filp)
+static int ide_floppy_init_media(ide_drive_t *drive, struct gendisk *disk)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_floppy_obj *floppy;
- ide_drive_t *drive;
int ret = 0;
- floppy = ide_floppy_get(disk);
- if (!floppy)
- return -ENXIO;
-
- drive = floppy->drive;
-
- ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
- floppy->openers++;
-
- if (floppy->openers == 1) {
- drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
- /* Just in case */
-
- if (ide_do_test_unit_ready(drive, disk))
- ide_do_start_stop(drive, disk, 1);
-
- if (ide_floppy_get_capacity(drive)
- && (filp->f_flags & O_NDELAY) == 0
- /*
- * Allow O_NDELAY to open a drive without a disk, or with an
- * unreadable disk, so that we can get the format capacity
- * of the drive or begin the format - Sam
- */
- ) {
- ret = -EIO;
- goto out_put_floppy;
- }
-
- if ((drive->atapi_flags & IDE_AFLAG_WP) && (filp->f_mode & 2)) {
- ret = -EROFS;
- goto out_put_floppy;
- }
-
- drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
- ide_set_media_lock(drive, disk, 1);
- check_disk_change(inode->i_bdev);
- } else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
- ret = -EBUSY;
- goto out_put_floppy;
- }
- return 0;
-
-out_put_floppy:
- floppy->openers--;
- ide_floppy_put(floppy);
- return ret;
-}
-
-static int idefloppy_release(struct inode *inode, struct file *filp)
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
- ide_drive_t *drive = floppy->drive;
-
- ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
- if (floppy->openers == 1) {
- ide_set_media_lock(drive, disk, 0);
- drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
- }
-
- floppy->openers--;
-
- ide_floppy_put(floppy);
-
- return 0;
-}
-
-static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
- ide_floppy_obj);
- ide_drive_t *drive = floppy->drive;
+ if (ide_do_test_unit_ready(drive, disk))
+ ide_do_start_stop(drive, disk, 1);
- geo->heads = drive->bios_head;
- geo->sectors = drive->bios_sect;
- geo->cylinders = (u16)drive->bios_cyl; /* truncate */
- return 0;
-}
+ ret = ide_floppy_get_capacity(drive);
-static int idefloppy_media_changed(struct gendisk *disk)
-{
- struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
- ide_drive_t *drive = floppy->drive;
- int ret;
+ set_capacity(disk, ide_gd_capacity(drive));
- /* do not scan partitions twice if this is a removable device */
- if (drive->dev_flags & IDE_DFLAG_ATTACH) {
- drive->dev_flags &= ~IDE_DFLAG_ATTACH;
- return 0;
- }
- ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
- drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return ret;
}
-static int idefloppy_revalidate_disk(struct gendisk *disk)
-{
- struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
- set_capacity(disk, ide_floppy_capacity(floppy->drive));
- return 0;
-}
-
-static struct block_device_operations idefloppy_ops = {
- .owner = THIS_MODULE,
- .open = idefloppy_open,
- .release = idefloppy_release,
- .ioctl = ide_floppy_ioctl,
- .getgeo = idefloppy_getgeo,
- .media_changed = idefloppy_media_changed,
- .revalidate_disk = idefloppy_revalidate_disk
+const struct ide_disk_ops ide_atapi_disk_ops = {
+ .check = ide_check_atapi_device,
+ .get_capacity = ide_floppy_get_capacity,
+ .setup = ide_floppy_setup,
+ .flush = ide_floppy_flush,
+ .init_media = ide_floppy_init_media,
+ .set_doorlock = ide_set_media_lock,
+ .do_request = ide_floppy_do_request,
+ .end_request = ide_floppy_end_request,
+ .ioctl = ide_floppy_ioctl,
};
-
-static int ide_floppy_probe(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy;
- struct gendisk *g;
-
- if (!strstr("ide-floppy", drive->driver_req))
- goto failed;
-
- if (drive->media != ide_floppy)
- goto failed;
-
- if (!ide_check_atapi_device(drive, DRV_NAME)) {
- printk(KERN_ERR PFX "%s: not supported by this version of "
- DRV_NAME "\n", drive->name);
- goto failed;
- }
- floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
- if (!floppy) {
- printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
- drive->name);
- goto failed;
- }
-
- g = alloc_disk(1 << PARTN_BITS);
- if (!g)
- goto out_free_floppy;
-
- ide_init_disk(g, drive);
-
- kref_init(&floppy->kref);
-
- floppy->drive = drive;
- floppy->driver = &idefloppy_driver;
- floppy->disk = g;
-
- g->private_data = &floppy->driver;
-
- drive->driver_data = floppy;
-
- drive->debug_mask = debug_mask;
-
- idefloppy_setup(drive, floppy);
- drive->dev_flags |= IDE_DFLAG_ATTACH;
-
- g->minors = 1 << PARTN_BITS;
- g->driverfs_dev = &drive->gendev;
- if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
- g->flags = GENHD_FL_REMOVABLE;
- g->fops = &idefloppy_ops;
- add_disk(g);
- return 0;
-
-out_free_floppy:
- kfree(floppy);
-failed:
- return -ENODEV;
-}
-
-static void __exit idefloppy_exit(void)
-{
- driver_unregister(&idefloppy_driver.gen_driver);
-}
-
-static int __init idefloppy_init(void)
-{
- printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
- return driver_register(&idefloppy_driver.gen_driver);
-}
-
-MODULE_ALIAS("ide:*m-floppy*");
-MODULE_ALIAS("ide-floppy");
-module_init(idefloppy_init);
-module_exit(idefloppy_exit);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
-
diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h
index 17cf865e583..6dd2beb4843 100644
--- a/drivers/ide/ide-floppy.h
+++ b/drivers/ide/ide-floppy.h
@@ -1,37 +1,9 @@
#ifndef __IDE_FLOPPY_H
#define __IDE_FLOPPY_H
-/*
- * 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 a variable of type
- * idefloppy_floppy_t, defined below.
- */
-typedef struct ide_floppy_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
-
- /* Last failed packet command */
- struct ide_atapi_pc *failed_pc;
- /* used for blk_{fs,pc}_request() requests */
- struct ide_atapi_pc queued_pc;
-
- /* Last error information */
- u8 sense_key, asc, ascq;
-
- int progress_indication;
-
- /* Device information */
- /* Current format */
- int blocks, block_size, bs_factor;
- /* Last format capacity descriptor */
- u8 cap_desc[8];
- /* Copy of the flexible disk page */
- u8 flexible_disk_page[32];
-} idefloppy_floppy_t;
+#include "ide-gd.h"
+#ifdef CONFIG_IDE_GD_ATAPI
/*
* Pages of the SELECT SENSE / MODE SENSE packet commands.
* See SFF-8070i spec.
@@ -46,17 +18,22 @@ typedef struct ide_floppy_obj {
#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
/* ide-floppy.c */
+extern const struct ide_disk_ops ide_atapi_disk_ops;
void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
-sector_t ide_floppy_capacity(ide_drive_t *);
/* ide-floppy_ioctl.c */
-int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long);
+int ide_floppy_ioctl(ide_drive_t *, struct block_device *, fmode_t,
+ unsigned int, unsigned long);
#ifdef CONFIG_IDE_PROC_FS
/* ide-floppy_proc.c */
extern ide_proc_entry_t ide_floppy_proc[];
extern const struct ide_proc_devset ide_floppy_settings[];
#endif
+#else
+#define ide_floppy_proc NULL
+#define ide_floppy_settings NULL
+#endif
#endif /*__IDE_FLOPPY_H */
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index a3a7a0809e2..2bc51ff73fe 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -33,7 +33,7 @@
static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
{
- struct ide_floppy_obj *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct ide_atapi_pc pc;
u8 header_len, desc_cnt;
int i, blocks, length, u_array_size, u_index;
@@ -113,7 +113,7 @@ static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct ide_atapi_pc pc;
drive->atapi_flags &= ~IDE_AFLAG_SRFP;
@@ -132,17 +132,17 @@ static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct ide_atapi_pc pc;
int blocks, length, flags, err = 0;
if (floppy->openers > 1) {
/* Don't format if someone is using the disk */
- drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
+ drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
return -EBUSY;
}
- drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
+ drive->dev_flags |= IDE_DFLAG_FORMAT_IN_PROGRESS;
/*
* Send ATAPI_FORMAT_UNIT to the drive.
@@ -174,7 +174,7 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
out:
if (err)
- drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
+ drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
return err;
}
@@ -190,7 +190,7 @@ out:
static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
{
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct ide_atapi_pc pc;
int progress_indication = 0x10000;
@@ -226,7 +226,7 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
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;
+ struct ide_disk_obj *floppy = drive->driver_data;
struct gendisk *disk = floppy->disk;
int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
@@ -241,7 +241,7 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
return 0;
}
-static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
+static int ide_floppy_format_ioctl(ide_drive_t *drive, fmode_t mode,
unsigned int cmd, void __user *argp)
{
switch (cmd) {
@@ -250,7 +250,7 @@ static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
return ide_floppy_get_format_capacities(drive, argp);
case IDEFLOPPY_IOCTL_FORMAT_START:
- if (!(file->f_mode & 2))
+ if (!(mode & FMODE_WRITE))
return -EPERM;
return ide_floppy_format_unit(drive, (int __user *)argp);
case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
@@ -260,13 +260,9 @@ static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
}
}
-int ide_floppy_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
+ fmode_t mode, unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
- struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
- ide_floppy_obj);
- ide_drive_t *drive = floppy->drive;
struct ide_atapi_pc pc;
void __user *argp = (void __user *)arg;
int err;
@@ -274,7 +270,7 @@ int ide_floppy_ioctl(struct inode *inode, struct file *file,
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
return ide_floppy_lockdoor(drive, &pc, arg, cmd);
- err = ide_floppy_format_ioctl(drive, file, cmd, argp);
+ err = ide_floppy_format_ioctl(drive, mode, cmd, argp);
if (err != -ENOTTY)
return err;
@@ -283,11 +279,11 @@ int ide_floppy_ioctl(struct inode *inode, struct file *file,
* and CDROM_SEND_PACKET (legacy) ioctls
*/
if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
- err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
- bdev->bd_disk, cmd, argp);
+ err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk,
+ mode, cmd, argp);
if (err == -ENOTTY)
- err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+ err = generic_ide_ioctl(drive, bdev, cmd, arg);
return err;
}
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
index 76f0c6c4eca..3ec762cb60a 100644
--- a/drivers/ide/ide-floppy_proc.c
+++ b/drivers/ide/ide-floppy_proc.c
@@ -9,7 +9,7 @@ static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
ide_drive_t*drive = (ide_drive_t *)data;
int len;
- len = sprintf(page, "%llu\n", (long long)ide_floppy_capacity(drive));
+ len = sprintf(page, "%llu\n", (long long)ide_gd_capacity(drive));
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
new file mode 100644
index 00000000000..7b666285437
--- /dev/null
+++ b/drivers/ide/ide-gd.c
@@ -0,0 +1,396 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/genhd.h>
+#include <linux/mutex.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
+#define IDE_DISK_MINORS (1 << PARTN_BITS)
+#else
+#define IDE_DISK_MINORS 0
+#endif
+
+#include "ide-disk.h"
+#include "ide-floppy.h"
+
+#define IDE_GD_VERSION "1.18"
+
+/* module parameters */
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
+
+static DEFINE_MUTEX(ide_disk_ref_mutex);
+
+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(&ide_disk_ref_mutex);
+ idkp = ide_drv_g(disk, ide_disk_obj);
+ if (idkp) {
+ if (ide_device_get(idkp->drive))
+ idkp = NULL;
+ else
+ kref_get(&idkp->kref);
+ }
+ mutex_unlock(&ide_disk_ref_mutex);
+ return idkp;
+}
+
+static void ide_disk_put(struct ide_disk_obj *idkp)
+{
+ ide_drive_t *drive = idkp->drive;
+
+ mutex_lock(&ide_disk_ref_mutex);
+ kref_put(&idkp->kref, ide_disk_release);
+ ide_device_put(drive);
+ mutex_unlock(&ide_disk_ref_mutex);
+}
+
+sector_t ide_gd_capacity(ide_drive_t *drive)
+{
+ return drive->capacity64;
+}
+
+static int ide_gd_probe(ide_drive_t *);
+
+static void ide_gd_remove(ide_drive_t *drive)
+{
+ struct ide_disk_obj *idkp = drive->driver_data;
+ struct gendisk *g = idkp->disk;
+
+ ide_proc_unregister_driver(drive, idkp->driver);
+
+ del_gendisk(g);
+
+ drive->disk_ops->flush(drive);
+
+ ide_disk_put(idkp);
+}
+
+static void ide_disk_release(struct kref *kref)
+{
+ struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj);
+ ide_drive_t *drive = idkp->drive;
+ struct gendisk *g = idkp->disk;
+
+ drive->disk_ops = NULL;
+ drive->driver_data = NULL;
+ g->private_data = NULL;
+ put_disk(g);
+ kfree(idkp);
+}
+
+/*
+ * On HPA drives the capacity needs to be
+ * reinitilized on resume otherwise the disk
+ * can not be used and a hard reset is required
+ */
+static void ide_gd_resume(ide_drive_t *drive)
+{
+ if (ata_id_hpa_enabled(drive->id))
+ (void)drive->disk_ops->get_capacity(drive);
+}
+
+static void ide_gd_shutdown(ide_drive_t *drive)
+{
+#ifdef CONFIG_ALPHA
+ /* On Alpha, halt(8) doesn't actually turn the machine off,
+ it puts you into the sort of firmware monitor. Typically,
+ it's used to boot another kernel image, so it's not much
+ different from reboot(8). Therefore, we don't need to
+ spin down the disk in this case, especially since Alpha
+ firmware doesn't handle disks in standby mode properly.
+ On the other hand, it's reasonably safe to turn the power
+ off when the shutdown process reaches the firmware prompt,
+ as the firmware initialization takes rather long time -
+ at least 10 seconds, which should be sufficient for
+ the disk to expire its write cache. */
+ if (system_state != SYSTEM_POWER_OFF) {
+#else
+ if (system_state == SYSTEM_RESTART) {
+#endif
+ drive->disk_ops->flush(drive);
+ return;
+ }
+
+ printk(KERN_INFO "Shutdown: %s\n", drive->name);
+
+ drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
+}
+
+#ifdef CONFIG_IDE_PROC_FS
+static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
+{
+ return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
+}
+
+static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
+{
+ return (drive->media == ide_disk) ? ide_disk_settings
+ : ide_floppy_settings;
+}
+#endif
+
+static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
+ struct request *rq, sector_t sector)
+{
+ return drive->disk_ops->do_request(drive, rq, sector);
+}
+
+static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs)
+{
+ return drive->disk_ops->end_request(drive, uptodate, nrsecs);
+}
+
+static ide_driver_t ide_gd_driver = {
+ .gen_driver = {
+ .owner = THIS_MODULE,
+ .name = "ide-gd",
+ .bus = &ide_bus_type,
+ },
+ .probe = ide_gd_probe,
+ .remove = ide_gd_remove,
+ .resume = ide_gd_resume,
+ .shutdown = ide_gd_shutdown,
+ .version = IDE_GD_VERSION,
+ .do_request = ide_gd_do_request,
+ .end_request = ide_gd_end_request,
+ .error = __ide_error,
+#ifdef CONFIG_IDE_PROC_FS
+ .proc_entries = ide_disk_proc_entries,
+ .proc_devsets = ide_disk_proc_devsets,
+#endif
+};
+
+static int ide_gd_open(struct block_device *bdev, fmode_t mode)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ struct ide_disk_obj *idkp;
+ ide_drive_t *drive;
+ int ret = 0;
+
+ idkp = ide_disk_get(disk);
+ if (idkp == NULL)
+ return -ENXIO;
+
+ drive = idkp->drive;
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
+ idkp->openers++;
+
+ if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
+ drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
+ /* Just in case */
+
+ ret = drive->disk_ops->init_media(drive, disk);
+
+ /*
+ * Allow O_NDELAY to open a drive without a disk, or with an
+ * unreadable disk, so that we can get the format capacity
+ * of the drive or begin the format - Sam
+ */
+ if (ret && (mode & FMODE_NDELAY) == 0) {
+ ret = -EIO;
+ goto out_put_idkp;
+ }
+
+ if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
+ ret = -EROFS;
+ goto out_put_idkp;
+ }
+
+ /*
+ * Ignore the return code from door_lock,
+ * since the open() has already succeeded,
+ * and the door_lock is irrelevant at this point.
+ */
+ drive->disk_ops->set_doorlock(drive, disk, 1);
+ drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
+ check_disk_change(bdev);
+ } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
+ ret = -EBUSY;
+ goto out_put_idkp;
+ }
+ return 0;
+
+out_put_idkp:
+ idkp->openers--;
+ ide_disk_put(idkp);
+ return ret;
+}
+
+static int ide_gd_release(struct gendisk *disk, fmode_t mode)
+{
+ struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
+ ide_drive_t *drive = idkp->drive;
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
+ if (idkp->openers == 1)
+ drive->disk_ops->flush(drive);
+
+ if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
+ drive->disk_ops->set_doorlock(drive, disk, 0);
+ drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
+ }
+
+ idkp->openers--;
+
+ ide_disk_put(idkp);
+
+ return 0;
+}
+
+static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
+ ide_drive_t *drive = idkp->drive;
+
+ geo->heads = drive->bios_head;
+ geo->sectors = drive->bios_sect;
+ geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+ return 0;
+}
+
+static int ide_gd_media_changed(struct gendisk *disk)
+{
+ struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
+ ide_drive_t *drive = idkp->drive;
+ int ret;
+
+ /* do not scan partitions twice if this is a removable device */
+ if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
+ return 0;
+ }
+
+ ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
+ drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
+
+ return ret;
+}
+
+static int ide_gd_revalidate_disk(struct gendisk *disk)
+{
+ struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
+ set_capacity(disk, ide_gd_capacity(idkp->drive));
+ return 0;
+}
+
+static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
+ ide_drive_t *drive = idkp->drive;
+
+ return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
+}
+
+static struct block_device_operations ide_gd_ops = {
+ .owner = THIS_MODULE,
+ .open = ide_gd_open,
+ .release = ide_gd_release,
+ .locked_ioctl = ide_gd_ioctl,
+ .getgeo = ide_gd_getgeo,
+ .media_changed = ide_gd_media_changed,
+ .revalidate_disk = ide_gd_revalidate_disk
+};
+
+static int ide_gd_probe(ide_drive_t *drive)
+{
+ const struct ide_disk_ops *disk_ops = NULL;
+ struct ide_disk_obj *idkp;
+ struct gendisk *g;
+
+ /* strstr("foo", "") is non-NULL */
+ if (!strstr("ide-gd", drive->driver_req))
+ goto failed;
+
+#ifdef CONFIG_IDE_GD_ATA
+ if (drive->media == ide_disk)
+ disk_ops = &ide_ata_disk_ops;
+#endif
+#ifdef CONFIG_IDE_GD_ATAPI
+ if (drive->media == ide_floppy)
+ disk_ops = &ide_atapi_disk_ops;
+#endif
+ if (disk_ops == NULL)
+ goto failed;
+
+ if (disk_ops->check(drive, DRV_NAME) == 0) {
+ printk(KERN_ERR PFX "%s: not supported by this driver\n",
+ drive->name);
+ goto failed;
+ }
+
+ idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
+ if (!idkp) {
+ printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
+ drive->name);
+ goto failed;
+ }
+
+ g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
+ if (!g)
+ goto out_free_idkp;
+
+ ide_init_disk(g, drive);
+
+ kref_init(&idkp->kref);
+
+ idkp->drive = drive;
+ idkp->driver = &ide_gd_driver;
+ idkp->disk = g;
+
+ g->private_data = &idkp->driver;
+
+ drive->driver_data = idkp;
+ drive->debug_mask = debug_mask;
+ drive->disk_ops = disk_ops;
+
+ disk_ops->setup(drive);
+
+ set_capacity(g, ide_gd_capacity(drive));
+
+ g->minors = IDE_DISK_MINORS;
+ g->driverfs_dev = &drive->gendev;
+ g->flags |= GENHD_FL_EXT_DEVT;
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+ g->flags = GENHD_FL_REMOVABLE;
+ g->fops = &ide_gd_ops;
+ add_disk(g);
+ return 0;
+
+out_free_idkp:
+ kfree(idkp);
+failed:
+ return -ENODEV;
+}
+
+static int __init ide_gd_init(void)
+{
+ printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
+ return driver_register(&ide_gd_driver.gen_driver);
+}
+
+static void __exit ide_gd_exit(void)
+{
+ driver_unregister(&ide_gd_driver.gen_driver);
+}
+
+MODULE_ALIAS("ide:*m-disk*");
+MODULE_ALIAS("ide-disk");
+MODULE_ALIAS("ide:*m-floppy*");
+MODULE_ALIAS("ide-floppy");
+module_init(ide_gd_init);
+module_exit(ide_gd_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");
diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h
new file mode 100644
index 00000000000..7d3d101713e
--- /dev/null
+++ b/drivers/ide/ide-gd.h
@@ -0,0 +1,44 @@
+#ifndef __IDE_GD_H
+#define __IDE_GD_H
+
+#define DRV_NAME "ide-gd"
+#define PFX DRV_NAME ": "
+
+/* define to see debug info */
+#define IDE_GD_DEBUG_LOG 0
+
+#if IDE_GD_DEBUG_LOG
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#else
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
+#endif
+
+struct ide_disk_obj {
+ ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
+ struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
+
+ /* Last failed packet command */
+ struct ide_atapi_pc *failed_pc;
+ /* used for blk_{fs,pc}_request() requests */
+ struct ide_atapi_pc queued_pc;
+
+ /* Last error information */
+ u8 sense_key, asc, ascq;
+
+ int progress_indication;
+
+ /* Device information */
+ /* Current format */
+ int blocks, block_size, bs_factor;
+ /* Last format capacity descriptor */
+ u8 cap_desc[8];
+ /* Copy of the flexible disk page */
+ u8 flexible_disk_page[32];
+};
+
+sector_t ide_gd_capacity(ide_drive_t *);
+
+#endif /* __IDE_GD_H */
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/ide-h8300.c
index e2cdd2e9cde..e2cdd2e9cde 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/ide-h8300.c
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index a90945f4979..fcde16bb53a 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -240,8 +240,7 @@ static int generic_drive_reset(ide_drive_t *drive)
return ret;
}
-int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
- struct block_device *bdev,
+int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,
unsigned int cmd, unsigned long arg)
{
int err;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b762deb2dac..bb7a1ed8094 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -755,7 +755,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
udelay(1);
SELECT_DRIVE(drive);
- SELECT_MASK(drive, 0);
+ SELECT_MASK(drive, 1);
udelay(1);
tp_ops->set_irq(hwif, 0);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/ide-pci-generic.c
index 474f96a7c07..474f96a7c07 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/ide-pci-generic.c
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 19f8c7770a2..1649ea54f76 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -208,6 +208,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->ready_stat = 0;
if (ata_id_cdb_intr(id))
drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
+ drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
/* we don't do head unloading on ATAPI devices */
drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
return;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index b26926487cc..c31d0dd7a53 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -567,10 +567,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
{
mutex_lock(&ide_setting_mtx);
- drive->settings = driver->settings;
+ drive->settings = driver->proc_devsets(drive);
mutex_unlock(&ide_setting_mtx);
- ide_add_proc_entries(drive->proc, driver->proc, drive);
+ ide_add_proc_entries(drive->proc, driver->proc_entries(drive), drive);
}
EXPORT_SYMBOL(ide_proc_register_driver);
@@ -591,7 +591,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
{
unsigned long flags;
- ide_remove_proc_entries(drive->proc, driver->proc);
+ ide_remove_proc_entries(drive->proc, driver->proc_entries(drive));
mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index d879c7797cd..a2d470eb2b5 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2108,7 +2108,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
/* device lacks locking support according to capabilities page */
if ((caps[6] & 1) == 0)
- drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
if (caps[7] & 0x02)
tape->blk_size = 512;
@@ -2298,6 +2298,16 @@ static ide_proc_entry_t idetape_proc[] = {
{ "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL },
{ NULL, 0, NULL, NULL }
};
+
+static ide_proc_entry_t *ide_tape_proc_entries(ide_drive_t *drive)
+{
+ return idetape_proc;
+}
+
+static const struct ide_proc_devset *ide_tape_proc_devsets(ide_drive_t *drive)
+{
+ return idetape_settings;
+}
#endif
static int ide_tape_probe(ide_drive_t *);
@@ -2315,8 +2325,8 @@ static ide_driver_t idetape_driver = {
.end_request = idetape_end_request,
.error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idetape_proc,
- .settings = idetape_settings,
+ .proc_entries = ide_tape_proc_entries,
+ .proc_devsets = ide_tape_proc_devsets,
#endif
};
@@ -2330,35 +2340,30 @@ static const struct file_operations idetape_fops = {
.release = idetape_chrdev_release,
};
-static int idetape_open(struct inode *inode, struct file *filp)
+static int idetape_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_tape_obj *tape;
+ struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk);
- tape = ide_tape_get(disk);
if (!tape)
return -ENXIO;
return 0;
}
-static int idetape_release(struct inode *inode, struct file *filp)
+static int idetape_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
ide_tape_put(tape);
-
return 0;
}
-static int idetape_ioctl(struct inode *inode, struct file *file,
+static int idetape_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
ide_drive_t *drive = tape->drive;
- int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+ int err = generic_ide_ioctl(drive, bdev, cmd, arg);
if (err == -EINVAL)
err = idetape_blkdev_ioctl(drive, cmd, arg);
return err;
@@ -2368,7 +2373,7 @@ static struct block_device_operations idetape_block_ops = {
.owner = THIS_MODULE,
.open = idetape_open,
.release = idetape_release,
- .ioctl = idetape_ioctl,
+ .locked_ioctl = idetape_ioctl,
};
static int ide_tape_probe(ide_drive_t *drive)
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/ide_arm.c
index f728f2927b5..f728f2927b5 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/ide_arm.c
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/ide_platform.c
index 051b4ab0f35..051b4ab0f35 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/ide_platform.c
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/it8213.c
index 7c2feeb3c5e..7c2feeb3c5e 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/it8213.c
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/it821x.c
index 995e18bb313..995e18bb313 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/it821x.c
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/jmicron.c
index 9a68433cf46..9a68433cf46 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/jmicron.c
diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
deleted file mode 100644
index 6939329f89e..00000000000
--- a/drivers/ide/legacy/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-
-# link order is important here
-
-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
-obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
-obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
-obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
-obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o
-
-obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o
-obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o
-obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o
-obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o
-obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o
-
-ifeq ($(CONFIG_BLK_DEV_IDECS), m)
- obj-m += ide-cs.o
-endif
-
-ifeq ($(CONFIG_BLK_DEV_PLATFORM), m)
- obj-m += ide_platform.o
-endif
-
-EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/macide.c
index 43f97cc1d30..43f97cc1d30 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/macide.c
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile
deleted file mode 100644
index 5873fa0b876..00000000000
--- a/drivers/ide/mips/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
-
-EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/ns87415.c
index 13789060f40..13789060f40 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/ns87415.c
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/opti621.c
index 6048eda3cd6..6048eda3cd6 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/opti621.c
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index 122ed3c072f..122ed3c072f 100644
--- a/drivers/ide/arm/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
deleted file mode 100644
index 02e6ee7d751..00000000000
--- a/drivers/ide/pci/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-
-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o
-obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o
-obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o
-obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o
-obj-$(CONFIG_BLK_DEV_CELLEB) += scc_pata.o
-obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
-obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
-obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
-obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o
-obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o
-obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o
-obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o
-obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
-obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
-obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o
-obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o
-obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o
-obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
-obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
-obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o
-obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o
-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o
-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
-obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += sgiioc4.o
-obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
-obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
-obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o
-obj-$(CONFIG_BLK_DEV_TC86C001) += tc86c001.o
-obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o
-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
-obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
-
-# Must appear at the end of the block
-obj-$(CONFIG_BLK_DEV_GENERIC) += ide-pci-generic.o
-ide-pci-generic-y += generic.o
-
-ifeq ($(CONFIG_BLK_DEV_CMD640), m)
- obj-m += cmd640.o
-endif
-
-EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
deleted file mode 100644
index fb1a3aa57f0..00000000000
--- a/drivers/ide/pci/hpt34x.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *
- * May be copied or modified under the terms of the GNU General Public License
- *
- *
- * 00:12.0 Unknown mass storage controller:
- * Triones Technologies, Inc.
- * Unknown device 0003 (rev 01)
- *
- * hde: UDMA 2 (0x0000 0x0002) (0x0000 0x0010)
- * hdf: UDMA 2 (0x0002 0x0012) (0x0010 0x0030)
- * hde: DMA 2 (0x0000 0x0002) (0x0000 0x0010)
- * hdf: DMA 2 (0x0002 0x0012) (0x0010 0x0030)
- * hdg: DMA 1 (0x0012 0x0052) (0x0030 0x0070)
- * hdh: DMA 1 (0x0052 0x0252) (0x0070 0x00f0)
- *
- * ide-pci.c reference
- *
- * Since there are two cards that report almost identically,
- * the only discernable difference is the values reported in pcicmd.
- * Booting-BIOS card or HPT363 :: pcicmd == 0x07
- * Non-bootable card or HPT343 :: pcicmd == 0x05
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#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)
-{
- struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
- u8 hi_speed, lo_speed;
-
- hi_speed = speed >> 4;
- lo_speed = speed & 0x0f;
-
- if (hi_speed & 7) {
- hi_speed = (hi_speed & 4) ? 0x01 : 0x10;
- } else {
- lo_speed <<= 5;
- lo_speed >>= 5;
- }
-
- pci_read_config_dword(dev, 0x44, &reg1);
- pci_read_config_dword(dev, 0x48, &reg2);
- tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
- tmp2 = ((hi_speed << drive->dn) | (reg2 & ~(0x11 << drive->dn)));
- pci_write_config_dword(dev, 0x44, tmp1);
- pci_write_config_dword(dev, 0x48, tmp2);
-
-#if HPT343_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \
- " (0x%02x 0x%02x)\n",
- drive->name, ide_xfer_verbose(speed),
- drive->dn, reg1, tmp1, reg2, tmp2,
- hi_speed, lo_speed);
-#endif /* HPT343_DEBUG_DRIVE_INFO */
-}
-
-static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
- hpt34x_set_mode(drive, XFER_PIO_0 + pio);
-}
-
-/*
- * If the BIOS does not set the IO base addaress to XX00, 343 will fail.
- */
-#define HPT34X_PCI_INIT_REG 0x80
-
-static unsigned int init_chipset_hpt34x(struct pci_dev *dev)
-{
- int i = 0;
- unsigned long hpt34xIoBase = pci_resource_start(dev, 4);
- unsigned long hpt_addr[4] = { 0x20, 0x34, 0x28, 0x3c };
- unsigned long hpt_addr_len[4] = { 7, 3, 7, 3 };
- u16 cmd;
- unsigned long flags;
-
- local_irq_save(flags);
-
- pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00);
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
-
- if (cmd & PCI_COMMAND_MEMORY)
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
- else
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
-
- /*
- * Since 20-23 can be assigned and are R/W, we correct them.
- */
- pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO);
- for(i=0; i<4; i++) {
- dev->resource[i].start = (hpt34xIoBase + hpt_addr[i]);
- dev->resource[i].end = dev->resource[i].start + hpt_addr_len[i];
- dev->resource[i].flags = IORESOURCE_IO;
- pci_write_config_dword(dev,
- (PCI_BASE_ADDRESS_0 + (i * 4)),
- dev->resource[i].start);
- }
- pci_write_config_word(dev, PCI_COMMAND, cmd);
-
- local_irq_restore(flags);
-
- return dev->irq;
-}
-
-static const struct ide_port_ops hpt34x_port_ops = {
- .set_pio_mode = hpt34x_set_pio_mode,
- .set_dma_mode = hpt34x_set_mode,
-};
-
-#define IDE_HFLAGS_HPT34X \
- (IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_NO_DSC | \
- IDE_HFLAG_NO_AUTODMA)
-
-static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
- { /* 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: HPT345 */
- .name = DRV_NAME,
- .init_chipset = init_chipset_hpt34x,
- .port_ops = &hpt34x_port_ops,
- .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
- .pio_mask = ATA_PIO5,
-#ifdef CONFIG_HPT34X_AUTODMA
- .swdma_mask = ATA_SWDMA2,
- .mwdma_mask = ATA_MWDMA2,
- .udma_mask = ATA_UDMA2,
-#endif
- }
-};
-
-static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
- const struct ide_port_info *d;
- u16 pcicmd = 0;
-
- pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
-
- d = &hpt34x_chipsets[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
-
- return ide_pci_init_one(dev, d, NULL);
-}
-
-static const struct pci_device_id hpt34x_pci_tbl[] = {
- { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), 0 },
- { 0, },
-};
-MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
-
-static struct pci_driver hpt34x_pci_driver = {
- .name = "HPT34x_IDE",
- .id_table = hpt34x_pci_tbl,
- .probe = hpt34x_init_one,
- .remove = ide_pci_remove,
- .suspend = ide_pci_suspend,
- .resume = ide_pci_resume,
-};
-
-static int __init hpt34x_ide_init(void)
-{
- return ide_pci_register_driver(&hpt34x_pci_driver);
-}
-
-static void __exit hpt34x_ide_exit(void)
-{
- pci_unregister_driver(&hpt34x_pci_driver);
-}
-
-module_init(hpt34x_ide_init);
-module_exit(hpt34x_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for Highpoint 34x IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index 211ae46e3e0..211ae46e3e0 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 799557c25ee..799557c25ee 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/piix.c
index d63f9fdca76..d63f9fdca76 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/piix.c
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/pmac.c
index 2e19d629853..2e19d629853 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/pmac.c
diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
deleted file mode 100644
index 74e52adcdf4..00000000000
--- a/drivers/ide/ppc/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-
-obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/q40ide.c
index 4af4a8ce4cd..4af4a8ce4cd 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/q40ide.c
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/qd65xx.c
index bc27c7aba93..bc27c7aba93 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/qd65xx.c
diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/qd65xx.h
index c83dea85e62..c83dea85e62 100644
--- a/drivers/ide/legacy/qd65xx.h
+++ b/drivers/ide/qd65xx.h
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/rapide.c
index 78d27d9ae43..d5003ca6980 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/rapide.c
@@ -11,7 +11,7 @@
#include <asm/ecard.h>
-static struct const ide_port_info rapide_port_info = {
+static const struct ide_port_info rapide_port_info = {
.host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
};
@@ -97,7 +97,7 @@ static int __init rapide_init(void)
static void __exit rapide_exit(void)
{
- ecard_unregister_driver(&rapide_driver);
+ ecard_remove_driver(&rapide_driver);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/rz1000.c
index 7daf0135cba..7daf0135cba 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/rz1000.c
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/sc1200.c
index f1a8758e3a9..f1a8758e3a9 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/sc1200.c
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/scc_pata.c
index 9ce1d805992..f26aa5d54ef 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/scc_pata.c
@@ -536,10 +536,6 @@ static u8 scc_udma_filter(ide_drive_t *drive)
static int setup_mmio_scc (struct pci_dev *dev, const char *name)
{
- unsigned long ctl_base = pci_resource_start(dev, 0);
- unsigned long dma_base = pci_resource_start(dev, 1);
- unsigned long ctl_size = pci_resource_len(dev, 0);
- unsigned long dma_size = pci_resource_len(dev, 1);
void __iomem *ctl_addr;
void __iomem *dma_addr;
int i, ret;
@@ -557,10 +553,12 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
return ret;
}
- if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
+ ctl_addr = pci_ioremap_bar(dev, 0);
+ if (!ctl_addr)
goto fail_0;
- if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
+ dma_addr = pci_ioremap_bar(dev, 1);
+ if (!dma_addr)
goto fail_1;
pci_set_master(dev);
@@ -617,7 +615,6 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
unsigned long intmask_port;
unsigned long mode_port;
unsigned long ecmode_port;
- unsigned long dma_status_port;
u32 reg = 0;
struct scc_ports *ports;
int rc;
@@ -637,7 +634,6 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
intmask_port = dma_base + 0x010;
mode_port = ctl_base + 0x024;
ecmode_port = ctl_base + 0xf00;
- dma_status_port = dma_base + 0x004;
/* controller initialization */
reg = 0;
@@ -843,8 +839,6 @@ static u8 scc_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_scc(ide_hwif_t *hwif)
{
- struct scc_ports *ports = ide_get_hwifdata(hwif);
-
/* PTERADD */
out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/serverworks.c
index 437bc919daf..437bc919daf 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/serverworks.c
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/sgiioc4.c
index dd634541ce3..7defa0ae201 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/sgiioc4.c
@@ -101,18 +101,8 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
for (i = 0; i <= 7; i++)
hw->io_ports_array[i] = reg + i * 4;
- if (ctrl_port)
- hw->io_ports.ctl_addr = ctrl_port;
-
- if (irq_port)
- hw->io_ports.irq_addr = irq_port;
-}
-
-static void
-sgiioc4_maskproc(ide_drive_t * drive, int mask)
-{
- writeb(ATA_DEVCTL_OBS | (mask ? 2 : 0),
- (void __iomem *)drive->hwif->io_ports.ctl_addr);
+ hw->io_ports.ctl_addr = ctrl_port;
+ hw->io_ports.irq_addr = irq_port;
}
static int
@@ -310,16 +300,14 @@ 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 */
- if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
- unsigned long other_ir = port - 0x110;
- unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
+ if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
+ unsigned long other_ir = port - 0x110;
+ unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
- /* Clear the Interrupt, Error bits on the IOC4 */
- if (intr_reg & 0x03) {
- writel(0x03, (void __iomem *) other_ir);
- intr_reg = (u32) readl((void __iomem *) other_ir);
- }
+ /* Clear the Interrupt, Error bits on the IOC4 */
+ if (intr_reg & 0x03) {
+ writel(0x03, (void __iomem *) other_ir);
+ intr_reg = (u32) readl((void __iomem *) other_ir);
}
}
@@ -332,13 +320,9 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
- void __iomem *virt_dma_base;
int num_ports = sizeof (ioc4_dma_regs_t);
void *pad;
- if (dma_base == 0)
- return -1;
-
printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
@@ -348,14 +332,8 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
return -1;
}
- virt_dma_base = ioremap(dma_base, num_ports);
- if (virt_dma_base == NULL) {
- printk(KERN_ERR "%s(%s) -- ERROR: unable to map addresses "
- "0x%lx to 0x%lx\n", __func__, hwif->name,
- dma_base, dma_base + num_ports - 1);
- goto dma_remap_failure;
- }
- hwif->dma_base = (unsigned long) virt_dma_base;
+ hwif->dma_base = (unsigned long)hwif->io_ports.irq_addr +
+ IOC4_DMA_OFFSET;
hwif->sg_max_nents = IOC4_PRD_ENTRIES;
@@ -379,9 +357,6 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
dma_pci_alloc_failure:
- iounmap(virt_dma_base);
-
-dma_remap_failure:
release_mem_region(dma_base, num_ports);
return -1;
@@ -563,8 +538,6 @@ static const struct ide_port_ops sgiioc4_port_ops = {
.set_dma_mode = sgiioc4_set_dma_mode,
/* reset DMA engine, clear IRQs */
.resetproc = sgiioc4_resetproc,
- /* mask on/off NIEN register */
- .maskproc = sgiioc4_maskproc,
};
static const struct ide_dma_ops sgiioc4_dma_ops = {
@@ -594,14 +567,12 @@ 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;
- 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);
- virt_base = ioremap(bar0, pci_resource_len(dev, 0));
+ virt_base = pci_ioremap_bar(dev, 0);
if (virt_base == NULL) {
printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
DRV_NAME, bar0);
@@ -617,7 +588,8 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
"already in use\n", DRV_NAME, pci_name(dev),
cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
- return -EBUSY;
+ rc = -EBUSY;
+ goto req_mem_rgn_err;
}
/* Initialize the IO registers */
@@ -630,21 +602,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
/* Initializing chipset IRQ Registers */
writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
- host = ide_host_alloc(&d, hws);
- if (host == NULL) {
- rc = -ENOMEM;
- goto err;
- }
-
- rc = ide_host_register(host, &d, hws);
- if (rc)
- goto err_free;
+ rc = ide_host_add(&sgiioc4_port_info, hws, NULL);
+ if (!rc)
+ return 0;
- return 0;
-err_free:
- ide_host_free(host);
-err:
release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
+req_mem_rgn_err:
iounmap(virt_base);
return rc;
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/siimage.c
index eb4faf92c57..c3107df7773 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/siimage.c
@@ -784,7 +784,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
"available\n", pci_name(dev));
} else {
- ioaddr = ioremap(bar5, barsize);
+ ioaddr = pci_ioremap_bar(dev, 5);
if (ioaddr == NULL)
release_mem_region(bar5, barsize);
}
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/sis5513.c
index ad32e18c5ba..ad32e18c5ba 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/sis5513.c
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/sl82c105.c
index 84dc33602ff..84dc33602ff 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/sl82c105.c
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/slc90e66.c
index 0f759e4ed77..0f759e4ed77 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/slc90e66.c
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/tc86c001.c
index 93e2cce4b29..93e2cce4b29 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/tc86c001.c
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/triflex.c
index b6ff40336aa..b6ff40336aa 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/triflex.c
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/trm290.c
index 75ea6152656..75ea6152656 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/trm290.c
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
new file mode 100644
index 00000000000..fa660f931a1
--- /dev/null
+++ b/drivers/ide/tx4938ide.c
@@ -0,0 +1,310 @@
+/*
+ * TX4938 internal IDE driver
+ * Based on tx4939ide.c.
+ *
+ * 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.
+ *
+ * (C) Copyright TOSHIBA CORPORATION 2005-2007
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <asm/txx9/tx4938.h>
+
+static void tx4938ide_tune_ebusc(unsigned int ebus_ch,
+ unsigned int gbus_clock,
+ u8 pio)
+{
+ struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+ u64 cr = __raw_readq(&tx4938_ebuscptr->cr[ebus_ch]);
+ unsigned int sp = (cr >> 4) & 3;
+ unsigned int clock = gbus_clock / (4 - sp);
+ unsigned int cycle = 1000000000 / clock;
+ unsigned int wt, shwt;
+
+ /* Minimum DIOx- active time */
+ wt = DIV_ROUND_UP(t->act8b, cycle) - 2;
+ /* IORDY setup time: 35ns */
+ wt = max(wt, DIV_ROUND_UP(35, cycle));
+ /* actual wait-cycle is max(wt & ~1, 1) */
+ if (wt > 2 && (wt & 1))
+ wt++;
+ wt &= ~1;
+ /* Address-valid to DIOR/DIOW setup */
+ shwt = DIV_ROUND_UP(t->setup, cycle);
+
+ pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d\n",
+ ebus_ch, cycle, wt, shwt);
+
+ __raw_writeq((cr & ~(0x3f007ull)) | (wt << 12) | shwt,
+ &tx4938_ebuscptr->cr[ebus_ch]);
+}
+
+static void tx4938ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct tx4938ide_platform_info *pdata = hwif->dev->platform_data;
+ u8 safe = pio;
+ ide_drive_t *pair;
+
+ pair = ide_get_pair_dev(drive);
+ if (pair)
+ safe = min(safe, ide_get_best_pio_mode(pair, 255, 5));
+ tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, safe);
+}
+
+#ifdef __BIG_ENDIAN
+
+/* custom iops (independent from SWAP_IO_SPACE) */
+static u8 tx4938ide_inb(unsigned long port)
+{
+ return __raw_readb((void __iomem *)port);
+}
+
+static void tx4938ide_outb(u8 value, unsigned long port)
+{
+ __raw_writeb(value, (void __iomem *)port);
+}
+
+static void tx4938ide_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;
+ struct ide_taskfile *tf = &task->tf;
+ u8 HIHI = task->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF;
+
+ if (task->tf_flags & IDE_TFLAG_FLAGGED)
+ HIHI = 0xFF;
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+ u16 data = (tf->hob_data << 8) | tf->data;
+
+ /* no endian swap */
+ __raw_writew(data, (void __iomem *)io_ports->data_addr);
+ }
+
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+ tx4938ide_outb(tf->hob_feature, io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+ tx4938ide_outb(tf->hob_nsect, io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+ tx4938ide_outb(tf->hob_lbal, io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+ tx4938ide_outb(tf->hob_lbam, io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+ tx4938ide_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+ tx4938ide_outb(tf->feature, io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+ tx4938ide_outb(tf->nsect, io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+ tx4938ide_outb(tf->lbal, io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+ tx4938ide_outb(tf->lbam, io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+ tx4938ide_outb(tf->lbah, io_ports->lbah_addr);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+ tx4938ide_outb((tf->device & HIHI) | drive->select,
+ io_ports->device_addr);
+}
+
+static void tx4938ide_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;
+ struct ide_taskfile *tf = &task->tf;
+
+ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+ u16 data;
+
+ /* no endian swap */
+ data = __raw_readw((void __iomem *)io_ports->data_addr);
+ tf->data = data & 0xff;
+ tf->hob_data = (data >> 8) & 0xff;
+ }
+
+ /* be sure we're looking at the low order bits */
+ tx4938ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = tx4938ide_inb(io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+ tf->nsect = tx4938ide_inb(io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+ tf->lbal = tx4938ide_inb(io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+ tf->lbam = tx4938ide_inb(io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+ tf->lbah = tx4938ide_inb(io_ports->lbah_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+ tf->device = tx4938ide_inb(io_ports->device_addr);
+
+ if (task->tf_flags & IDE_TFLAG_LBA48) {
+ tx4938ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+ tf->hob_feature =
+ tx4938ide_inb(io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+ tf->hob_nsect = tx4938ide_inb(io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+ tf->hob_lbal = tx4938ide_inb(io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+ tf->hob_lbam = tx4938ide_inb(io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+ tf->hob_lbah = tx4938ide_inb(io_ports->lbah_addr);
+ }
+}
+
+static void tx4938ide_input_data_swap(ide_drive_t *drive, struct request *rq,
+ void *buf, unsigned int len)
+{
+ unsigned long port = drive->hwif->io_ports.data_addr;
+ unsigned short *ptr = buf;
+ unsigned int count = (len + 1) / 2;
+
+ while (count--)
+ *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port));
+ __ide_flush_dcache_range((unsigned long)buf, count * 2);
+}
+
+static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq,
+ void *buf, unsigned int len)
+{
+ unsigned long port = drive->hwif->io_ports.data_addr;
+ unsigned short *ptr = buf;
+ unsigned int count = (len + 1) / 2;
+
+ while (count--) {
+ __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port);
+ ptr++;
+ }
+ __ide_flush_dcache_range((unsigned long)buf, count * 2);
+}
+
+static const struct ide_tp_ops tx4938ide_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 = tx4938ide_tf_load,
+ .tf_read = tx4938ide_tf_read,
+
+ .input_data = tx4938ide_input_data_swap,
+ .output_data = tx4938ide_output_data_swap,
+};
+
+#endif /* __BIG_ENDIAN */
+
+static const struct ide_port_ops tx4938ide_port_ops = {
+ .set_pio_mode = tx4938ide_set_pio_mode,
+};
+
+static const struct ide_port_info tx4938ide_port_info __initdata = {
+ .port_ops = &tx4938ide_port_ops,
+#ifdef __BIG_ENDIAN
+ .tp_ops = &tx4938ide_tp_ops,
+#endif
+ .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO5,
+};
+
+static int __init tx4938ide_probe(struct platform_device *pdev)
+{
+ hw_regs_t hw;
+ hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+ struct ide_host *host;
+ struct resource *res;
+ struct tx4938ide_platform_info *pdata = pdev->dev.platform_data;
+ int irq, ret, i;
+ unsigned long mapbase;
+ struct ide_port_info d = tx4938ide_port_info;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENODEV;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ res->end - res->start + 1, "tx4938ide"))
+ return -EBUSY;
+ mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start + 1);
+ if (!mapbase)
+ return -EBUSY;
+
+ memset(&hw, 0, sizeof(hw));
+ if (pdata->ioport_shift) {
+ unsigned long port = mapbase;
+
+ hw.io_ports_array[0] = port;
+#ifdef __BIG_ENDIAN
+ port++;
+#endif
+ for (i = 1; i <= 7; i++)
+ hw.io_ports_array[i] =
+ port + (i << pdata->ioport_shift);
+ hw.io_ports.ctl_addr =
+ port + 0x10000 + (6 << pdata->ioport_shift);
+ } else
+ ide_std_init_ports(&hw, mapbase, mapbase + 0x10006);
+ hw.irq = irq;
+ hw.dev = &pdev->dev;
+
+ pr_info("TX4938 IDE interface (base %#lx, irq %d)\n", mapbase, hw.irq);
+ if (pdata->gbus_clock)
+ tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0);
+ else
+ d.port_ops = NULL;
+ ret = ide_host_add(&d, hws, &host);
+ if (ret)
+ return ret;
+ platform_set_drvdata(pdev, host);
+ return 0;
+}
+
+static int __exit tx4938ide_remove(struct platform_device *pdev)
+{
+ struct ide_host *host = platform_get_drvdata(pdev);
+
+ ide_host_remove(host);
+ return 0;
+}
+
+static struct platform_driver tx4938ide_driver = {
+ .driver = {
+ .name = "tx4938ide",
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(tx4938ide_remove),
+};
+
+static int __init tx4938ide_init(void)
+{
+ return platform_driver_probe(&tx4938ide_driver, tx4938ide_probe);
+}
+
+static void __exit tx4938ide_exit(void)
+{
+ platform_driver_unregister(&tx4938ide_driver);
+}
+
+module_init(tx4938ide_init);
+module_exit(tx4938ide_exit);
+
+MODULE_DESCRIPTION("TX4938 internal IDE driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tx4938ide");
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
new file mode 100644
index 00000000000..bafb7d1a22e
--- /dev/null
+++ b/drivers/ide/tx4939ide.c
@@ -0,0 +1,754 @@
+/*
+ * TX4939 internal IDE driver
+ * Based on RBTX49xx patch from CELF patch archive.
+ *
+ * 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.
+ *
+ * (C) Copyright TOSHIBA CORPORATION 2005-2007
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+
+#define MODNAME "tx4939ide"
+
+/* ATA Shadow Registers (8-bit except for Data which is 16-bit) */
+#define TX4939IDE_Data 0x000
+#define TX4939IDE_Error_Feature 0x001
+#define TX4939IDE_Sec 0x002
+#define TX4939IDE_LBA0 0x003
+#define TX4939IDE_LBA1 0x004
+#define TX4939IDE_LBA2 0x005
+#define TX4939IDE_DevHead 0x006
+#define TX4939IDE_Stat_Cmd 0x007
+#define TX4939IDE_AltStat_DevCtl 0x402
+/* H/W DMA Registers */
+#define TX4939IDE_DMA_Cmd 0x800 /* 8-bit */
+#define TX4939IDE_DMA_Stat 0x802 /* 8-bit */
+#define TX4939IDE_PRD_Ptr 0x804 /* 32-bit */
+/* ATA100 CORE Registers (16-bit) */
+#define TX4939IDE_Sys_Ctl 0xc00
+#define TX4939IDE_Xfer_Cnt_1 0xc08
+#define TX4939IDE_Xfer_Cnt_2 0xc0a
+#define TX4939IDE_Sec_Cnt 0xc10
+#define TX4939IDE_Start_Lo_Addr 0xc18
+#define TX4939IDE_Start_Up_Addr 0xc20
+#define TX4939IDE_Add_Ctl 0xc28
+#define TX4939IDE_Lo_Burst_Cnt 0xc30
+#define TX4939IDE_Up_Burst_Cnt 0xc38
+#define TX4939IDE_PIO_Addr 0xc88
+#define TX4939IDE_H_Rst_Tim 0xc90
+#define TX4939IDE_Int_Ctl 0xc98
+#define TX4939IDE_Pkt_Cmd 0xcb8
+#define TX4939IDE_Bxfer_Cnt_Hi 0xcc0
+#define TX4939IDE_Bxfer_Cnt_Lo 0xcc8
+#define TX4939IDE_Dev_TErr 0xcd0
+#define TX4939IDE_Pkt_Xfer_Ctl 0xcd8
+#define TX4939IDE_Start_TAddr 0xce0
+
+/* bits for Int_Ctl */
+#define TX4939IDE_INT_ADDRERR 0x80
+#define TX4939IDE_INT_REACHMUL 0x40
+#define TX4939IDE_INT_DEVTIMING 0x20
+#define TX4939IDE_INT_UDMATERM 0x10
+#define TX4939IDE_INT_TIMER 0x08
+#define TX4939IDE_INT_BUSERR 0x04
+#define TX4939IDE_INT_XFEREND 0x02
+#define TX4939IDE_INT_HOST 0x01
+
+#define TX4939IDE_IGNORE_INTS \
+ (TX4939IDE_INT_ADDRERR | TX4939IDE_INT_REACHMUL | \
+ TX4939IDE_INT_DEVTIMING | TX4939IDE_INT_UDMATERM | \
+ TX4939IDE_INT_TIMER | TX4939IDE_INT_XFEREND)
+
+#ifdef __BIG_ENDIAN
+#define tx4939ide_swizzlel(a) ((a) ^ 4)
+#define tx4939ide_swizzlew(a) ((a) ^ 6)
+#define tx4939ide_swizzleb(a) ((a) ^ 7)
+#else
+#define tx4939ide_swizzlel(a) (a)
+#define tx4939ide_swizzlew(a) (a)
+#define tx4939ide_swizzleb(a) (a)
+#endif
+
+static u16 tx4939ide_readw(void __iomem *base, u32 reg)
+{
+ return __raw_readw(base + tx4939ide_swizzlew(reg));
+}
+static u8 tx4939ide_readb(void __iomem *base, u32 reg)
+{
+ return __raw_readb(base + tx4939ide_swizzleb(reg));
+}
+static void tx4939ide_writel(u32 val, void __iomem *base, u32 reg)
+{
+ __raw_writel(val, base + tx4939ide_swizzlel(reg));
+}
+static void tx4939ide_writew(u16 val, void __iomem *base, u32 reg)
+{
+ __raw_writew(val, base + tx4939ide_swizzlew(reg));
+}
+static void tx4939ide_writeb(u8 val, void __iomem *base, u32 reg)
+{
+ __raw_writeb(val, base + tx4939ide_swizzleb(reg));
+}
+
+#define TX4939IDE_BASE(hwif) ((void __iomem *)(hwif)->extra_base)
+
+static void tx4939ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ int is_slave = drive->dn;
+ u32 mask, val;
+ u8 safe = pio;
+ ide_drive_t *pair;
+
+ pair = ide_get_pair_dev(drive);
+ if (pair)
+ safe = min(safe, ide_get_best_pio_mode(pair, 255, 4));
+ /*
+ * Update Command Transfer Mode for master/slave and Data
+ * Transfer Mode for this drive.
+ */
+ mask = is_slave ? 0x07f00000 : 0x000007f0;
+ val = ((safe << 8) | (pio << 4)) << (is_slave ? 16 : 0);
+ hwif->select_data = (hwif->select_data & ~mask) | val;
+ /* tx4939ide_tf_load_fixup() will set the Sys_Ctl register */
+}
+
+static void tx4939ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u32 mask, val;
+
+ /* Update Data Transfer Mode for this drive. */
+ if (mode >= XFER_UDMA_0)
+ val = mode - XFER_UDMA_0 + 8;
+ else
+ val = mode - XFER_MW_DMA_0 + 5;
+ if (drive->dn) {
+ mask = 0x00f00000;
+ val <<= 20;
+ } else {
+ mask = 0x000000f0;
+ val <<= 4;
+ }
+ hwif->select_data = (hwif->select_data & ~mask) | val;
+ /* tx4939ide_tf_load_fixup() will set the Sys_Ctl register */
+}
+
+static u16 tx4939ide_check_error_ints(ide_hwif_t *hwif)
+{
+ void __iomem *base = TX4939IDE_BASE(hwif);
+ u16 ctl = tx4939ide_readw(base, TX4939IDE_Int_Ctl);
+
+ if (ctl & TX4939IDE_INT_BUSERR) {
+ /* reset FIFO */
+ u16 sysctl = tx4939ide_readw(base, TX4939IDE_Sys_Ctl);
+
+ tx4939ide_writew(sysctl | 0x4000, base, TX4939IDE_Sys_Ctl);
+ mmiowb();
+ /* wait 12GBUSCLK (typ. 60ns @ GBUS200MHz, max 270ns) */
+ ndelay(270);
+ tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl);
+ }
+ if (ctl & (TX4939IDE_INT_ADDRERR |
+ TX4939IDE_INT_DEVTIMING | TX4939IDE_INT_BUSERR))
+ pr_err("%s: Error interrupt %#x (%s%s%s )\n",
+ hwif->name, ctl,
+ ctl & TX4939IDE_INT_ADDRERR ? " Address-Error" : "",
+ ctl & TX4939IDE_INT_DEVTIMING ? " DEV-Timing" : "",
+ ctl & TX4939IDE_INT_BUSERR ? " Bus-Error" : "");
+ return ctl;
+}
+
+static void tx4939ide_clear_irq(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif;
+ void __iomem *base;
+ u16 ctl;
+
+ /*
+ * tx4939ide_dma_test_irq() and tx4939ide_dma_end() do all job
+ * for DMA case.
+ */
+ if (drive->waiting_for_dma)
+ return;
+ hwif = drive->hwif;
+ base = TX4939IDE_BASE(hwif);
+ ctl = tx4939ide_check_error_ints(hwif);
+ tx4939ide_writew(ctl, base, TX4939IDE_Int_Ctl);
+}
+
+static u8 tx4939ide_cable_detect(ide_hwif_t *hwif)
+{
+ void __iomem *base = TX4939IDE_BASE(hwif);
+
+ return tx4939ide_readw(base, TX4939IDE_Sys_Ctl) & 0x2000 ?
+ ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+#ifdef __BIG_ENDIAN
+static void tx4939ide_dma_host_set(ide_drive_t *drive, int on)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 unit = drive->dn;
+ void __iomem *base = TX4939IDE_BASE(hwif);
+ u8 dma_stat = tx4939ide_readb(base, TX4939IDE_DMA_Stat);
+
+ if (on)
+ dma_stat |= (1 << (5 + unit));
+ else
+ dma_stat &= ~(1 << (5 + unit));
+
+ tx4939ide_writeb(dma_stat, base, TX4939IDE_DMA_Stat);
+}
+#else
+#define tx4939ide_dma_host_set ide_dma_host_set
+#endif
+
+static u8 tx4939ide_clear_dma_status(void __iomem *base)
+{
+ u8 dma_stat;
+
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = tx4939ide_readb(base, TX4939IDE_DMA_Stat);
+ /* clear INTR & ERROR flags */
+ tx4939ide_writeb(dma_stat | ATA_DMA_INTR | ATA_DMA_ERR, base,
+ TX4939IDE_DMA_Stat);
+ /* recover intmask cleared by writing to bit2 of DMA_Stat */
+ tx4939ide_writew(TX4939IDE_IGNORE_INTS << 8, base, TX4939IDE_Int_Ctl);
+ return dma_stat;
+}
+
+#ifdef __BIG_ENDIAN
+/* custom ide_build_dmatable to handle swapped layout */
+static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u32 *table = (u32 *)hwif->dmatable_cpu;
+ unsigned int count = 0;
+ int i;
+ struct scatterlist *sg;
+
+ hwif->sg_nents = ide_build_sglist(drive, rq);
+ if (hwif->sg_nents == 0)
+ return 0;
+
+ for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+ u32 cur_addr, cur_len, bcount;
+
+ cur_addr = sg_dma_address(sg);
+ cur_len = sg_dma_len(sg);
+
+ /*
+ * Fill in the DMA table, without crossing any 64kB boundaries.
+ */
+
+ while (cur_len) {
+ if (count++ >= PRD_ENTRIES)
+ goto use_pio_instead;
+
+ bcount = 0x10000 - (cur_addr & 0xffff);
+ if (bcount > cur_len)
+ bcount = cur_len;
+ *table++ = bcount & 0xffff;
+ *table++ = cur_addr;
+ cur_addr += bcount;
+ cur_len -= bcount;
+ }
+ }
+
+ if (count) {
+ *(table - 2) |= 0x80000000;
+ return count;
+ }
+
+use_pio_instead:
+ printk(KERN_ERR "%s: %s\n", drive->name,
+ count ? "DMA table too small" : "empty DMA table?");
+
+ ide_destroy_dmatable(drive);
+
+ return 0; /* revert to PIO for this request */
+}
+#else
+#define tx4939ide_build_dmatable ide_build_dmatable
+#endif
+
+static int tx4939ide_dma_setup(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ void __iomem *base = TX4939IDE_BASE(hwif);
+ struct request *rq = hwif->hwgroup->rq;
+ u8 reading;
+ int nent;
+
+ if (rq_data_dir(rq))
+ reading = 0;
+ else
+ reading = ATA_DMA_WR;
+
+ /* fall back to PIO! */
+ nent = tx4939ide_build_dmatable(drive, rq);
+ if (!nent) {
+ ide_map_sg(drive, rq);
+ return 1;
+ }
+
+ /* PRD table */
+ tx4939ide_writel(hwif->dmatable_dma, base, TX4939IDE_PRD_Ptr);
+
+ /* specify r/w */
+ tx4939ide_writeb(reading, base, TX4939IDE_DMA_Cmd);
+
+ /* clear INTR & ERROR flags */
+ tx4939ide_clear_dma_status(base);
+
+ drive->waiting_for_dma = 1;
+
+ tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ?
+ TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1);
+ tx4939ide_writew(rq->nr_sectors, base, TX4939IDE_Sec_Cnt);
+ return 0;
+}
+
+static int tx4939ide_dma_end(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_stat, dma_cmd;
+ void __iomem *base = TX4939IDE_BASE(hwif);
+ u16 ctl = tx4939ide_readw(base, TX4939IDE_Int_Ctl);
+
+ drive->waiting_for_dma = 0;
+
+ /* get DMA command mode */
+ dma_cmd = tx4939ide_readb(base, TX4939IDE_DMA_Cmd);
+ /* stop DMA */
+ tx4939ide_writeb(dma_cmd & ~ATA_DMA_START, base, TX4939IDE_DMA_Cmd);
+
+ /* read and clear the INTR & ERROR bits */
+ dma_stat = tx4939ide_clear_dma_status(base);
+
+ /* purge DMA mappings */
+ ide_destroy_dmatable(drive);
+ /* verify good DMA status */
+ wmb();
+
+ if ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == 0 &&
+ (ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) ==
+ (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST))
+ /* INT_IDE lost... bug? */
+ return 0;
+ return ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) !=
+ ATA_DMA_INTR) ? 0x10 | dma_stat : 0;
+}
+
+/* returns 1 if DMA IRQ issued, 0 otherwise */
+static int tx4939ide_dma_test_irq(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ void __iomem *base = TX4939IDE_BASE(hwif);
+ u16 ctl, ide_int;
+ u8 dma_stat, stat;
+ int found = 0;
+
+ ctl = tx4939ide_check_error_ints(hwif);
+ ide_int = ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST);
+ switch (ide_int) {
+ case TX4939IDE_INT_HOST:
+ /* On error, XFEREND might not be asserted. */
+ stat = tx4939ide_readb(base, TX4939IDE_AltStat_DevCtl);
+ if ((stat & (ATA_BUSY | ATA_DRQ | ATA_ERR)) == ATA_ERR)
+ found = 1;
+ else
+ /* Wait for XFEREND (Mask HOST and unmask XFEREND) */
+ ctl &= ~TX4939IDE_INT_XFEREND << 8;
+ ctl |= ide_int << 8;
+ break;
+ case TX4939IDE_INT_HOST | TX4939IDE_INT_XFEREND:
+ dma_stat = tx4939ide_readb(base, TX4939IDE_DMA_Stat);
+ if (!(dma_stat & ATA_DMA_INTR))
+ pr_warning("%s: weird interrupt status. "
+ "DMA_Stat %#02x int_ctl %#04x\n",
+ hwif->name, dma_stat, ctl);
+ found = 1;
+ break;
+ }
+ /*
+ * Do not clear XFEREND, HOST now. They will be cleared by
+ * clearing bit2 of DMA_Stat.
+ */
+ ctl &= ~ide_int;
+ tx4939ide_writew(ctl, base, TX4939IDE_Int_Ctl);
+ return found;
+}
+
+static void tx4939ide_init_hwif(ide_hwif_t *hwif)
+{
+ void __iomem *base = TX4939IDE_BASE(hwif);
+
+ /* Soft Reset */
+ tx4939ide_writew(0x8000, base, TX4939IDE_Sys_Ctl);
+ mmiowb();
+ /* at least 20 GBUSCLK (typ. 100ns @ GBUS200MHz, max 450ns) */
+ ndelay(450);
+ tx4939ide_writew(0x0000, base, TX4939IDE_Sys_Ctl);
+ /* mask some interrupts and clear all interrupts */
+ tx4939ide_writew((TX4939IDE_IGNORE_INTS << 8) | 0xff, base,
+ TX4939IDE_Int_Ctl);
+
+ tx4939ide_writew(0x0008, base, TX4939IDE_Lo_Burst_Cnt);
+ tx4939ide_writew(0, base, TX4939IDE_Up_Burst_Cnt);
+}
+
+static int tx4939ide_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+ hwif->dma_base =
+ hwif->extra_base + tx4939ide_swizzleb(TX4939IDE_DMA_Cmd);
+ /*
+ * Note that we cannot use ATA_DMA_TABLE_OFS, ATA_DMA_STATUS
+ * for big endian.
+ */
+ return ide_allocate_dma_engine(hwif);
+}
+
+static void tx4939ide_tf_load_fixup(ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ void __iomem *base = TX4939IDE_BASE(hwif);
+ u16 sysctl = hwif->select_data >> (drive->dn ? 16 : 0);
+
+ /*
+ * Fix ATA100 CORE System Control Register. (The write to the
+ * Device/Head register may write wrong data to the System
+ * Control Register)
+ * While Sys_Ctl is written here, selectproc is not needed.
+ */
+ tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl);
+}
+
+#ifdef __BIG_ENDIAN
+
+static u8 tx4939ide_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ void __iomem *base = TX4939IDE_BASE(hwif);
+
+ return tx4939ide_readb(base, TX4939IDE_DMA_Stat);
+}
+
+/* custom iops (independent from SWAP_IO_SPACE) */
+static u8 tx4939ide_inb(unsigned long port)
+{
+ return __raw_readb((void __iomem *)port);
+}
+
+static void tx4939ide_outb(u8 value, unsigned long port)
+{
+ __raw_writeb(value, (void __iomem *)port);
+}
+
+static void tx4939ide_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;
+ struct ide_taskfile *tf = &task->tf;
+ u8 HIHI = task->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF;
+
+ if (task->tf_flags & IDE_TFLAG_FLAGGED)
+ HIHI = 0xFF;
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+ u16 data = (tf->hob_data << 8) | tf->data;
+
+ /* no endian swap */
+ __raw_writew(data, (void __iomem *)io_ports->data_addr);
+ }
+
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+ tx4939ide_outb(tf->hob_feature, io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+ tx4939ide_outb(tf->hob_nsect, io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+ tx4939ide_outb(tf->hob_lbal, io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+ tx4939ide_outb(tf->hob_lbam, io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+ tx4939ide_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+ tx4939ide_outb(tf->feature, io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+ tx4939ide_outb(tf->nsect, io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+ tx4939ide_outb(tf->lbal, io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+ tx4939ide_outb(tf->lbam, io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+ tx4939ide_outb(tf->lbah, io_ports->lbah_addr);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) {
+ tx4939ide_outb((tf->device & HIHI) | drive->select,
+ io_ports->device_addr);
+ tx4939ide_tf_load_fixup(drive, task);
+ }
+}
+
+static void tx4939ide_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;
+ struct ide_taskfile *tf = &task->tf;
+
+ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+ u16 data;
+
+ /* no endian swap */
+ data = __raw_readw((void __iomem *)io_ports->data_addr);
+ tf->data = data & 0xff;
+ tf->hob_data = (data >> 8) & 0xff;
+ }
+
+ /* be sure we're looking at the low order bits */
+ tx4939ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = tx4939ide_inb(io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+ tf->nsect = tx4939ide_inb(io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+ tf->lbal = tx4939ide_inb(io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+ tf->lbam = tx4939ide_inb(io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+ tf->lbah = tx4939ide_inb(io_ports->lbah_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+ tf->device = tx4939ide_inb(io_ports->device_addr);
+
+ if (task->tf_flags & IDE_TFLAG_LBA48) {
+ tx4939ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+ tf->hob_feature =
+ tx4939ide_inb(io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+ tf->hob_nsect = tx4939ide_inb(io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+ tf->hob_lbal = tx4939ide_inb(io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+ tf->hob_lbam = tx4939ide_inb(io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+ tf->hob_lbah = tx4939ide_inb(io_ports->lbah_addr);
+ }
+}
+
+static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq,
+ void *buf, unsigned int len)
+{
+ unsigned long port = drive->hwif->io_ports.data_addr;
+ unsigned short *ptr = buf;
+ unsigned int count = (len + 1) / 2;
+
+ while (count--)
+ *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port));
+ __ide_flush_dcache_range((unsigned long)buf, count * 2);
+}
+
+static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq,
+ void *buf, unsigned int len)
+{
+ unsigned long port = drive->hwif->io_ports.data_addr;
+ unsigned short *ptr = buf;
+ unsigned int count = (len + 1) / 2;
+
+ while (count--) {
+ __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port);
+ ptr++;
+ }
+ __ide_flush_dcache_range((unsigned long)buf, count * 2);
+}
+
+static const struct ide_tp_ops tx4939ide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = tx4939ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = tx4939ide_tf_load,
+ .tf_read = tx4939ide_tf_read,
+
+ .input_data = tx4939ide_input_data_swap,
+ .output_data = tx4939ide_output_data_swap,
+};
+
+#else /* __LITTLE_ENDIAN */
+
+static void tx4939ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+ ide_tf_load(drive, task);
+ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+ tx4939ide_tf_load_fixup(drive, task);
+}
+
+static const struct ide_tp_ops tx4939ide_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 = tx4939ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
+#endif /* __LITTLE_ENDIAN */
+
+static const struct ide_port_ops tx4939ide_port_ops = {
+ .set_pio_mode = tx4939ide_set_pio_mode,
+ .set_dma_mode = tx4939ide_set_dma_mode,
+ .clear_irq = tx4939ide_clear_irq,
+ .cable_detect = tx4939ide_cable_detect,
+};
+
+static const struct ide_dma_ops tx4939ide_dma_ops = {
+ .dma_host_set = tx4939ide_dma_host_set,
+ .dma_setup = tx4939ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
+ .dma_start = ide_dma_start,
+ .dma_end = tx4939ide_dma_end,
+ .dma_test_irq = tx4939ide_dma_test_irq,
+ .dma_lost_irq = ide_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
+};
+
+static const struct ide_port_info tx4939ide_port_info __initdata = {
+ .init_hwif = tx4939ide_init_hwif,
+ .init_dma = tx4939ide_init_dma,
+ .port_ops = &tx4939ide_port_ops,
+ .dma_ops = &tx4939ide_dma_ops,
+ .tp_ops = &tx4939ide_tp_ops,
+ .host_flags = IDE_HFLAG_MMIO,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+};
+
+static int __init tx4939ide_probe(struct platform_device *pdev)
+{
+ hw_regs_t hw;
+ hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+ struct ide_host *host;
+ struct resource *res;
+ int irq, ret;
+ unsigned long mapbase;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENODEV;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ res->end - res->start + 1, "tx4938ide"))
+ return -EBUSY;
+ mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start + 1);
+ if (!mapbase)
+ return -EBUSY;
+ memset(&hw, 0, sizeof(hw));
+ hw.io_ports.data_addr =
+ mapbase + tx4939ide_swizzlew(TX4939IDE_Data);
+ hw.io_ports.error_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_Error_Feature);
+ hw.io_ports.nsect_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_Sec);
+ hw.io_ports.lbal_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_LBA0);
+ hw.io_ports.lbam_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_LBA1);
+ hw.io_ports.lbah_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_LBA2);
+ hw.io_ports.device_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_DevHead);
+ hw.io_ports.command_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_Stat_Cmd);
+ hw.io_ports.ctl_addr =
+ mapbase + tx4939ide_swizzleb(TX4939IDE_AltStat_DevCtl);
+ hw.irq = irq;
+ hw.dev = &pdev->dev;
+
+ pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq);
+ host = ide_host_alloc(&tx4939ide_port_info, hws);
+ if (!host)
+ return -ENOMEM;
+ /* use extra_base for base address of the all registers */
+ host->ports[0]->extra_base = mapbase;
+ ret = ide_host_register(host, &tx4939ide_port_info, hws);
+ if (ret) {
+ ide_host_free(host);
+ return ret;
+ }
+ platform_set_drvdata(pdev, host);
+ return 0;
+}
+
+static int __exit tx4939ide_remove(struct platform_device *pdev)
+{
+ struct ide_host *host = platform_get_drvdata(pdev);
+
+ ide_host_remove(host);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int tx4939ide_resume(struct platform_device *dev)
+{
+ struct ide_host *host = platform_get_drvdata(dev);
+ ide_hwif_t *hwif = host->ports[0];
+
+ tx4939ide_init_hwif(hwif);
+ return 0;
+}
+#else
+#define tx4939ide_resume NULL
+#endif
+
+static struct platform_driver tx4939ide_driver = {
+ .driver = {
+ .name = MODNAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(tx4939ide_remove),
+ .resume = tx4939ide_resume,
+};
+
+static int __init tx4939ide_init(void)
+{
+ return platform_driver_probe(&tx4939ide_driver, tx4939ide_probe);
+}
+
+static void __exit tx4939ide_exit(void)
+{
+ platform_driver_unregister(&tx4939ide_driver);
+}
+
+module_init(tx4939ide_init);
+module_exit(tx4939ide_exit);
+
+MODULE_DESCRIPTION("TX4939 internal IDE driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tx4939ide");
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/umc8672.c
index 1da076e0c91..1da076e0c91 100644
--- a/drivers/ide/legacy/umc8672.c
+++ b/drivers/ide/umc8672.c
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/via82cxxx.c
index 2a812d3207e..2a812d3207e 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig
new file mode 100644
index 00000000000..108264de0ac
--- /dev/null
+++ b/drivers/idle/Kconfig
@@ -0,0 +1,17 @@
+
+menu "Memory power savings"
+
+config I7300_IDLE_IOAT_CHANNEL
+ bool
+
+config I7300_IDLE
+ tristate "Intel chipset idle memory power saving driver"
+ select I7300_IDLE_IOAT_CHANNEL
+ depends on X86_64 && EXPERIMENTAL
+ help
+ Enable memory power savings when idle with certain Intel server
+ chipsets. The chipset must have I/O AT support, such as the
+ Intel 7300. The power savings depends on the type and quantity of
+ DRAM devices.
+
+endmenu
diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile
new file mode 100644
index 00000000000..5f68fc377e2
--- /dev/null
+++ b/drivers/idle/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_I7300_IDLE) += i7300_idle.o
+
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
new file mode 100644
index 00000000000..fb176f6ef9f
--- /dev/null
+++ b/drivers/idle/i7300_idle.c
@@ -0,0 +1,609 @@
+/*
+ * (C) Copyright 2008 Intel Corporation
+ * Authors:
+ * Andy Henroid <andrew.d.henroid@intel.com>
+ * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ */
+
+/*
+ * Save DIMM power on Intel 7300-based platforms when all CPUs/cores
+ * are idle, using the DIMM thermal throttling capability.
+ *
+ * This driver depends on the Intel integrated DMA controller (I/O AT).
+ * If the driver for I/O AT (drivers/dma/ioatdma*) is also enabled,
+ * this driver should work cooperatively.
+ */
+
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/cpumask.h>
+#include <linux/ktime.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/stop_machine.h>
+#include <linux/i7300_idle.h>
+
+#include <asm/idle.h>
+
+#include "../dma/ioatdma_hw.h"
+#include "../dma/ioatdma_registers.h"
+
+#define I7300_IDLE_DRIVER_VERSION "1.55"
+#define I7300_PRINT "i7300_idle:"
+
+#define MAX_STOP_RETRIES 10
+
+static int debug;
+module_param_named(debug, debug, uint, 0644);
+MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
+
+#define dprintk(fmt, arg...) \
+ do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0)
+
+/*
+ * Value to set THRTLOW to when initiating throttling
+ * 0 = No throttling
+ * 1 = Throttle when > 4 activations per eval window (Maximum throttling)
+ * 2 = Throttle when > 8 activations
+ * 168 = Throttle when > 672 activations (Minimum throttling)
+ */
+#define MAX_THROTTLE_LOW_LIMIT 168
+static uint throttle_low_limit = 1;
+module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644);
+MODULE_PARM_DESC(throttle_low_limit,
+ "Value for THRTLOWLM activation field "
+ "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
+
+/*
+ * simple invocation and duration statistics
+ */
+static unsigned long total_starts;
+static unsigned long total_us;
+
+#ifdef DEBUG
+static unsigned long past_skip;
+#endif
+
+static struct pci_dev *fbd_dev;
+
+static spinlock_t i7300_idle_lock;
+static int i7300_idle_active;
+
+static u8 i7300_idle_thrtctl_saved;
+static u8 i7300_idle_thrtlow_saved;
+static u32 i7300_idle_mc_saved;
+
+static cpumask_t idle_cpumask;
+static ktime_t start_ktime;
+static unsigned long avg_idle_us;
+
+static struct dentry *debugfs_dir;
+
+/* Begin: I/O AT Helper routines */
+
+#define IOAT_CHANBASE(ioat_ctl, chan) (ioat_ctl + 0x80 + 0x80 * chan)
+/* Snoop control (disable snoops when coherency is not important) */
+#define IOAT_DESC_SADDR_SNP_CTL (1UL << 1)
+#define IOAT_DESC_DADDR_SNP_CTL (1UL << 2)
+
+static struct pci_dev *ioat_dev;
+static struct ioat_dma_descriptor *ioat_desc; /* I/O AT desc & data (1 page) */
+static unsigned long ioat_desc_phys;
+static u8 *ioat_iomap; /* I/O AT memory-mapped control regs (aka CB_BAR) */
+static u8 *ioat_chanbase;
+
+/* Start I/O AT memory copy */
+static int i7300_idle_ioat_start(void)
+{
+ u32 err;
+ /* Clear error (due to circular descriptor pointer) */
+ err = readl(ioat_chanbase + IOAT_CHANERR_OFFSET);
+ if (err)
+ writel(err, ioat_chanbase + IOAT_CHANERR_OFFSET);
+
+ writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+ return 0;
+}
+
+/* Stop I/O AT memory copy */
+static void i7300_idle_ioat_stop(void)
+{
+ int i;
+ u64 sts;
+
+ for (i = 0; i < MAX_STOP_RETRIES; i++) {
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+
+ udelay(10);
+
+ sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ if (sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE)
+ break;
+
+ }
+
+ if (i == MAX_STOP_RETRIES) {
+ dprintk("failed to stop I/O AT after %d retries\n",
+ MAX_STOP_RETRIES);
+ }
+}
+
+/* Test I/O AT by copying 1024 byte from 2k to 1k */
+static int __init i7300_idle_ioat_selftest(u8 *ctl,
+ struct ioat_dma_descriptor *desc, unsigned long desc_phys)
+{
+ u64 chan_sts;
+
+ memset(desc, 0, 2048);
+ memset((u8 *) desc + 2048, 0xab, 1024);
+
+ desc[0].size = 1024;
+ desc[0].ctl = 0;
+ desc[0].src_addr = desc_phys + 2048;
+ desc[0].dst_addr = desc_phys + 1024;
+ desc[0].next = 0;
+
+ writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+ writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+
+ udelay(1000);
+
+ chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE) {
+ /* Not complete, reset the channel */
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+ return -1;
+ }
+
+ if (*(u32 *) ((u8 *) desc + 3068) != 0xabababab ||
+ *(u32 *) ((u8 *) desc + 2044) != 0xabababab) {
+ dprintk("Data values src 0x%x, dest 0x%x, memset 0x%x\n",
+ *(u32 *) ((u8 *) desc + 2048),
+ *(u32 *) ((u8 *) desc + 1024),
+ *(u32 *) ((u8 *) desc + 3072));
+ return -1;
+ }
+ return 0;
+}
+
+static struct device dummy_dma_dev = {
+ .bus_id = "fallback device",
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .dma_mask = &dummy_dma_dev.coherent_dma_mask,
+};
+
+/* Setup and initialize I/O AT */
+/* This driver needs I/O AT as the throttling takes effect only when there is
+ * some memory activity. We use I/O AT to set up a dummy copy, while all CPUs
+ * go idle and memory is throttled.
+ */
+static int __init i7300_idle_ioat_init(void)
+{
+ u8 ver, chan_count, ioat_chan;
+ u16 chan_ctl;
+
+ ioat_iomap = (u8 *) ioremap_nocache(pci_resource_start(ioat_dev, 0),
+ pci_resource_len(ioat_dev, 0));
+
+ if (!ioat_iomap) {
+ printk(KERN_ERR I7300_PRINT "failed to map I/O AT registers\n");
+ goto err_ret;
+ }
+
+ ver = readb(ioat_iomap + IOAT_VER_OFFSET);
+ if (ver != IOAT_VER_1_2) {
+ printk(KERN_ERR I7300_PRINT "unknown I/O AT version (%u.%u)\n",
+ ver >> 4, ver & 0xf);
+ goto err_unmap;
+ }
+
+ chan_count = readb(ioat_iomap + IOAT_CHANCNT_OFFSET);
+ if (!chan_count) {
+ printk(KERN_ERR I7300_PRINT "unexpected # of I/O AT channels "
+ "(%u)\n",
+ chan_count);
+ goto err_unmap;
+ }
+
+ ioat_chan = chan_count - 1;
+ ioat_chanbase = IOAT_CHANBASE(ioat_iomap, ioat_chan);
+
+ chan_ctl = readw(ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+ if (chan_ctl & IOAT_CHANCTRL_CHANNEL_IN_USE) {
+ printk(KERN_ERR I7300_PRINT "channel %d in use\n", ioat_chan);
+ goto err_unmap;
+ }
+
+ writew(IOAT_CHANCTRL_CHANNEL_IN_USE,
+ ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+
+ ioat_desc = (struct ioat_dma_descriptor *)dma_alloc_coherent(
+ &dummy_dma_dev, 4096,
+ (dma_addr_t *)&ioat_desc_phys, GFP_KERNEL);
+ if (!ioat_desc) {
+ printk(KERN_ERR I7300_PRINT "failed to allocate I/O AT desc\n");
+ goto err_mark_unused;
+ }
+
+ writel(ioat_desc_phys & 0xffffffffUL,
+ ioat_chanbase + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(ioat_desc_phys >> 32,
+ ioat_chanbase + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ if (i7300_idle_ioat_selftest(ioat_iomap, ioat_desc, ioat_desc_phys)) {
+ printk(KERN_ERR I7300_PRINT "I/O AT self-test failed\n");
+ goto err_free;
+ }
+
+ /* Setup circular I/O AT descriptor chain */
+ ioat_desc[0].ctl = IOAT_DESC_SADDR_SNP_CTL | IOAT_DESC_DADDR_SNP_CTL;
+ ioat_desc[0].src_addr = ioat_desc_phys + 2048;
+ ioat_desc[0].dst_addr = ioat_desc_phys + 3072;
+ ioat_desc[0].size = 128;
+ ioat_desc[0].next = ioat_desc_phys + sizeof(struct ioat_dma_descriptor);
+
+ ioat_desc[1].ctl = ioat_desc[0].ctl;
+ ioat_desc[1].src_addr = ioat_desc[0].src_addr;
+ ioat_desc[1].dst_addr = ioat_desc[0].dst_addr;
+ ioat_desc[1].size = ioat_desc[0].size;
+ ioat_desc[1].next = ioat_desc_phys;
+
+ return 0;
+
+err_free:
+ dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
+err_mark_unused:
+ writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+err_unmap:
+ iounmap(ioat_iomap);
+err_ret:
+ return -ENODEV;
+}
+
+/* Cleanup I/O AT */
+static void __exit i7300_idle_ioat_exit(void)
+{
+ int i;
+ u64 chan_sts;
+
+ i7300_idle_ioat_stop();
+
+ /* Wait for a while for the channel to halt before releasing */
+ for (i = 0; i < MAX_STOP_RETRIES; i++) {
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chanbase + IOAT1_CHANCMD_OFFSET);
+
+ chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {
+ writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
+ break;
+ }
+ udelay(1000);
+ }
+
+ chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
+ IOAT_CHANSTS_DMA_TRANSFER_STATUS;
+
+ /*
+ * We tried to reset multiple times. If IO A/T channel is still active
+ * flag an error and return without cleanup. Memory leak is better
+ * than random corruption in that extreme error situation.
+ */
+ if (chan_sts == IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {
+ printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels."
+ " Not freeing resources\n");
+ return;
+ }
+
+ dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
+ iounmap(ioat_iomap);
+}
+
+/* End: I/O AT Helper routines */
+
+#define DIMM_THRTLOW 0x64
+#define DIMM_THRTCTL 0x67
+#define DIMM_THRTCTL_THRMHUNT (1UL << 0)
+#define DIMM_MC 0x40
+#define DIMM_GTW_MODE (1UL << 17)
+#define DIMM_GBLACT 0x60
+
+/*
+ * Keep track of an exponential-decaying average of recent idle durations.
+ * The latest duration gets DURATION_WEIGHT_PCT percentage weight
+ * in this average, with the old average getting the remaining weight.
+ *
+ * High weights emphasize recent history, low weights include long history.
+ */
+#define DURATION_WEIGHT_PCT 55
+
+/*
+ * When the decaying average of recent durations or the predicted duration
+ * of the next timer interrupt is shorter than duration_threshold, the
+ * driver will decline to throttle.
+ */
+#define DURATION_THRESHOLD_US 100
+
+
+/* Store DIMM thermal throttle configuration */
+static int i7300_idle_thrt_save(void)
+{
+ u32 new_mc_val;
+ u8 gblactlm;
+
+ pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &i7300_idle_thrtctl_saved);
+ pci_read_config_byte(fbd_dev, DIMM_THRTLOW, &i7300_idle_thrtlow_saved);
+ pci_read_config_dword(fbd_dev, DIMM_MC, &i7300_idle_mc_saved);
+ /*
+ * Make sure we have Global Throttling Window Mode set to have a
+ * "short" window. This (mostly) works around an issue where
+ * throttling persists until the end of the global throttling window
+ * size. On the tested system, this was resulting in a maximum of
+ * 64 ms to exit throttling (average 32 ms). The actual numbers
+ * depends on system frequencies. Setting the short window reduces
+ * this by a factor of 4096.
+ *
+ * We will only do this only if the system is set for
+ * unlimited-activations while in open-loop throttling (i.e., when
+ * Global Activation Throttle Limit is zero).
+ */
+ pci_read_config_byte(fbd_dev, DIMM_GBLACT, &gblactlm);
+ dprintk("thrtctl_saved = 0x%02x, thrtlow_saved = 0x%02x\n",
+ i7300_idle_thrtctl_saved,
+ i7300_idle_thrtlow_saved);
+ dprintk("mc_saved = 0x%08x, gblactlm = 0x%02x\n",
+ i7300_idle_mc_saved,
+ gblactlm);
+ if (gblactlm == 0) {
+ new_mc_val = i7300_idle_mc_saved | DIMM_GTW_MODE;
+ pci_write_config_dword(fbd_dev, DIMM_MC, new_mc_val);
+ return 0;
+ } else {
+ dprintk("could not set GTW_MODE = 1 (OLTT enabled)\n");
+ return -ENODEV;
+ }
+}
+
+/* Restore DIMM thermal throttle configuration */
+static void i7300_idle_thrt_restore(void)
+{
+ pci_write_config_dword(fbd_dev, DIMM_MC, i7300_idle_mc_saved);
+ pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
+}
+
+/* Enable DIMM thermal throttling */
+static void i7300_idle_start(void)
+{
+ u8 new_ctl;
+ u8 limit;
+
+ new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
+
+ limit = throttle_low_limit;
+ if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT))
+ limit = MAX_THROTTLE_LOW_LIMIT;
+
+ pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);
+
+ new_ctl = i7300_idle_thrtctl_saved | DIMM_THRTCTL_THRMHUNT;
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
+}
+
+/* Disable DIMM thermal throttling */
+static void i7300_idle_stop(void)
+{
+ u8 new_ctl;
+ u8 got_ctl;
+
+ new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
+
+ pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
+ pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
+ pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &got_ctl);
+ WARN_ON_ONCE(got_ctl != i7300_idle_thrtctl_saved);
+}
+
+
+/*
+ * i7300_avg_duration_check()
+ * return 0 if the decaying average of recent idle durations is
+ * more than DURATION_THRESHOLD_US
+ */
+static int i7300_avg_duration_check(void)
+{
+ if (avg_idle_us >= DURATION_THRESHOLD_US)
+ return 0;
+
+#ifdef DEBUG
+ past_skip++;
+#endif
+ return 1;
+}
+
+/* Idle notifier to look at idle CPUs */
+static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ unsigned long flags;
+ ktime_t now_ktime;
+ static ktime_t idle_begin_time;
+ static int time_init = 1;
+
+ if (!throttle_low_limit)
+ return 0;
+
+ if (unlikely(time_init)) {
+ time_init = 0;
+ idle_begin_time = ktime_get();
+ }
+
+ spin_lock_irqsave(&i7300_idle_lock, flags);
+ if (val == IDLE_START) {
+
+ cpu_set(smp_processor_id(), idle_cpumask);
+
+ if (cpus_weight(idle_cpumask) != num_online_cpus())
+ goto end;
+
+ now_ktime = ktime_get();
+ idle_begin_time = now_ktime;
+
+ if (i7300_avg_duration_check())
+ goto end;
+
+ i7300_idle_active = 1;
+ total_starts++;
+ start_ktime = now_ktime;
+
+ i7300_idle_start();
+ i7300_idle_ioat_start();
+
+ } else if (val == IDLE_END) {
+ cpu_clear(smp_processor_id(), idle_cpumask);
+ if (cpus_weight(idle_cpumask) == (num_online_cpus() - 1)) {
+ /* First CPU coming out of idle */
+ u64 idle_duration_us;
+
+ now_ktime = ktime_get();
+
+ idle_duration_us = ktime_to_us(ktime_sub
+ (now_ktime, idle_begin_time));
+
+ avg_idle_us =
+ ((100 - DURATION_WEIGHT_PCT) * avg_idle_us +
+ DURATION_WEIGHT_PCT * idle_duration_us) / 100;
+
+ if (i7300_idle_active) {
+ ktime_t idle_ktime;
+
+ idle_ktime = ktime_sub(now_ktime, start_ktime);
+ total_us += ktime_to_us(idle_ktime);
+
+ i7300_idle_ioat_stop();
+ i7300_idle_stop();
+ i7300_idle_active = 0;
+ }
+ }
+ }
+end:
+ spin_unlock_irqrestore(&i7300_idle_lock, flags);
+ return 0;
+}
+
+static struct notifier_block i7300_idle_nb = {
+ .notifier_call = i7300_idle_notifier,
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+int stats_open_generic(struct inode *inode, struct file *fp)
+{
+ fp->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
+ loff_t *off)
+{
+ unsigned long *p = fp->private_data;
+ char buf[32];
+ int len;
+
+ len = snprintf(buf, 32, "%lu\n", *p);
+ return simple_read_from_buffer(ubuf, count, off, buf, len);
+}
+
+static const struct file_operations idle_fops = {
+ .open = stats_open_generic,
+ .read = stats_read_ul,
+};
+
+struct debugfs_file_info {
+ void *ptr;
+ char name[32];
+ struct dentry *file;
+} debugfs_file_list[] = {
+ {&total_starts, "total_starts", NULL},
+ {&total_us, "total_us", NULL},
+#ifdef DEBUG
+ {&past_skip, "past_skip", NULL},
+#endif
+ {NULL, "", NULL}
+ };
+
+static int __init i7300_idle_init(void)
+{
+ spin_lock_init(&i7300_idle_lock);
+ cpus_clear(idle_cpumask);
+ total_us = 0;
+
+ if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev))
+ return -ENODEV;
+
+ if (i7300_idle_thrt_save())
+ return -ENODEV;
+
+ if (i7300_idle_ioat_init())
+ return -ENODEV;
+
+ debugfs_dir = debugfs_create_dir("i7300_idle", NULL);
+ if (debugfs_dir) {
+ int i = 0;
+
+ while (debugfs_file_list[i].ptr != NULL) {
+ debugfs_file_list[i].file = debugfs_create_file(
+ debugfs_file_list[i].name,
+ S_IRUSR,
+ debugfs_dir,
+ debugfs_file_list[i].ptr,
+ &idle_fops);
+ i++;
+ }
+ }
+
+ idle_notifier_register(&i7300_idle_nb);
+
+ printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION);
+ return 0;
+}
+
+static void __exit i7300_idle_exit(void)
+{
+ idle_notifier_unregister(&i7300_idle_nb);
+
+ if (debugfs_dir) {
+ int i = 0;
+
+ while (debugfs_file_list[i].file != NULL) {
+ debugfs_remove(debugfs_file_list[i].file);
+ i++;
+ }
+
+ debugfs_remove(debugfs_dir);
+ }
+ i7300_idle_thrt_restore();
+ i7300_idle_ioat_exit();
+}
+
+module_init(i7300_idle_init);
+module_exit(i7300_idle_exit);
+
+MODULE_AUTHOR("Andy Henroid <andrew.d.henroid@intel.com>");
+MODULE_DESCRIPTION("Intel Chipset DIMM Idle Power Saving Driver v"
+ I7300_IDLE_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index a78d35aecee..f1e82a92e61 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -122,7 +122,7 @@ struct cm_counter_attribute {
#define CM_COUNTER_ATTR(_name, _index) \
struct cm_counter_attribute cm_##_name##_counter_attr = { \
- .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
.index = _index \
}
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 49c45feccd5..5c54fc2350b 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -406,19 +406,15 @@ static int register_snoop_agent(struct ib_mad_qp_info *qp_info,
if (i == qp_info->snoop_table_size) {
/* Grow table. */
- new_snoop_table = kmalloc(sizeof mad_snoop_priv *
- qp_info->snoop_table_size + 1,
- GFP_ATOMIC);
+ new_snoop_table = krealloc(qp_info->snoop_table,
+ sizeof mad_snoop_priv *
+ (qp_info->snoop_table_size + 1),
+ GFP_ATOMIC);
if (!new_snoop_table) {
i = -ENOMEM;
goto out;
}
- if (qp_info->snoop_table) {
- memcpy(new_snoop_table, qp_info->snoop_table,
- sizeof mad_snoop_priv *
- qp_info->snoop_table_size);
- kfree(qp_info->snoop_table);
- }
+
qp_info->snoop_table = new_snoop_table;
qp_info->snoop_table_size++;
}
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 3ddacf39b7b..4346a24568f 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -904,8 +904,8 @@ static ssize_t ucma_join_multicast(struct ucma_file *file,
mutex_lock(&file->mut);
mc = ucma_alloc_multicast(ctx);
- if (IS_ERR(mc)) {
- ret = PTR_ERR(mc);
+ if (!mc) {
+ ret = -ENOMEM;
goto err1;
}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index c325c44807e..44e936e48a3 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1942,6 +1942,7 @@ fail4:
fail3:
cxgb3_free_atid(ep->com.tdev, ep->atid);
fail2:
+ cm_id->rem_ref(cm_id);
put_ep(&ep->com);
out:
return err;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 5d7b7855afb..4df887af66a 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -128,6 +128,8 @@ struct ehca_shca {
/* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
u32 hca_cap_mr_pgsize;
int max_mtu;
+ int max_num_qps;
+ int max_num_cqs;
atomic_t num_cqs;
atomic_t num_qps;
};
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 33647a95eb9..2f4c28a3027 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -132,9 +132,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
return ERR_PTR(-EINVAL);
- if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) {
+ if (!atomic_add_unless(&shca->num_cqs, 1, shca->max_num_cqs)) {
ehca_err(device, "Unable to create CQ, max number of %i "
- "CQs reached.", ehca_max_cq);
+ "CQs reached.", shca->max_num_cqs);
ehca_err(device, "To increase the maximum number of CQs "
"use the number_of_cqs module parameter.\n");
return ERR_PTR(-ENOSPC);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 598844d2edc..bb02a86aa52 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -44,6 +44,8 @@
#include <linux/slab.h>
#endif
+#include <linux/notifier.h>
+#include <linux/memory.h>
#include "ehca_classes.h"
#include "ehca_iverbs.h"
#include "ehca_mrmw.h"
@@ -366,22 +368,23 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
/* Set maximum number of CQs and QPs to calculate EQ size */
- if (ehca_max_qp == -1)
- ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES);
- else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) {
- ehca_gen_err("Requested number of QPs is out of range (1 - %i) "
- "specified by HW", rblock->max_qp);
- ret = -EINVAL;
- goto sense_attributes1;
+ if (shca->max_num_qps == -1)
+ shca->max_num_qps = min_t(int, rblock->max_qp,
+ EHCA_MAX_NUM_QUEUES);
+ else if (shca->max_num_qps < 1 || shca->max_num_qps > rblock->max_qp) {
+ ehca_gen_warn("The requested number of QPs is out of range "
+ "(1 - %i) specified by HW. Value is set to %i",
+ rblock->max_qp, rblock->max_qp);
+ shca->max_num_qps = rblock->max_qp;
}
- if (ehca_max_cq == -1)
- ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES);
- else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) {
- ehca_gen_err("Requested number of CQs is out of range (1 - %i) "
- "specified by HW", rblock->max_cq);
- ret = -EINVAL;
- goto sense_attributes1;
+ if (shca->max_num_cqs == -1)
+ shca->max_num_cqs = min_t(int, rblock->max_cq,
+ EHCA_MAX_NUM_QUEUES);
+ else if (shca->max_num_cqs < 1 || shca->max_num_cqs > rblock->max_cq) {
+ ehca_gen_warn("The requested number of CQs is out of range "
+ "(1 - %i) specified by HW. Value is set to %i",
+ rblock->max_cq, rblock->max_cq);
}
/* query max MTU from first port -- it's the same for all ports */
@@ -733,9 +736,13 @@ static int __devinit ehca_probe(struct of_device *dev,
ehca_gen_err("Cannot allocate shca memory.");
return -ENOMEM;
}
+
mutex_init(&shca->modify_mutex);
atomic_set(&shca->num_cqs, 0);
atomic_set(&shca->num_qps, 0);
+ shca->max_num_qps = ehca_max_qp;
+ shca->max_num_cqs = ehca_max_cq;
+
for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
spin_lock_init(&shca->sport[i].mod_sqp_lock);
@@ -755,7 +762,7 @@ static int __devinit ehca_probe(struct of_device *dev,
goto probe1;
}
- eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp;
+ eq_size = 2 * shca->max_num_cqs + 4 * shca->max_num_qps;
/* create event queues */
ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
if (ret) {
@@ -964,6 +971,41 @@ void ehca_poll_eqs(unsigned long data)
spin_unlock(&shca_list_lock);
}
+static int ehca_mem_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ static unsigned long ehca_dmem_warn_time;
+
+ switch (action) {
+ case MEM_CANCEL_OFFLINE:
+ case MEM_CANCEL_ONLINE:
+ case MEM_ONLINE:
+ case MEM_OFFLINE:
+ return NOTIFY_OK;
+ case MEM_GOING_ONLINE:
+ case MEM_GOING_OFFLINE:
+ /* only ok if no hca is attached to the lpar */
+ spin_lock(&shca_list_lock);
+ if (list_empty(&shca_list)) {
+ spin_unlock(&shca_list_lock);
+ return NOTIFY_OK;
+ } else {
+ spin_unlock(&shca_list_lock);
+ if (printk_timed_ratelimit(&ehca_dmem_warn_time,
+ 30 * 1000))
+ ehca_gen_err("DMEM operations are not allowed"
+ "as long as an ehca adapter is"
+ "attached to the LPAR");
+ return NOTIFY_BAD;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block ehca_mem_nb = {
+ .notifier_call = ehca_mem_notifier,
+};
+
static int __init ehca_module_init(void)
{
int ret;
@@ -991,6 +1033,12 @@ static int __init ehca_module_init(void)
goto module_init2;
}
+ ret = register_memory_notifier(&ehca_mem_nb);
+ if (ret) {
+ ehca_gen_err("Failed registering memory add/remove notifier");
+ goto module_init3;
+ }
+
if (ehca_poll_all_eqs != 1) {
ehca_gen_err("WARNING!!!");
ehca_gen_err("It is possible to lose interrupts.");
@@ -1003,6 +1051,9 @@ static int __init ehca_module_init(void)
return 0;
+module_init3:
+ ibmebus_unregister_driver(&ehca_driver);
+
module_init2:
ehca_destroy_slab_caches();
@@ -1018,6 +1069,8 @@ static void __exit ehca_module_exit(void)
ibmebus_unregister_driver(&ehca_driver);
+ unregister_memory_notifier(&ehca_mem_nb);
+
ehca_destroy_slab_caches();
ehca_destroy_comp_pool();
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 4dbe2870e01..4d54b9f6456 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -465,9 +465,9 @@ static struct ehca_qp *internal_create_qp(
u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
unsigned long flags;
- if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) {
+ if (!atomic_add_unless(&shca->num_qps, 1, shca->max_num_qps)) {
ehca_err(pd->device, "Unable to create QP, max number of %i "
- "QPs reached.", ehca_max_qp);
+ "QPs reached.", shca->max_num_qps);
ehca_err(pd->device, "To increase the maximum number of QPs "
"use the number_of_qps module parameter.\n");
return ERR_PTR(-ENOSPC);
@@ -502,6 +502,12 @@ static struct ehca_qp *internal_create_qp(
if (init_attr->srq) {
my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq);
+ if (qp_type == IB_QPT_UC) {
+ ehca_err(pd->device, "UC with SRQ not supported");
+ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+
has_srq = 1;
parms.ext_type = EQPT_SRQBASE;
parms.srq_qpn = my_srq->real_qp_num;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index cdca3a511e1..606f1e2ef28 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -298,7 +298,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
int p, q;
int ret;
- for (p = 0; p < dev->dev->caps.num_ports; ++p)
+ for (p = 0; p < dev->num_ports; ++p)
for (q = 0; q <= 1; ++q) {
agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
q ? IB_QPT_GSI : IB_QPT_SMI,
@@ -314,7 +314,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
return 0;
err:
- for (p = 0; p < dev->dev->caps.num_ports; ++p)
+ for (p = 0; p < dev->num_ports; ++p)
for (q = 0; q <= 1; ++q)
if (dev->send_agent[p][q])
ib_unregister_mad_agent(dev->send_agent[p][q]);
@@ -327,7 +327,7 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev)
struct ib_mad_agent *agent;
int p, q;
- for (p = 0; p < dev->dev->caps.num_ports; ++p) {
+ for (p = 0; p < dev->num_ports; ++p) {
for (q = 0; q <= 1; ++q) {
agent = dev->send_agent[p][q];
dev->send_agent[p][q] = NULL;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index a3c2851c054..2e80f8f47b0 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -574,7 +574,10 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
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->num_ports = 0;
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+ ibdev->num_ports++;
+ ibdev->ib_dev.phys_port_cnt = ibdev->num_ports;
ibdev->ib_dev.num_comp_vectors = 1;
ibdev->ib_dev.dma_device = &dev->pdev->dev;
@@ -691,7 +694,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
struct mlx4_ib_dev *ibdev = ibdev_ptr;
int p;
- for (p = 1; p <= dev->caps.num_ports; ++p)
+ for (p = 1; p <= ibdev->num_ports; ++p)
mlx4_CLOSE_PORT(dev, p);
mlx4_ib_mad_cleanup(ibdev);
@@ -706,6 +709,10 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
enum mlx4_dev_event event, int port)
{
struct ib_event ibev;
+ struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr);
+
+ if (port > ibdev->num_ports)
+ return;
switch (event) {
case MLX4_DEV_EVENT_PORT_UP:
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 6e2b0dc21b6..9974e886b8d 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -162,6 +162,7 @@ struct mlx4_ib_ah {
struct mlx4_ib_dev {
struct ib_device ib_dev;
struct mlx4_dev *dev;
+ int num_ports;
void __iomem *uar_map;
struct mlx4_uar priv_uar;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index baa01deb243..39167a797f9 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -451,6 +451,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
{
+ int qpn;
int err;
mutex_init(&qp->mutex);
@@ -545,9 +546,17 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
}
}
- err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp);
+ if (sqpn) {
+ qpn = sqpn;
+ } else {
+ err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
+ if (err)
+ goto err_wrid;
+ }
+
+ err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp);
if (err)
- goto err_wrid;
+ goto err_qpn;
/*
* Hardware wants QPN written in big-endian order (after
@@ -560,6 +569,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
return 0;
+err_qpn:
+ if (!sqpn)
+ mlx4_qp_release_range(dev->dev, qpn, 1);
+
err_wrid:
if (pd->uobject) {
if (!init_attr->srq)
@@ -655,6 +668,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
mlx4_ib_unlock_cqs(send_cq, recv_cq);
mlx4_qp_free(dev->dev, &qp->mqp);
+
+ if (!is_sqp(dev, qp))
+ mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
+
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
if (is_user) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 68ba5c3482e..e0c7dfabf2b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -507,6 +507,7 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev);
void ipoib_drain_cq(struct net_device *dev);
void ipoib_set_ethtool_ops(struct net_device *dev);
+int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca);
#ifdef CONFIG_INFINIBAND_IPOIB_CM
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 66af5c1a76e..e9795f60e5d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -42,6 +42,13 @@ static void ipoib_get_drvinfo(struct net_device *netdev,
strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
}
+static u32 ipoib_get_rx_csum(struct net_device *dev)
+{
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ return test_bit(IPOIB_FLAG_CSUM, &priv->flags) &&
+ !test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+}
+
static int ipoib_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
@@ -129,7 +136,7 @@ static void ipoib_get_ethtool_stats(struct net_device *dev,
static const struct ethtool_ops ipoib_ethtool_ops = {
.get_drvinfo = ipoib_get_drvinfo,
- .get_tso = ethtool_op_get_tso,
+ .get_rx_csum = ipoib_get_rx_csum,
.get_coalesce = ipoib_get_coalesce,
.set_coalesce = ipoib_set_coalesce,
.get_flags = ethtool_op_get_flags,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 0e748aeeae9..28eb6f03c58 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -685,10 +685,6 @@ int ipoib_ib_dev_open(struct net_device *dev)
queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
round_jiffies_relative(HZ));
- init_timer(&priv->poll_timer);
- priv->poll_timer.function = ipoib_ib_tx_timer_func;
- priv->poll_timer.data = (unsigned long)dev;
-
set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
return 0;
@@ -906,6 +902,9 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
return -ENODEV;
}
+ setup_timer(&priv->poll_timer, ipoib_ib_tx_timer_func,
+ (unsigned long) dev);
+
if (dev->flags & IFF_UP) {
if (ipoib_ib_dev_open(dev)) {
ipoib_transport_dev_cleanup(dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index c0ee514396d..fddded7900d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1173,11 +1173,48 @@ int ipoib_add_pkey_attr(struct net_device *dev)
return device_create_file(&dev->dev, &dev_attr_pkey);
}
+int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca)
+{
+ struct ib_device_attr *device_attr;
+ int result = -ENOMEM;
+
+ device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
+ if (!device_attr) {
+ printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
+ hca->name, sizeof *device_attr);
+ return result;
+ }
+
+ result = ib_query_device(hca, device_attr);
+ if (result) {
+ printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
+ hca->name, result);
+ kfree(device_attr);
+ return result;
+ }
+ priv->hca_caps = device_attr->device_cap_flags;
+
+ kfree(device_attr);
+
+ if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
+ set_bit(IPOIB_FLAG_CSUM, &priv->flags);
+ priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ }
+
+ if (lro)
+ priv->dev->features |= NETIF_F_LRO;
+
+ if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
+ priv->dev->features |= NETIF_F_TSO;
+
+ return 0;
+}
+
+
static struct net_device *ipoib_add_port(const char *format,
struct ib_device *hca, u8 port)
{
struct ipoib_dev_priv *priv;
- struct ib_device_attr *device_attr;
struct ib_port_attr attr;
int result = -ENOMEM;
@@ -1206,31 +1243,8 @@ static struct net_device *ipoib_add_port(const char *format,
goto device_init_failed;
}
- device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
- if (!device_attr) {
- printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
- hca->name, sizeof *device_attr);
+ if (ipoib_set_dev_features(priv, hca))
goto device_init_failed;
- }
-
- result = ib_query_device(hca, device_attr);
- if (result) {
- printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
- hca->name, result);
- kfree(device_attr);
- goto device_init_failed;
- }
- priv->hca_caps = device_attr->device_cap_flags;
-
- kfree(device_attr);
-
- if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
- set_bit(IPOIB_FLAG_CSUM, &priv->flags);
- priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
- }
-
- if (lro)
- priv->dev->features |= NETIF_F_LRO;
/*
* Set the full membership bit, so that we join the right
@@ -1266,9 +1280,6 @@ static struct net_device *ipoib_add_port(const char *format,
goto event_failed;
}
- if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
- priv->dev->features |= NETIF_F_TSO;
-
result = register_netdev(priv->dev);
if (result) {
printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n",
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index b08eb56196d..2cf1a408871 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -93,6 +93,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;
set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
+ result = ipoib_set_dev_features(priv, ppriv->ca);
+ if (result)
+ goto device_init_failed;
+
priv->pkey = pkey;
memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, INFINIBAND_ALEN);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6e1e8c624f9..3d1ab8fa9ac 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -42,8 +42,9 @@ config TOUCHSCREEN_BITSY
module will be called h3600_ts_input.
config TOUCHSCREEN_CORGI
- tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
+ tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)"
depends on PXA_SHARPSL
+ select CORGI_SSP_DEPRECATED
default y
help
Say Y here to enable the driver for the touchscreen on the
@@ -54,6 +55,9 @@ config TOUCHSCREEN_CORGI
To compile this driver as a module, choose M here: the
module will be called corgi_ts.
+ NOTE: this driver is deprecated, try enable SPI and generic
+ ADS7846-based touchscreen driver.
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
@@ -219,7 +223,7 @@ config TOUCHSCREEN_ATMEL_TSADCC
config TOUCHSCREEN_UCB1400
tristate "Philips UCB1400 touchscreen"
- select AC97_BUS
+ depends on AC97_BUS
depends on UCB1400_CORE
help
This enables support for the Philips UCB1400 touchscreen interface.
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index c38d4e0f95c..a89700e7ace 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -5,7 +5,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/adc.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
#define MODNAME "hp680_ts_input"
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e3e40427e00..e7fb7d2fcbf 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -113,11 +113,12 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.
-config LEDS_CM_X270
- tristate "LED Support for the CM-X270 LEDs"
- depends on LEDS_CLASS && MACH_ARMCORE
+config LEDS_HP_DISK
+ tristate "LED Support for disk protection LED on HP notebooks"
+ depends on LEDS_CLASS && ACPI
help
- This option enables support for the CM-X270 LEDs.
+ This option enable support for disk protection LED, found on
+ newer HP notebooks.
config LEDS_CLEVO_MAIL
tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
@@ -157,6 +158,13 @@ config LEDS_PCA955X
LED driver chips accessed via the I2C bus. Supported
devices include PCA9550, PCA9551, PCA9552, and PCA9553.
+config LEDS_DA903X
+ tristate "LED Support for DA9030/DA9034 PMIC"
+ depends on LEDS_CLASS && PMIC_DA903X
+ help
+ This option enables support for on-chip LED drivers found
+ on Dialog Semiconductor DA9030/DA9034 PMICs.
+
comment "LED Triggers"
config LEDS_TRIGGERS
@@ -179,7 +187,7 @@ config LEDS_TRIGGER_TIMER
config LEDS_TRIGGER_IDE_DISK
bool "LED IDE Disk Trigger"
- depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK
+ depends on LEDS_TRIGGERS && IDE_GD_ATA
help
This allows LEDs to be controlled by IDE disk activity.
If unsure, say Y.
@@ -193,6 +201,15 @@ config LEDS_TRIGGER_HEARTBEAT
load average.
If unsure, say Y.
+config LEDS_TRIGGER_BACKLIGHT
+ tristate "LED backlight Trigger"
+ depends on LEDS_TRIGGERS
+ help
+ This allows LEDs to be controlled as a backlight device: they
+ turn off and on when the display is blanked and unblanked.
+
+ If unsure, say N.
+
config LEDS_TRIGGER_DEFAULT_ON
tristate "LED Default ON Trigger"
depends on LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index eb186c351a1..e1967a29850 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -17,14 +17,16 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.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
+obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
+obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
+obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index ee74ee7b2ac..6c4a326176d 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -34,14 +34,11 @@ static ssize_t led_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
- ssize_t ret = 0;
/* no lock needed for this */
led_update_brightness(led_cdev);
- sprintf(buf, "%u\n", led_cdev->brightness);
- ret = strlen(buf) + 1;
- return ret;
+ return sprintf(buf, "%u\n", led_cdev->brightness);
}
static ssize_t led_brightness_store(struct device *dev,
@@ -113,6 +110,9 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
if (rc)
goto err_out;
+#ifdef CONFIG_LEDS_TRIGGERS
+ init_rwsem(&led_cdev->trigger_lock);
+#endif
/* add to the list of leds */
down_write(&leds_list_lock);
list_add_tail(&led_cdev->node, &leds_list);
@@ -121,8 +121,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
led_update_brightness(led_cdev);
#ifdef CONFIG_LEDS_TRIGGERS
- init_rwsem(&led_cdev->trigger_lock);
-
rc = device_create_file(led_cdev->dev, &dev_attr_trigger);
if (rc)
goto err_out_led_list;
@@ -147,7 +145,7 @@ err_out:
EXPORT_SYMBOL_GPL(led_classdev_register);
/**
- * __led_classdev_unregister - unregisters a object of led_properties class.
+ * led_classdev_unregister - unregisters a object of led_properties class.
* @led_cdev: the led device to unregister
*
* Unregisters a previously registered via led_classdev_register object.
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
index 32c98b2efa3..1bd590bb3a6 100644
--- a/drivers/leds/leds-ams-delta.c
+++ b/drivers/leds/leds-ams-delta.c
@@ -107,27 +107,27 @@ static int ams_delta_led_resume(struct platform_device *dev)
static int ams_delta_led_probe(struct platform_device *pdev)
{
- int i;
- int ret;
+ int i, ret;
- for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) {
+ for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) {
ret = led_classdev_register(&pdev->dev,
&ams_delta_leds[i].cdev);
+ if (ret < 0)
+ goto fail;
}
- if (ret < 0 && i > 1) {
- for (i = i - 2; i >= 0; i--)
- led_classdev_unregister(&ams_delta_leds[i].cdev);
- }
-
- return ret;
+ return 0;
+fail:
+ while (--i >= 0)
+ led_classdev_unregister(&ams_delta_leds[i].cdev);
+ return ret;
}
static int ams_delta_led_remove(struct platform_device *pdev)
{
int i;
- for (i = ARRAY_SIZE(ams_delta_leds) - 1; i >= 0; i--)
+ for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i--)
led_classdev_unregister(&ams_delta_leds[i].cdev);
return 0;
diff --git a/drivers/leds/leds-cm-x270.c b/drivers/leds/leds-cm-x270.c
deleted file mode 100644
index 836a43d776e..00000000000
--- a/drivers/leds/leds-cm-x270.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * drivers/leds/leds-cm-x270.c
- *
- * Copyright 2007 CompuLab Ltd.
- * Author: Mike Rapoport <mike@compulab.co.il>
- *
- * Based on leds-corgi.c
- * Author: Richard Purdie <rpurdie@openedhand.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/platform_device.h>
-#include <linux/leds.h>
-
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-
-#define GPIO_RED_LED (93)
-#define GPIO_GREEN_LED (94)
-
-static void cmx270_red_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- GPCR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED);
- else
- GPSR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED);
-}
-
-static void cmx270_green_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- GPCR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED);
- else
- GPSR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED);
-}
-
-static struct led_classdev cmx270_red_led = {
- .name = "cm-x270:red",
- .default_trigger = "nand-disk",
- .brightness_set = cmx270_red_set,
-};
-
-static struct led_classdev cmx270_green_led = {
- .name = "cm-x270:green",
- .default_trigger = "heartbeat",
- .brightness_set = cmx270_green_set,
-};
-
-#ifdef CONFIG_PM
-static int cmx270led_suspend(struct platform_device *dev, pm_message_t state)
-{
- led_classdev_suspend(&cmx270_red_led);
- led_classdev_suspend(&cmx270_green_led);
- return 0;
-}
-
-static int cmx270led_resume(struct platform_device *dev)
-{
- led_classdev_resume(&cmx270_red_led);
- led_classdev_resume(&cmx270_green_led);
- return 0;
-}
-#endif
-
-static int cmx270led_probe(struct platform_device *pdev)
-{
- int ret;
-
- ret = led_classdev_register(&pdev->dev, &cmx270_red_led);
- if (ret < 0)
- return ret;
-
- ret = led_classdev_register(&pdev->dev, &cmx270_green_led);
- if (ret < 0)
- led_classdev_unregister(&cmx270_red_led);
-
- return ret;
-}
-
-static int cmx270led_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&cmx270_red_led);
- led_classdev_unregister(&cmx270_green_led);
- return 0;
-}
-
-static struct platform_driver cmx270led_driver = {
- .probe = cmx270led_probe,
- .remove = cmx270led_remove,
-#ifdef CONFIG_PM
- .suspend = cmx270led_suspend,
- .resume = cmx270led_resume,
-#endif
- .driver = {
- .name = "cm-x270-led",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init cmx270led_init(void)
-{
- return platform_driver_register(&cmx270led_driver);
-}
-
-static void __exit cmx270led_exit(void)
-{
- platform_driver_unregister(&cmx270led_driver);
-}
-
-module_init(cmx270led_init);
-module_exit(cmx270led_exit);
-
-MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
-MODULE_DESCRIPTION("CM-x270 LED driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cm-x270-led");
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
new file mode 100644
index 00000000000..f1fddb18d70
--- /dev/null
+++ b/drivers/leds/leds-da903x.c
@@ -0,0 +1,175 @@
+/*
+ * LEDs driver for Dialog Semiconductor DA9030/DA9034
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Eric Miao <eric.miao@marvell.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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/mfd/da903x.h>
+
+#define DA9030_LED1_CONTROL 0x20
+#define DA9030_LED2_CONTROL 0x21
+#define DA9030_LED3_CONTROL 0x22
+#define DA9030_LED4_CONTROL 0x23
+#define DA9030_LEDPC_CONTROL 0x24
+#define DA9030_MISC_CONTROL_A 0x26 /* Vibrator Control */
+
+#define DA9034_LED1_CONTROL 0x35
+#define DA9034_LED2_CONTROL 0x36
+#define DA9034_VIBRA 0x40
+
+struct da903x_led {
+ struct led_classdev cdev;
+ struct work_struct work;
+ struct device *master;
+ enum led_brightness new_brightness;
+ int id;
+ int flags;
+};
+
+#define DA9030_LED_OFFSET(id) ((id) - DA9030_ID_LED_1)
+#define DA9034_LED_OFFSET(id) ((id) - DA9034_ID_LED_1)
+
+static void da903x_led_work(struct work_struct *work)
+{
+ struct da903x_led *led = container_of(work, struct da903x_led, work);
+ uint8_t val;
+ int offset;
+
+ switch (led->id) {
+ case DA9030_ID_LED_1:
+ case DA9030_ID_LED_2:
+ case DA9030_ID_LED_3:
+ case DA9030_ID_LED_4:
+ case DA9030_ID_LED_PC:
+ offset = DA9030_LED_OFFSET(led->id);
+ val = led->flags & ~0x87;
+ val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */
+ val |= (led->new_brightness >> 5) & 0x7; /* PWM<2:0> */
+ da903x_write(led->master, DA9030_LED1_CONTROL + offset, val);
+ break;
+ case DA9030_ID_VIBRA:
+ val = led->flags & ~0x80;
+ val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */
+ da903x_write(led->master, DA9030_MISC_CONTROL_A, val);
+ break;
+ case DA9034_ID_LED_1:
+ case DA9034_ID_LED_2:
+ offset = DA9034_LED_OFFSET(led->id);
+ val = (led->new_brightness * 0x5f / LED_FULL) & 0x7f;
+ val |= (led->flags & DA9034_LED_RAMP) ? 0x80 : 0;
+ da903x_write(led->master, DA9034_LED1_CONTROL + offset, val);
+ break;
+ case DA9034_ID_VIBRA:
+ val = led->new_brightness & 0xfe;
+ da903x_write(led->master, DA9034_VIBRA, val);
+ break;
+ }
+}
+
+static void da903x_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct da903x_led *led;
+
+ led = container_of(led_cdev, struct da903x_led, cdev);
+ led->new_brightness = value;
+ schedule_work(&led->work);
+}
+
+static int __devinit da903x_led_probe(struct platform_device *pdev)
+{
+ struct led_info *pdata = pdev->dev.platform_data;
+ struct da903x_led *led;
+ int id, ret;
+
+ if (pdata == NULL)
+ return 0;
+
+ id = pdev->id;
+
+ if (!((id >= DA9030_ID_LED_1 && id <= DA9030_ID_VIBRA) ||
+ (id >= DA9034_ID_LED_1 && id <= DA9034_ID_VIBRA))) {
+ dev_err(&pdev->dev, "invalid LED ID (%d) specified\n", id);
+ return -EINVAL;
+ }
+
+ led = kzalloc(sizeof(struct da903x_led), GFP_KERNEL);
+ if (led == NULL) {
+ dev_err(&pdev->dev, "failed to alloc memory for LED%d\n", id);
+ return -ENOMEM;
+ }
+
+ led->cdev.name = pdata->name;
+ led->cdev.default_trigger = pdata->default_trigger;
+ led->cdev.brightness_set = da903x_led_set;
+ led->cdev.brightness = LED_OFF;
+
+ led->id = id;
+ led->flags = pdata->flags;
+ led->master = pdev->dev.parent;
+ led->new_brightness = LED_OFF;
+
+ INIT_WORK(&led->work, da903x_led_work);
+
+ ret = led_classdev_register(led->master, &led->cdev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register LED %d\n", id);
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, led);
+ return 0;
+
+err:
+ kfree(led);
+ return ret;
+}
+
+static int __devexit da903x_led_remove(struct platform_device *pdev)
+{
+ struct da903x_led *led = platform_get_drvdata(pdev);
+
+ led_classdev_unregister(&led->cdev);
+ kfree(led);
+ return 0;
+}
+
+static struct platform_driver da903x_led_driver = {
+ .driver = {
+ .name = "da903x-led",
+ .owner = THIS_MODULE,
+ },
+ .probe = da903x_led_probe,
+ .remove = __devexit_p(da903x_led_remove),
+};
+
+static int __init da903x_led_init(void)
+{
+ return platform_driver_register(&da903x_led_driver);
+}
+module_init(da903x_led_init);
+
+static void __exit da903x_led_exit(void)
+{
+ platform_driver_unregister(&da903x_led_driver);
+}
+module_exit(da903x_led_exit);
+
+MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+ "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da903x-led");
diff --git a/drivers/leds/leds-hp-disk.c b/drivers/leds/leds-hp-disk.c
new file mode 100644
index 00000000000..74645ab1566
--- /dev/null
+++ b/drivers/leds/leds-hp-disk.c
@@ -0,0 +1,156 @@
+/*
+ * leds-hp-disk.c - driver for HP "hard disk protection" LED
+ *
+ * Copyright (C) 2008 Pavel Machek
+ *
+ * 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/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/version.h>
+#include <linux/leds.h>
+#include <acpi/acpi_drivers.h>
+
+#define DRIVER_NAME "leds-hp-disk"
+#define ACPI_MDPS_CLASS "led"
+
+/* For automatic insertion of the module */
+static struct acpi_device_id hpled_device_ids[] = {
+ {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, hpled_device_ids);
+
+struct acpi_hpled {
+ struct acpi_device *device; /* The ACPI device */
+};
+
+static struct acpi_hpled adev;
+
+static acpi_status hpled_acpi_write(acpi_handle handle, int reg)
+{
+ unsigned long long ret; /* Not used when writing */
+ union acpi_object in_obj[1];
+ struct acpi_object_list args = { 1, in_obj };
+
+ in_obj[0].type = ACPI_TYPE_INTEGER;
+ in_obj[0].integer.value = reg;
+
+ return acpi_evaluate_integer(handle, "ALED", &args, &ret);
+}
+
+static void hpled_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ hpled_acpi_write(adev.device->handle, !!value);
+}
+
+static struct led_classdev hpled_led = {
+ .name = "hp:red:hddprotection",
+ .default_trigger = "heartbeat",
+ .brightness_set = hpled_set,
+};
+
+#ifdef CONFIG_PM
+static int hpled_suspend(struct acpi_device *dev, pm_message_t state)
+{
+ led_classdev_suspend(&hpled_led);
+ return 0;
+}
+
+static int hpled_resume(struct acpi_device *dev)
+{
+ led_classdev_resume(&hpled_led);
+ return 0;
+}
+#else
+#define hpled_suspend NULL
+#define hpled_resume NULL
+#endif
+
+static int hpled_add(struct acpi_device *device)
+{
+ int ret;
+
+ if (!device)
+ return -EINVAL;
+
+ adev.device = device;
+ strcpy(acpi_device_name(device), DRIVER_NAME);
+ strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
+ device->driver_data = &adev;
+
+ ret = led_classdev_register(NULL, &hpled_led);
+ return ret;
+}
+
+static int hpled_remove(struct acpi_device *device, int type)
+{
+ if (!device)
+ return -EINVAL;
+
+ led_classdev_unregister(&hpled_led);
+ return 0;
+}
+
+
+
+static struct acpi_driver leds_hp_driver = {
+ .name = DRIVER_NAME,
+ .class = ACPI_MDPS_CLASS,
+ .ids = hpled_device_ids,
+ .ops = {
+ .add = hpled_add,
+ .remove = hpled_remove,
+ .suspend = hpled_suspend,
+ .resume = hpled_resume,
+ }
+};
+
+static int __init hpled_init_module(void)
+{
+ int ret;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ ret = acpi_bus_register_driver(&leds_hp_driver);
+ if (ret < 0)
+ return ret;
+
+ printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
+
+ return 0;
+}
+
+static void __exit hpled_exit_module(void)
+{
+ acpi_bus_unregister_driver(&leds_hp_driver);
+}
+
+MODULE_DESCRIPTION("Driver for HP disk protection LED");
+MODULE_AUTHOR("Pavel Machek <pavel@suse.cz>");
+MODULE_LICENSE("GPL");
+
+module_init(hpled_init_module);
+module_exit(hpled_exit_module);
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index 844d5979c90..e8fb1baf8a5 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -15,7 +15,7 @@
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/hd64461.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
static void hp6xxled_green_set(struct led_classdev *led_cdev,
enum led_brightness value)
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index f508729123b..4e2d1a42b48 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -226,7 +226,7 @@ static void pca955x_led_work(struct work_struct *work)
pca955x_write_ls(pca955x->client, chip_ls, ls);
}
-void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
{
struct pca955x_led *pca955x;
diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c
index 7ac61a7b56a..2f3aa87f2a1 100644
--- a/drivers/leds/leds-wrap.c
+++ b/drivers/leds/leds-wrap.c
@@ -53,8 +53,9 @@ static void wrap_extra_led_set(struct led_classdev *led_cdev,
}
static struct led_classdev wrap_power_led = {
- .name = "wrap::power",
- .brightness_set = wrap_power_led_set,
+ .name = "wrap::power",
+ .brightness_set = wrap_power_led_set,
+ .default_trigger = "default-on",
};
static struct led_classdev wrap_error_led = {
diff --git a/drivers/leds/ledtrig-backlight.c b/drivers/leds/ledtrig-backlight.c
new file mode 100644
index 00000000000..d3dfcfb417b
--- /dev/null
+++ b/drivers/leds/ledtrig-backlight.c
@@ -0,0 +1,110 @@
+/*
+ * Backlight emulation LED trigger
+ *
+ * Copyright 2008 (C) Rodolfo Giometti <giometti@linux.it>
+ * Copyright 2008 (C) Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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/init.h>
+#include <linux/fb.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+#define BLANK 1
+#define UNBLANK 0
+
+struct bl_trig_notifier {
+ struct led_classdev *led;
+ int brightness;
+ int old_status;
+ struct notifier_block notifier;
+};
+
+static int fb_notifier_callback(struct notifier_block *p,
+ unsigned long event, void *data)
+{
+ struct bl_trig_notifier *n = container_of(p,
+ struct bl_trig_notifier, notifier);
+ struct led_classdev *led = n->led;
+ struct fb_event *fb_event = data;
+ int *blank = fb_event->data;
+
+ switch (event) {
+ case FB_EVENT_BLANK :
+ if (*blank && n->old_status == UNBLANK) {
+ n->brightness = led->brightness;
+ led_set_brightness(led, LED_OFF);
+ n->old_status = BLANK;
+ } else if (!*blank && n->old_status == BLANK) {
+ led_set_brightness(led, n->brightness);
+ n->old_status = UNBLANK;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void bl_trig_activate(struct led_classdev *led)
+{
+ int ret;
+
+ struct bl_trig_notifier *n;
+
+ n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
+ led->trigger_data = n;
+ if (!n) {
+ dev_err(led->dev, "unable to allocate backlight trigger\n");
+ return;
+ }
+
+ n->led = led;
+ n->brightness = led->brightness;
+ n->old_status = UNBLANK;
+ n->notifier.notifier_call = fb_notifier_callback;
+
+ ret = fb_register_client(&n->notifier);
+ if (ret)
+ dev_err(led->dev, "unable to register backlight trigger\n");
+}
+
+static void bl_trig_deactivate(struct led_classdev *led)
+{
+ struct bl_trig_notifier *n =
+ (struct bl_trig_notifier *) led->trigger_data;
+
+ if (n) {
+ fb_unregister_client(&n->notifier);
+ kfree(n);
+ }
+}
+
+static struct led_trigger bl_led_trigger = {
+ .name = "backlight",
+ .activate = bl_trig_activate,
+ .deactivate = bl_trig_deactivate
+};
+
+static int __init bl_trig_init(void)
+{
+ return led_trigger_register(&bl_led_trigger);
+}
+
+static void __exit bl_trig_exit(void)
+{
+ led_trigger_unregister(&bl_led_trigger);
+}
+
+module_init(bl_trig_init);
+module_exit(bl_trig_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("Backlight emulation LED trigger");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index 5c99f4f0c69..db681962d7b 100644
--- a/drivers/leds/ledtrig-timer.c
+++ b/drivers/leds/ledtrig-timer.c
@@ -70,9 +70,7 @@ static ssize_t led_delay_on_show(struct device *dev,
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data;
- sprintf(buf, "%lu\n", timer_data->delay_on);
-
- return strlen(buf) + 1;
+ return sprintf(buf, "%lu\n", timer_data->delay_on);
}
static ssize_t led_delay_on_store(struct device *dev,
@@ -116,9 +114,7 @@ static ssize_t led_delay_off_show(struct device *dev,
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data;
- sprintf(buf, "%lu\n", timer_data->delay_off);
-
- return strlen(buf) + 1;
+ return sprintf(buf, "%lu\n", timer_data->delay_off);
}
static ssize_t led_delay_off_store(struct device *dev,
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index f1ef33dfd8c..1c615804ea7 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_DELAY) += dm-delay.o
obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
-obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o
+obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
quiet_cmd_unroll = UNROLL $@
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 682ef9e6acd..ce26c84af06 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -23,7 +23,7 @@
#include <asm/page.h>
#include <asm/unaligned.h>
-#include "dm.h"
+#include <linux/device-mapper.h>
#define DM_MSG_PREFIX "crypt"
#define MESG_STR(x) x, sizeof(x)
@@ -56,6 +56,7 @@ struct dm_crypt_io {
atomic_t pending;
int error;
sector_t sector;
+ struct dm_crypt_io *base_io;
};
struct dm_crypt_request {
@@ -93,7 +94,6 @@ struct crypt_config {
struct workqueue_struct *io_queue;
struct workqueue_struct *crypt_queue;
- wait_queue_head_t writeq;
/*
* crypto related data
@@ -534,6 +534,7 @@ static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti,
io->base_bio = bio;
io->sector = sector;
io->error = 0;
+ io->base_io = NULL;
atomic_set(&io->pending, 0);
return io;
@@ -547,6 +548,7 @@ static void crypt_inc_pending(struct dm_crypt_io *io)
/*
* One of the bios was finished. Check for completion of
* the whole request and correctly clean up the buffer.
+ * If base_io is set, wait for the last fragment to complete.
*/
static void crypt_dec_pending(struct dm_crypt_io *io)
{
@@ -555,7 +557,14 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
if (!atomic_dec_and_test(&io->pending))
return;
- bio_endio(io->base_bio, io->error);
+ if (likely(!io->base_io))
+ bio_endio(io->base_bio, io->error);
+ else {
+ if (io->error && !io->base_io->error)
+ io->base_io->error = io->error;
+ crypt_dec_pending(io->base_io);
+ }
+
mempool_free(io, cc->io_pool);
}
@@ -646,10 +655,7 @@ static void kcryptd_io_read(struct dm_crypt_io *io)
static void kcryptd_io_write(struct dm_crypt_io *io)
{
struct bio *clone = io->ctx.bio_out;
- struct crypt_config *cc = io->target->private;
-
generic_make_request(clone);
- wake_up(&cc->writeq);
}
static void kcryptd_io(struct work_struct *work)
@@ -688,7 +694,6 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
BUG_ON(io->ctx.idx_out < clone->bi_vcnt);
clone->bi_sector = cc->start + io->sector;
- io->sector += bio_sectors(clone);
if (async)
kcryptd_queue_io(io);
@@ -700,16 +705,18 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->target->private;
struct bio *clone;
+ struct dm_crypt_io *new_io;
int crypt_finished;
unsigned out_of_pages = 0;
unsigned remaining = io->base_bio->bi_size;
+ sector_t sector = io->sector;
int r;
/*
* Prevent io from disappearing until this function completes.
*/
crypt_inc_pending(io);
- crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector);
+ crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, sector);
/*
* The allocated buffers can be smaller than the whole bio,
@@ -726,6 +733,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
io->ctx.idx_out = 0;
remaining -= clone->bi_size;
+ sector += bio_sectors(clone);
crypt_inc_pending(io);
r = crypt_convert(cc, &io->ctx);
@@ -741,6 +749,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
*/
if (unlikely(r < 0))
break;
+
+ io->sector = sector;
}
/*
@@ -750,8 +760,33 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
if (unlikely(out_of_pages))
congestion_wait(WRITE, HZ/100);
- if (unlikely(remaining))
- wait_event(cc->writeq, !atomic_read(&io->ctx.pending));
+ /*
+ * With async crypto it is unsafe to share the crypto context
+ * between fragments, so switch to a new dm_crypt_io structure.
+ */
+ if (unlikely(!crypt_finished && remaining)) {
+ new_io = crypt_io_alloc(io->target, io->base_bio,
+ sector);
+ crypt_inc_pending(new_io);
+ crypt_convert_init(cc, &new_io->ctx, NULL,
+ io->base_bio, sector);
+ new_io->ctx.idx_in = io->ctx.idx_in;
+ new_io->ctx.offset_in = io->ctx.offset_in;
+
+ /*
+ * Fragments after the first use the base_io
+ * pending count.
+ */
+ if (!io->base_io)
+ new_io->base_io = io;
+ else {
+ new_io->base_io = io->base_io;
+ crypt_inc_pending(io->base_io);
+ crypt_dec_pending(io);
+ }
+
+ io = new_io;
+ }
}
crypt_dec_pending(io);
@@ -1078,7 +1113,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad_crypt_queue;
}
- init_waitqueue_head(&cc->writeq);
ti->private = cc;
return 0;
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index bdd37f881c4..848b381f117 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -13,7 +13,8 @@
#include <linux/bio.h>
#include <linux/slab.h>
-#include "dm.h"
+#include <linux/device-mapper.h>
+
#include "dm-bio-list.h"
#define DM_MSG_PREFIX "delay"
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 769ab677f8e..01590f3e000 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -7,7 +7,6 @@
* This file is released under the GPL.
*/
-#include "dm.h"
#include "dm-snap.h"
#include <linux/mm.h>
@@ -105,6 +104,11 @@ struct pstore {
void *area;
/*
+ * An area of zeros used to clear the next area.
+ */
+ void *zero_area;
+
+ /*
* Used to keep track of which metadata area the data in
* 'chunk' refers to.
*/
@@ -149,6 +153,13 @@ static int alloc_area(struct pstore *ps)
if (!ps->area)
return r;
+ ps->zero_area = vmalloc(len);
+ if (!ps->zero_area) {
+ vfree(ps->area);
+ return r;
+ }
+ memset(ps->zero_area, 0, len);
+
return 0;
}
@@ -156,6 +167,8 @@ static void free_area(struct pstore *ps)
{
vfree(ps->area);
ps->area = NULL;
+ vfree(ps->zero_area);
+ ps->zero_area = NULL;
}
struct mdata_req {
@@ -220,25 +233,41 @@ static chunk_t area_location(struct pstore *ps, chunk_t area)
* Read or write a metadata area. Remembering to skip the first
* chunk which holds the header.
*/
-static int area_io(struct pstore *ps, chunk_t area, int rw)
+static int area_io(struct pstore *ps, int rw)
{
int r;
chunk_t chunk;
- chunk = area_location(ps, area);
+ chunk = area_location(ps, ps->current_area);
r = chunk_io(ps, chunk, rw, 0);
if (r)
return r;
- ps->current_area = area;
return 0;
}
-static int zero_area(struct pstore *ps, chunk_t area)
+static void zero_memory_area(struct pstore *ps)
{
memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
- return area_io(ps, area, WRITE);
+}
+
+static int zero_disk_area(struct pstore *ps, chunk_t area)
+{
+ struct dm_io_region where = {
+ .bdev = ps->snap->cow->bdev,
+ .sector = ps->snap->chunk_size * area_location(ps, area),
+ .count = ps->snap->chunk_size,
+ };
+ struct dm_io_request io_req = {
+ .bi_rw = WRITE,
+ .mem.type = DM_IO_VMA,
+ .mem.ptr.vma = ps->zero_area,
+ .client = ps->io_client,
+ .notify.fn = NULL,
+ };
+
+ return dm_io(&io_req, 1, &where, NULL);
}
static int read_header(struct pstore *ps, int *new_snapshot)
@@ -411,15 +440,14 @@ static int insert_exceptions(struct pstore *ps, int *full)
static int read_exceptions(struct pstore *ps)
{
- chunk_t area;
int r, full = 1;
/*
* Keeping reading chunks and inserting exceptions until
* we find a partially full area.
*/
- for (area = 0; full; area++) {
- r = area_io(ps, area, READ);
+ for (ps->current_area = 0; full; ps->current_area++) {
+ r = area_io(ps, READ);
if (r)
return r;
@@ -428,6 +456,8 @@ static int read_exceptions(struct pstore *ps)
return r;
}
+ ps->current_area--;
+
return 0;
}
@@ -486,12 +516,13 @@ static int persistent_read_metadata(struct exception_store *store)
return r;
}
- r = zero_area(ps, 0);
+ ps->current_area = 0;
+ zero_memory_area(ps);
+ r = zero_disk_area(ps, 0);
if (r) {
- DMWARN("zero_area(0) failed");
+ DMWARN("zero_disk_area(0) failed");
return r;
}
-
} else {
/*
* Sanity checks.
@@ -551,7 +582,6 @@ static void persistent_commit(struct exception_store *store,
void (*callback) (void *, int success),
void *callback_context)
{
- int r;
unsigned int i;
struct pstore *ps = get_info(store);
struct disk_exception de;
@@ -572,33 +602,41 @@ static void persistent_commit(struct exception_store *store,
cb->context = callback_context;
/*
- * If there are no more exceptions in flight, or we have
- * filled this metadata area we commit the exceptions to
- * disk.
+ * If there are exceptions in flight and we have not yet
+ * filled this metadata area there's nothing more to do.
*/
- if (atomic_dec_and_test(&ps->pending_count) ||
- (ps->current_committed == ps->exceptions_per_area)) {
- r = area_io(ps, ps->current_area, WRITE);
- if (r)
- ps->valid = 0;
+ if (!atomic_dec_and_test(&ps->pending_count) &&
+ (ps->current_committed != ps->exceptions_per_area))
+ return;
- /*
- * Have we completely filled the current area ?
- */
- if (ps->current_committed == ps->exceptions_per_area) {
- ps->current_committed = 0;
- r = zero_area(ps, ps->current_area + 1);
- if (r)
- ps->valid = 0;
- }
+ /*
+ * If we completely filled the current area, then wipe the next one.
+ */
+ if ((ps->current_committed == ps->exceptions_per_area) &&
+ zero_disk_area(ps, ps->current_area + 1))
+ ps->valid = 0;
- for (i = 0; i < ps->callback_count; i++) {
- cb = ps->callbacks + i;
- cb->callback(cb->context, r == 0 ? 1 : 0);
- }
+ /*
+ * Commit exceptions to disk.
+ */
+ if (ps->valid && area_io(ps, WRITE))
+ ps->valid = 0;
- ps->callback_count = 0;
+ /*
+ * Advance to the next area if this one is full.
+ */
+ if (ps->current_committed == ps->exceptions_per_area) {
+ ps->current_committed = 0;
+ ps->current_area++;
+ zero_memory_area(ps);
}
+
+ for (i = 0; i < ps->callback_count; i++) {
+ cb = ps->callbacks + i;
+ cb->callback(cb->context, ps->valid);
+ }
+
+ ps->callback_count = 0;
}
static void persistent_drop(struct exception_store *store)
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 4789c42d9a3..2fd6d445063 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -5,7 +5,7 @@
* This file is released under the GPL.
*/
-#include "dm.h"
+#include <linux/device-mapper.h>
#include <linux/bio.h>
#include <linux/mempool.h>
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index dca401dc70a..777c948180f 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -988,9 +988,9 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size)
return r;
}
-static inline int get_mode(struct dm_ioctl *param)
+static inline fmode_t get_mode(struct dm_ioctl *param)
{
- int mode = FMODE_READ | FMODE_WRITE;
+ fmode_t mode = FMODE_READ | FMODE_WRITE;
if (param->flags & DM_READONLY_FLAG)
mode = FMODE_READ;
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 996802b8a45..3073618269e 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
+#include <linux/device-mapper.h>
#include <linux/dm-kcopyd.h>
#include "dm.h"
@@ -268,6 +269,17 @@ static void push(struct list_head *jobs, struct kcopyd_job *job)
spin_unlock_irqrestore(&kc->job_lock, flags);
}
+
+static void push_head(struct list_head *jobs, struct kcopyd_job *job)
+{
+ unsigned long flags;
+ struct dm_kcopyd_client *kc = job->kc;
+
+ spin_lock_irqsave(&kc->job_lock, flags);
+ list_add(&job->list, jobs);
+ spin_unlock_irqrestore(&kc->job_lock, flags);
+}
+
/*
* These three functions process 1 item from the corresponding
* job list.
@@ -398,7 +410,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
* We couldn't service this job ATM, so
* push this job back onto the list.
*/
- push(jobs, job);
+ push_head(jobs, job);
break;
}
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 6449bcdf84c..44042becad8 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -5,12 +5,12 @@
*/
#include "dm.h"
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <linux/slab.h>
+#include <linux/device-mapper.h>
#define DM_MSG_PREFIX "linear"
@@ -110,20 +110,11 @@ static int linear_status(struct dm_target *ti, status_type_t type,
return 0;
}
-static int linear_ioctl(struct dm_target *ti, struct inode *inode,
- struct file *filp, unsigned int cmd,
+static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
unsigned long arg)
{
struct linear_c *lc = (struct linear_c *) ti->private;
- struct block_device *bdev = lc->dev->bdev;
- struct file fake_file = {};
- struct dentry fake_dentry = {};
-
- fake_file.f_mode = lc->dev->mode;
- fake_file.f_path.dentry = &fake_dentry;
- fake_dentry.d_inode = bdev->bd_inode;
-
- return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg);
+ return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
}
static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 5b48478c79f..a8c0fc79ca7 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -12,7 +12,7 @@
#include <linux/dm-io.h>
#include <linux/dm-dirty-log.h>
-#include "dm.h"
+#include <linux/device-mapper.h>
#define DM_MSG_PREFIX "dirty region log"
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 9bf3460c554..4840733cd90 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -5,7 +5,8 @@
* This file is released under the GPL.
*/
-#include "dm.h"
+#include <linux/device-mapper.h>
+
#include "dm-path-selector.h"
#include "dm-bio-list.h"
#include "dm-bio-record.h"
@@ -1395,19 +1396,15 @@ error:
return -EINVAL;
}
-static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
- struct file *filp, unsigned int cmd,
+static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
unsigned long arg)
{
struct multipath *m = (struct multipath *) ti->private;
struct block_device *bdev = NULL;
+ fmode_t mode = 0;
unsigned long flags;
- struct file fake_file = {};
- struct dentry fake_dentry = {};
int r = 0;
- fake_file.f_path.dentry = &fake_dentry;
-
spin_lock_irqsave(&m->lock, flags);
if (!m->current_pgpath)
@@ -1415,8 +1412,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
if (m->current_pgpath) {
bdev = m->current_pgpath->path.dev->bdev;
- fake_dentry.d_inode = bdev->bd_inode;
- fake_file.f_mode = m->current_pgpath->path.dev->mode;
+ mode = m->current_pgpath->path.dev->mode;
}
if (m->queue_io)
@@ -1426,8 +1422,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
spin_unlock_irqrestore(&m->lock, flags);
- return r ? : blkdev_driver_ioctl(bdev->bd_inode, &fake_file,
- bdev->bd_disk, cmd, arg);
+ return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
/*-----------------------------------------------------------------
diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c
index ca1bb636a3e..96ea226155b 100644
--- a/drivers/md/dm-path-selector.c
+++ b/drivers/md/dm-path-selector.c
@@ -9,7 +9,8 @@
* Path selector registration.
*/
-#include "dm.h"
+#include <linux/device-mapper.h>
+
#include "dm-path-selector.h"
#include <linux/slab.h>
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 29913e42c4a..92dcc06832a 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1,30 +1,30 @@
/*
* Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
-#include "dm.h"
#include "dm-bio-list.h"
#include "dm-bio-record.h"
-#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/vmalloc.h>
#include <linux/workqueue.h>
-#include <linux/log2.h>
-#include <linux/hardirq.h>
+#include <linux/device-mapper.h>
#include <linux/dm-io.h>
#include <linux/dm-dirty-log.h>
#include <linux/dm-kcopyd.h>
+#include <linux/dm-region-hash.h>
#define DM_MSG_PREFIX "raid1"
+
+#define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */
#define DM_IO_PAGES 64
+#define DM_KCOPYD_PAGES 64
#define DM_RAID1_HANDLE_ERRORS 0x01
#define errors_handled(p) ((p)->features & DM_RAID1_HANDLE_ERRORS)
@@ -32,87 +32,6 @@
static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
/*-----------------------------------------------------------------
- * Region hash
- *
- * The mirror splits itself up into discrete regions. Each
- * region can be in one of three states: clean, dirty,
- * nosync. There is no need to put clean regions in the hash.
- *
- * In addition to being present in the hash table a region _may_
- * be present on one of three lists.
- *
- * clean_regions: Regions on this list have no io pending to
- * them, they are in sync, we are no longer interested in them,
- * they are dull. rh_update_states() will remove them from the
- * hash table.
- *
- * quiesced_regions: These regions have been spun down, ready
- * for recovery. rh_recovery_start() will remove regions from
- * this list and hand them to kmirrord, which will schedule the
- * recovery io with kcopyd.
- *
- * recovered_regions: Regions that kcopyd has successfully
- * recovered. rh_update_states() will now schedule any delayed
- * io, up the recovery_count, and remove the region from the
- * hash.
- *
- * There are 2 locks:
- * A rw spin lock 'hash_lock' protects just the hash table,
- * this is never held in write mode from interrupt context,
- * which I believe means that we only have to disable irqs when
- * doing a write lock.
- *
- * An ordinary spin lock 'region_lock' that protects the three
- * lists in the region_hash, with the 'state', 'list' and
- * 'bhs_delayed' fields of the regions. This is used from irq
- * context, so all other uses will have to suspend local irqs.
- *---------------------------------------------------------------*/
-struct mirror_set;
-struct region_hash {
- struct mirror_set *ms;
- uint32_t region_size;
- unsigned region_shift;
-
- /* holds persistent region state */
- struct dm_dirty_log *log;
-
- /* hash table */
- rwlock_t hash_lock;
- mempool_t *region_pool;
- unsigned int mask;
- unsigned int nr_buckets;
- struct list_head *buckets;
-
- spinlock_t region_lock;
- atomic_t recovery_in_flight;
- struct semaphore recovery_count;
- struct list_head clean_regions;
- struct list_head quiesced_regions;
- struct list_head recovered_regions;
- struct list_head failed_recovered_regions;
-};
-
-enum {
- RH_CLEAN,
- RH_DIRTY,
- RH_NOSYNC,
- RH_RECOVERING
-};
-
-struct region {
- struct region_hash *rh; /* FIXME: can we get rid of this ? */
- region_t key;
- int state;
-
- struct list_head hash_list;
- struct list_head list;
-
- atomic_t pending;
- struct bio_list delayed_bios;
-};
-
-
-/*-----------------------------------------------------------------
* Mirror set structures.
*---------------------------------------------------------------*/
enum dm_raid1_error {
@@ -132,8 +51,7 @@ struct mirror {
struct mirror_set {
struct dm_target *ti;
struct list_head list;
- struct region_hash rh;
- struct dm_kcopyd_client *kcopyd_client;
+
uint64_t features;
spinlock_t lock; /* protects the lists */
@@ -141,6 +59,8 @@ struct mirror_set {
struct bio_list writes;
struct bio_list failures;
+ struct dm_region_hash *rh;
+ struct dm_kcopyd_client *kcopyd_client;
struct dm_io_client *io_client;
mempool_t *read_record_pool;
@@ -159,25 +79,14 @@ struct mirror_set {
struct work_struct trigger_event;
- unsigned int nr_mirrors;
+ unsigned nr_mirrors;
struct mirror mirror[0];
};
-/*
- * Conversion fns
- */
-static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio)
-{
- return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift;
-}
-
-static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
+static void wakeup_mirrord(void *context)
{
- return region << rh->region_shift;
-}
+ struct mirror_set *ms = context;
-static void wake(struct mirror_set *ms)
-{
queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
}
@@ -186,7 +95,7 @@ static void delayed_wake_fn(unsigned long data)
struct mirror_set *ms = (struct mirror_set *) data;
clear_bit(0, &ms->timer_pending);
- wake(ms);
+ wakeup_mirrord(ms);
}
static void delayed_wake(struct mirror_set *ms)
@@ -200,473 +109,34 @@ static void delayed_wake(struct mirror_set *ms)
add_timer(&ms->timer);
}
-/* FIXME move this */
-static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
-
-#define MIN_REGIONS 64
-#define MAX_RECOVERY 1
-static int rh_init(struct region_hash *rh, struct mirror_set *ms,
- struct dm_dirty_log *log, uint32_t region_size,
- region_t nr_regions)
+static void wakeup_all_recovery_waiters(void *context)
{
- unsigned int nr_buckets, max_buckets;
- size_t i;
-
- /*
- * Calculate a suitable number of buckets for our hash
- * table.
- */
- max_buckets = nr_regions >> 6;
- for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1)
- ;
- nr_buckets >>= 1;
-
- rh->ms = ms;
- rh->log = log;
- rh->region_size = region_size;
- rh->region_shift = ffs(region_size) - 1;
- rwlock_init(&rh->hash_lock);
- rh->mask = nr_buckets - 1;
- rh->nr_buckets = nr_buckets;
-
- rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets));
- if (!rh->buckets) {
- DMERR("unable to allocate region hash memory");
- return -ENOMEM;
- }
-
- for (i = 0; i < nr_buckets; i++)
- INIT_LIST_HEAD(rh->buckets + i);
-
- spin_lock_init(&rh->region_lock);
- sema_init(&rh->recovery_count, 0);
- atomic_set(&rh->recovery_in_flight, 0);
- INIT_LIST_HEAD(&rh->clean_regions);
- INIT_LIST_HEAD(&rh->quiesced_regions);
- INIT_LIST_HEAD(&rh->recovered_regions);
- INIT_LIST_HEAD(&rh->failed_recovered_regions);
-
- rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
- sizeof(struct region));
- if (!rh->region_pool) {
- vfree(rh->buckets);
- rh->buckets = NULL;
- return -ENOMEM;
- }
-
- return 0;
+ wake_up_all(&_kmirrord_recovery_stopped);
}
-static void rh_exit(struct region_hash *rh)
-{
- unsigned int h;
- struct region *reg, *nreg;
-
- BUG_ON(!list_empty(&rh->quiesced_regions));
- for (h = 0; h < rh->nr_buckets; h++) {
- list_for_each_entry_safe(reg, nreg, rh->buckets + h, hash_list) {
- BUG_ON(atomic_read(&reg->pending));
- mempool_free(reg, rh->region_pool);
- }
- }
-
- if (rh->log)
- dm_dirty_log_destroy(rh->log);
- if (rh->region_pool)
- mempool_destroy(rh->region_pool);
- vfree(rh->buckets);
-}
-
-#define RH_HASH_MULT 2654435387U
-
-static inline unsigned int rh_hash(struct region_hash *rh, region_t region)
-{
- return (unsigned int) ((region * RH_HASH_MULT) >> 12) & rh->mask;
-}
-
-static struct region *__rh_lookup(struct region_hash *rh, region_t region)
-{
- struct region *reg;
-
- list_for_each_entry (reg, rh->buckets + rh_hash(rh, region), hash_list)
- if (reg->key == region)
- return reg;
-
- return NULL;
-}
-
-static void __rh_insert(struct region_hash *rh, struct region *reg)
-{
- unsigned int h = rh_hash(rh, reg->key);
- list_add(&reg->hash_list, rh->buckets + h);
-}
-
-static struct region *__rh_alloc(struct region_hash *rh, region_t region)
-{
- struct region *reg, *nreg;
-
- read_unlock(&rh->hash_lock);
- nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
- if (unlikely(!nreg))
- nreg = kmalloc(sizeof(struct region), GFP_NOIO);
- nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
- RH_CLEAN : RH_NOSYNC;
- nreg->rh = rh;
- nreg->key = region;
-
- INIT_LIST_HEAD(&nreg->list);
-
- atomic_set(&nreg->pending, 0);
- bio_list_init(&nreg->delayed_bios);
- write_lock_irq(&rh->hash_lock);
-
- reg = __rh_lookup(rh, region);
- if (reg)
- /* we lost the race */
- mempool_free(nreg, rh->region_pool);
-
- else {
- __rh_insert(rh, nreg);
- if (nreg->state == RH_CLEAN) {
- spin_lock(&rh->region_lock);
- list_add(&nreg->list, &rh->clean_regions);
- spin_unlock(&rh->region_lock);
- }
- reg = nreg;
- }
- write_unlock_irq(&rh->hash_lock);
- read_lock(&rh->hash_lock);
-
- return reg;
-}
-
-static inline struct region *__rh_find(struct region_hash *rh, region_t region)
-{
- struct region *reg;
-
- reg = __rh_lookup(rh, region);
- if (!reg)
- reg = __rh_alloc(rh, region);
-
- return reg;
-}
-
-static int rh_state(struct region_hash *rh, region_t region, int may_block)
-{
- int r;
- struct region *reg;
-
- read_lock(&rh->hash_lock);
- reg = __rh_lookup(rh, region);
- read_unlock(&rh->hash_lock);
-
- if (reg)
- return reg->state;
-
- /*
- * The region wasn't in the hash, so we fall back to the
- * dirty log.
- */
- r = rh->log->type->in_sync(rh->log, region, may_block);
-
- /*
- * Any error from the dirty log (eg. -EWOULDBLOCK) gets
- * taken as a RH_NOSYNC
- */
- return r == 1 ? RH_CLEAN : RH_NOSYNC;
-}
-
-static inline int rh_in_sync(struct region_hash *rh,
- region_t region, int may_block)
-{
- int state = rh_state(rh, region, may_block);
- return state == RH_CLEAN || state == RH_DIRTY;
-}
-
-static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list)
-{
- struct bio *bio;
-
- while ((bio = bio_list_pop(bio_list))) {
- queue_bio(ms, bio, WRITE);
- }
-}
-
-static void complete_resync_work(struct region *reg, int success)
-{
- struct region_hash *rh = reg->rh;
-
- rh->log->type->set_region_sync(rh->log, reg->key, success);
-
- /*
- * Dispatch the bios before we call 'wake_up_all'.
- * This is important because if we are suspending,
- * we want to know that recovery is complete and
- * the work queue is flushed. If we wake_up_all
- * before we dispatch_bios (queue bios and call wake()),
- * then we risk suspending before the work queue
- * has been properly flushed.
- */
- dispatch_bios(rh->ms, &reg->delayed_bios);
- if (atomic_dec_and_test(&rh->recovery_in_flight))
- wake_up_all(&_kmirrord_recovery_stopped);
- up(&rh->recovery_count);
-}
-
-static void rh_update_states(struct region_hash *rh)
-{
- struct region *reg, *next;
-
- LIST_HEAD(clean);
- LIST_HEAD(recovered);
- LIST_HEAD(failed_recovered);
-
- /*
- * Quickly grab the lists.
- */
- write_lock_irq(&rh->hash_lock);
- spin_lock(&rh->region_lock);
- if (!list_empty(&rh->clean_regions)) {
- list_splice_init(&rh->clean_regions, &clean);
-
- list_for_each_entry(reg, &clean, list)
- list_del(&reg->hash_list);
- }
-
- if (!list_empty(&rh->recovered_regions)) {
- list_splice_init(&rh->recovered_regions, &recovered);
-
- list_for_each_entry (reg, &recovered, list)
- list_del(&reg->hash_list);
- }
-
- if (!list_empty(&rh->failed_recovered_regions)) {
- list_splice_init(&rh->failed_recovered_regions,
- &failed_recovered);
-
- list_for_each_entry(reg, &failed_recovered, list)
- list_del(&reg->hash_list);
- }
-
- spin_unlock(&rh->region_lock);
- write_unlock_irq(&rh->hash_lock);
-
- /*
- * All the regions on the recovered and clean lists have
- * now been pulled out of the system, so no need to do
- * any more locking.
- */
- list_for_each_entry_safe (reg, next, &recovered, list) {
- rh->log->type->clear_region(rh->log, reg->key);
- complete_resync_work(reg, 1);
- mempool_free(reg, rh->region_pool);
- }
-
- list_for_each_entry_safe(reg, next, &failed_recovered, list) {
- complete_resync_work(reg, errors_handled(rh->ms) ? 0 : 1);
- mempool_free(reg, rh->region_pool);
- }
-
- list_for_each_entry_safe(reg, next, &clean, list) {
- rh->log->type->clear_region(rh->log, reg->key);
- mempool_free(reg, rh->region_pool);
- }
-
- rh->log->type->flush(rh->log);
-}
-
-static void rh_inc(struct region_hash *rh, region_t region)
-{
- struct region *reg;
-
- read_lock(&rh->hash_lock);
- reg = __rh_find(rh, region);
-
- spin_lock_irq(&rh->region_lock);
- atomic_inc(&reg->pending);
-
- if (reg->state == RH_CLEAN) {
- reg->state = RH_DIRTY;
- list_del_init(&reg->list); /* take off the clean list */
- spin_unlock_irq(&rh->region_lock);
-
- rh->log->type->mark_region(rh->log, reg->key);
- } else
- spin_unlock_irq(&rh->region_lock);
-
-
- read_unlock(&rh->hash_lock);
-}
-
-static void rh_inc_pending(struct region_hash *rh, struct bio_list *bios)
-{
- struct bio *bio;
-
- for (bio = bios->head; bio; bio = bio->bi_next)
- rh_inc(rh, bio_to_region(rh, bio));
-}
-
-static void rh_dec(struct region_hash *rh, region_t region)
+static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
{
unsigned long flags;
- struct region *reg;
int should_wake = 0;
+ struct bio_list *bl;
- read_lock(&rh->hash_lock);
- reg = __rh_lookup(rh, region);
- read_unlock(&rh->hash_lock);
-
- spin_lock_irqsave(&rh->region_lock, flags);
- if (atomic_dec_and_test(&reg->pending)) {
- /*
- * There is no pending I/O for this region.
- * We can move the region to corresponding list for next action.
- * At this point, the region is not yet connected to any list.
- *
- * If the state is RH_NOSYNC, the region should be kept off
- * from clean list.
- * The hash entry for RH_NOSYNC will remain in memory
- * until the region is recovered or the map is reloaded.
- */
-
- /* do nothing for RH_NOSYNC */
- if (reg->state == RH_RECOVERING) {
- list_add_tail(&reg->list, &rh->quiesced_regions);
- } else if (reg->state == RH_DIRTY) {
- reg->state = RH_CLEAN;
- list_add(&reg->list, &rh->clean_regions);
- }
- should_wake = 1;
- }
- spin_unlock_irqrestore(&rh->region_lock, flags);
+ bl = (rw == WRITE) ? &ms->writes : &ms->reads;
+ spin_lock_irqsave(&ms->lock, flags);
+ should_wake = !(bl->head);
+ bio_list_add(bl, bio);
+ spin_unlock_irqrestore(&ms->lock, flags);
if (should_wake)
- wake(rh->ms);
-}
-
-/*
- * Starts quiescing a region in preparation for recovery.
- */
-static int __rh_recovery_prepare(struct region_hash *rh)
-{
- int r;
- struct region *reg;
- region_t region;
-
- /*
- * Ask the dirty log what's next.
- */
- r = rh->log->type->get_resync_work(rh->log, &region);
- if (r <= 0)
- return r;
-
- /*
- * Get this region, and start it quiescing by setting the
- * recovering flag.
- */
- read_lock(&rh->hash_lock);
- reg = __rh_find(rh, region);
- read_unlock(&rh->hash_lock);
-
- spin_lock_irq(&rh->region_lock);
- reg->state = RH_RECOVERING;
-
- /* Already quiesced ? */
- if (atomic_read(&reg->pending))
- list_del_init(&reg->list);
- else
- list_move(&reg->list, &rh->quiesced_regions);
-
- spin_unlock_irq(&rh->region_lock);
-
- return 1;
-}
-
-static void rh_recovery_prepare(struct region_hash *rh)
-{
- /* Extra reference to avoid race with rh_stop_recovery */
- atomic_inc(&rh->recovery_in_flight);
-
- while (!down_trylock(&rh->recovery_count)) {
- atomic_inc(&rh->recovery_in_flight);
- if (__rh_recovery_prepare(rh) <= 0) {
- atomic_dec(&rh->recovery_in_flight);
- up(&rh->recovery_count);
- break;
- }
- }
-
- /* Drop the extra reference */
- if (atomic_dec_and_test(&rh->recovery_in_flight))
- wake_up_all(&_kmirrord_recovery_stopped);
-}
-
-/*
- * Returns any quiesced regions.
- */
-static struct region *rh_recovery_start(struct region_hash *rh)
-{
- struct region *reg = NULL;
-
- spin_lock_irq(&rh->region_lock);
- if (!list_empty(&rh->quiesced_regions)) {
- reg = list_entry(rh->quiesced_regions.next,
- struct region, list);
- list_del_init(&reg->list); /* remove from the quiesced list */
- }
- spin_unlock_irq(&rh->region_lock);
-
- return reg;
-}
-
-static void rh_recovery_end(struct region *reg, int success)
-{
- struct region_hash *rh = reg->rh;
-
- spin_lock_irq(&rh->region_lock);
- if (success)
- list_add(&reg->list, &reg->rh->recovered_regions);
- else {
- reg->state = RH_NOSYNC;
- list_add(&reg->list, &reg->rh->failed_recovered_regions);
- }
- spin_unlock_irq(&rh->region_lock);
-
- wake(rh->ms);
+ wakeup_mirrord(ms);
}
-static int rh_flush(struct region_hash *rh)
+static void dispatch_bios(void *context, struct bio_list *bio_list)
{
- return rh->log->type->flush(rh->log);
-}
-
-static void rh_delay(struct region_hash *rh, struct bio *bio)
-{
- struct region *reg;
-
- read_lock(&rh->hash_lock);
- reg = __rh_find(rh, bio_to_region(rh, bio));
- bio_list_add(&reg->delayed_bios, bio);
- read_unlock(&rh->hash_lock);
-}
-
-static void rh_stop_recovery(struct region_hash *rh)
-{
- int i;
-
- /* wait for any recovering regions */
- for (i = 0; i < MAX_RECOVERY; i++)
- down(&rh->recovery_count);
-}
-
-static void rh_start_recovery(struct region_hash *rh)
-{
- int i;
-
- for (i = 0; i < MAX_RECOVERY; i++)
- up(&rh->recovery_count);
+ struct mirror_set *ms = context;
+ struct bio *bio;
- wake(rh->ms);
+ while ((bio = bio_list_pop(bio_list)))
+ queue_bio(ms, bio, WRITE);
}
#define MIN_READ_RECORDS 20
@@ -776,8 +246,8 @@ out:
static void recovery_complete(int read_err, unsigned long write_err,
void *context)
{
- struct region *reg = (struct region *)context;
- struct mirror_set *ms = reg->rh->ms;
+ struct dm_region *reg = context;
+ struct mirror_set *ms = dm_rh_region_context(reg);
int m, bit = 0;
if (read_err) {
@@ -803,31 +273,33 @@ static void recovery_complete(int read_err, unsigned long write_err,
}
}
- rh_recovery_end(reg, !(read_err || write_err));
+ dm_rh_recovery_end(reg, !(read_err || write_err));
}
-static int recover(struct mirror_set *ms, struct region *reg)
+static int recover(struct mirror_set *ms, struct dm_region *reg)
{
int r;
- unsigned int i;
+ unsigned i;
struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
struct mirror *m;
unsigned long flags = 0;
+ region_t key = dm_rh_get_region_key(reg);
+ sector_t region_size = dm_rh_get_region_size(ms->rh);
/* fill in the source */
m = get_default_mirror(ms);
from.bdev = m->dev->bdev;
- from.sector = m->offset + region_to_sector(reg->rh, reg->key);
- if (reg->key == (ms->nr_regions - 1)) {
+ from.sector = m->offset + dm_rh_region_to_sector(ms->rh, key);
+ if (key == (ms->nr_regions - 1)) {
/*
* The final region may be smaller than
* region_size.
*/
- from.count = ms->ti->len & (reg->rh->region_size - 1);
+ from.count = ms->ti->len & (region_size - 1);
if (!from.count)
- from.count = reg->rh->region_size;
+ from.count = region_size;
} else
- from.count = reg->rh->region_size;
+ from.count = region_size;
/* fill in the destinations */
for (i = 0, dest = to; i < ms->nr_mirrors; i++) {
@@ -836,7 +308,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
m = ms->mirror + i;
dest->bdev = m->dev->bdev;
- dest->sector = m->offset + region_to_sector(reg->rh, reg->key);
+ dest->sector = m->offset + dm_rh_region_to_sector(ms->rh, key);
dest->count = from.count;
dest++;
}
@@ -853,22 +325,22 @@ static int recover(struct mirror_set *ms, struct region *reg)
static void do_recovery(struct mirror_set *ms)
{
+ struct dm_region *reg;
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
int r;
- struct region *reg;
- struct dm_dirty_log *log = ms->rh.log;
/*
* Start quiescing some regions.
*/
- rh_recovery_prepare(&ms->rh);
+ dm_rh_recovery_prepare(ms->rh);
/*
* Copy any already quiesced regions.
*/
- while ((reg = rh_recovery_start(&ms->rh))) {
+ while ((reg = dm_rh_recovery_start(ms->rh))) {
r = recover(ms, reg);
if (r)
- rh_recovery_end(reg, 0);
+ dm_rh_recovery_end(reg, 0);
}
/*
@@ -909,9 +381,10 @@ static int default_ok(struct mirror *m)
static int mirror_available(struct mirror_set *ms, struct bio *bio)
{
- region_t region = bio_to_region(&ms->rh, bio);
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
+ region_t region = dm_rh_bio_to_region(ms->rh, bio);
- if (ms->rh.log->type->in_sync(ms->rh.log, region, 0))
+ if (log->type->in_sync(log, region, 0))
return choose_mirror(ms, bio->bi_sector) ? 1 : 0;
return 0;
@@ -985,7 +458,14 @@ static void read_async_bio(struct mirror *m, struct bio *bio)
map_region(&io, m, bio);
bio_set_m(bio, m);
- (void) dm_io(&io_req, 1, &io, NULL);
+ BUG_ON(dm_io(&io_req, 1, &io, NULL));
+}
+
+static inline int region_in_sync(struct mirror_set *ms, region_t region,
+ int may_block)
+{
+ int state = dm_rh_get_state(ms->rh, region, may_block);
+ return state == DM_RH_CLEAN || state == DM_RH_DIRTY;
}
static void do_reads(struct mirror_set *ms, struct bio_list *reads)
@@ -995,13 +475,13 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
struct mirror *m;
while ((bio = bio_list_pop(reads))) {
- region = bio_to_region(&ms->rh, bio);
+ region = dm_rh_bio_to_region(ms->rh, bio);
m = get_default_mirror(ms);
/*
* We can only read balance if the region is in sync.
*/
- if (likely(rh_in_sync(&ms->rh, region, 1)))
+ if (likely(region_in_sync(ms, region, 1)))
m = choose_mirror(ms, bio->bi_sector);
else if (m && atomic_read(&m->error_count))
m = NULL;
@@ -1024,57 +504,6 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
* NOSYNC: increment pending, just write to the default mirror
*---------------------------------------------------------------*/
-/* __bio_mark_nosync
- * @ms
- * @bio
- * @done
- * @error
- *
- * The bio was written on some mirror(s) but failed on other mirror(s).
- * We can successfully endio the bio but should avoid the region being
- * marked clean by setting the state RH_NOSYNC.
- *
- * This function is _not_ safe in interrupt context!
- */
-static void __bio_mark_nosync(struct mirror_set *ms,
- struct bio *bio, unsigned done, int error)
-{
- unsigned long flags;
- struct region_hash *rh = &ms->rh;
- struct dm_dirty_log *log = ms->rh.log;
- struct region *reg;
- region_t region = bio_to_region(rh, bio);
- int recovering = 0;
-
- /* We must inform the log that the sync count has changed. */
- log->type->set_region_sync(log, region, 0);
- ms->in_sync = 0;
-
- read_lock(&rh->hash_lock);
- reg = __rh_find(rh, region);
- read_unlock(&rh->hash_lock);
-
- /* region hash entry should exist because write was in-flight */
- BUG_ON(!reg);
- BUG_ON(!list_empty(&reg->list));
-
- spin_lock_irqsave(&rh->region_lock, flags);
- /*
- * Possible cases:
- * 1) RH_DIRTY
- * 2) RH_NOSYNC: was dirty, other preceeding writes failed
- * 3) RH_RECOVERING: flushing pending writes
- * Either case, the region should have not been connected to list.
- */
- recovering = (reg->state == RH_RECOVERING);
- reg->state = RH_NOSYNC;
- BUG_ON(!list_empty(&reg->list));
- spin_unlock_irqrestore(&rh->region_lock, flags);
-
- bio_endio(bio, error);
- if (recovering)
- complete_resync_work(reg, 0);
-}
static void write_callback(unsigned long error, void *context)
{
@@ -1119,7 +548,7 @@ static void write_callback(unsigned long error, void *context)
bio_list_add(&ms->failures, bio);
spin_unlock_irqrestore(&ms->lock, flags);
if (should_wake)
- wake(ms);
+ wakeup_mirrord(ms);
return;
}
out:
@@ -1149,7 +578,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
*/
bio_set_m(bio, get_default_mirror(ms));
- (void) dm_io(&io_req, ms->nr_mirrors, io, NULL);
+ BUG_ON(dm_io(&io_req, ms->nr_mirrors, io, NULL));
}
static void do_writes(struct mirror_set *ms, struct bio_list *writes)
@@ -1169,18 +598,19 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
bio_list_init(&recover);
while ((bio = bio_list_pop(writes))) {
- state = rh_state(&ms->rh, bio_to_region(&ms->rh, bio), 1);
+ state = dm_rh_get_state(ms->rh,
+ dm_rh_bio_to_region(ms->rh, bio), 1);
switch (state) {
- case RH_CLEAN:
- case RH_DIRTY:
+ case DM_RH_CLEAN:
+ case DM_RH_DIRTY:
this_list = &sync;
break;
- case RH_NOSYNC:
+ case DM_RH_NOSYNC:
this_list = &nosync;
break;
- case RH_RECOVERING:
+ case DM_RH_RECOVERING:
this_list = &recover;
break;
}
@@ -1193,9 +623,9 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
* be written to (writes to recover regions are going to
* be delayed).
*/
- rh_inc_pending(&ms->rh, &sync);
- rh_inc_pending(&ms->rh, &nosync);
- ms->log_failure = rh_flush(&ms->rh) ? 1 : 0;
+ dm_rh_inc_pending(ms->rh, &sync);
+ dm_rh_inc_pending(ms->rh, &nosync);
+ ms->log_failure = dm_rh_flush(ms->rh) ? 1 : 0;
/*
* Dispatch io.
@@ -1204,13 +634,13 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
spin_lock_irq(&ms->lock);
bio_list_merge(&ms->failures, &sync);
spin_unlock_irq(&ms->lock);
- wake(ms);
+ wakeup_mirrord(ms);
} else
while ((bio = bio_list_pop(&sync)))
do_write(ms, bio);
while ((bio = bio_list_pop(&recover)))
- rh_delay(&ms->rh, bio);
+ dm_rh_delay(ms->rh, bio);
while ((bio = bio_list_pop(&nosync))) {
map_bio(get_default_mirror(ms), bio);
@@ -1227,7 +657,8 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures)
if (!ms->log_failure) {
while ((bio = bio_list_pop(failures)))
- __bio_mark_nosync(ms, bio, bio->bi_size, 0);
+ ms->in_sync = 0;
+ dm_rh_mark_nosync(ms->rh, bio, bio->bi_size, 0);
return;
}
@@ -1280,8 +711,8 @@ static void trigger_event(struct work_struct *work)
*---------------------------------------------------------------*/
static void do_mirror(struct work_struct *work)
{
- struct mirror_set *ms =container_of(work, struct mirror_set,
- kmirrord_work);
+ struct mirror_set *ms = container_of(work, struct mirror_set,
+ kmirrord_work);
struct bio_list reads, writes, failures;
unsigned long flags;
@@ -1294,7 +725,7 @@ static void do_mirror(struct work_struct *work)
bio_list_init(&ms->failures);
spin_unlock_irqrestore(&ms->lock, flags);
- rh_update_states(&ms->rh);
+ dm_rh_update_states(ms->rh, errors_handled(ms));
do_recovery(ms);
do_reads(ms, &reads);
do_writes(ms, &writes);
@@ -1303,7 +734,6 @@ static void do_mirror(struct work_struct *work)
dm_table_unplug_all(ms->ti->table);
}
-
/*-----------------------------------------------------------------
* Target functions
*---------------------------------------------------------------*/
@@ -1315,9 +745,6 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
size_t len;
struct mirror_set *ms = NULL;
- if (array_too_big(sizeof(*ms), sizeof(ms->mirror[0]), nr_mirrors))
- return NULL;
-
len = sizeof(*ms) + (sizeof(ms->mirror[0]) * nr_mirrors);
ms = kzalloc(len, GFP_KERNEL);
@@ -1353,7 +780,11 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
return NULL;
}
- if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
+ ms->rh = dm_region_hash_create(ms, dispatch_bios, wakeup_mirrord,
+ wakeup_all_recovery_waiters,
+ ms->ti->begin, MAX_RECOVERY,
+ dl, region_size, ms->nr_regions);
+ if (IS_ERR(ms->rh)) {
ti->error = "Error creating dirty region hash";
dm_io_client_destroy(ms->io_client);
mempool_destroy(ms->read_record_pool);
@@ -1371,7 +802,7 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
dm_put_device(ti, ms->mirror[m].dev);
dm_io_client_destroy(ms->io_client);
- rh_exit(&ms->rh);
+ dm_region_hash_destroy(ms->rh);
mempool_destroy(ms->read_record_pool);
kfree(ms);
}
@@ -1411,10 +842,10 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
* Create dirty log: log_type #log_params <log_params>
*/
static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
- unsigned int argc, char **argv,
- unsigned int *args_used)
+ unsigned argc, char **argv,
+ unsigned *args_used)
{
- unsigned int param_count;
+ unsigned param_count;
struct dm_dirty_log *dl;
if (argc < 2) {
@@ -1545,7 +976,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
ti->private = ms;
- ti->split_io = ms->rh.region_size;
+ ti->split_io = dm_rh_get_region_size(ms->rh);
ms->kmirrord_wq = create_singlethread_workqueue("kmirrord");
if (!ms->kmirrord_wq) {
@@ -1580,11 +1011,11 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto err_destroy_wq;
}
- r = dm_kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
+ r = dm_kcopyd_client_create(DM_KCOPYD_PAGES, &ms->kcopyd_client);
if (r)
goto err_destroy_wq;
- wake(ms);
+ wakeup_mirrord(ms);
return 0;
err_destroy_wq:
@@ -1605,22 +1036,6 @@ static void mirror_dtr(struct dm_target *ti)
free_context(ms, ti, ms->nr_mirrors);
}
-static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
-{
- unsigned long flags;
- int should_wake = 0;
- struct bio_list *bl;
-
- bl = (rw == WRITE) ? &ms->writes : &ms->reads;
- spin_lock_irqsave(&ms->lock, flags);
- should_wake = !(bl->head);
- bio_list_add(bl, bio);
- spin_unlock_irqrestore(&ms->lock, flags);
-
- if (should_wake)
- wake(ms);
-}
-
/*
* Mirror mapping function
*/
@@ -1631,16 +1046,16 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
struct mirror *m;
struct mirror_set *ms = ti->private;
struct dm_raid1_read_record *read_record = NULL;
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
if (rw == WRITE) {
/* Save region for mirror_end_io() handler */
- map_context->ll = bio_to_region(&ms->rh, bio);
+ map_context->ll = dm_rh_bio_to_region(ms->rh, bio);
queue_bio(ms, bio, rw);
return DM_MAPIO_SUBMITTED;
}
- r = ms->rh.log->type->in_sync(ms->rh.log,
- bio_to_region(&ms->rh, bio), 0);
+ r = log->type->in_sync(log, dm_rh_bio_to_region(ms->rh, bio), 0);
if (r < 0 && r != -EWOULDBLOCK)
return r;
@@ -1688,7 +1103,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
* We need to dec pending if this was a write.
*/
if (rw == WRITE) {
- rh_dec(&ms->rh, map_context->ll);
+ dm_rh_dec(ms->rh, map_context->ll);
return error;
}
@@ -1744,7 +1159,7 @@ out:
static void mirror_presuspend(struct dm_target *ti)
{
struct mirror_set *ms = (struct mirror_set *) ti->private;
- struct dm_dirty_log *log = ms->rh.log;
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
atomic_set(&ms->suspend, 1);
@@ -1752,10 +1167,10 @@ static void mirror_presuspend(struct dm_target *ti)
* We must finish up all the work that we've
* generated (i.e. recovery work).
*/
- rh_stop_recovery(&ms->rh);
+ dm_rh_stop_recovery(ms->rh);
wait_event(_kmirrord_recovery_stopped,
- !atomic_read(&ms->rh.recovery_in_flight));
+ !dm_rh_recovery_in_flight(ms->rh));
if (log->type->presuspend && log->type->presuspend(log))
/* FIXME: need better error handling */
@@ -1773,7 +1188,7 @@ static void mirror_presuspend(struct dm_target *ti)
static void mirror_postsuspend(struct dm_target *ti)
{
struct mirror_set *ms = ti->private;
- struct dm_dirty_log *log = ms->rh.log;
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
if (log->type->postsuspend && log->type->postsuspend(log))
/* FIXME: need better error handling */
@@ -1783,13 +1198,13 @@ static void mirror_postsuspend(struct dm_target *ti)
static void mirror_resume(struct dm_target *ti)
{
struct mirror_set *ms = ti->private;
- struct dm_dirty_log *log = ms->rh.log;
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
atomic_set(&ms->suspend, 0);
if (log->type->resume && log->type->resume(log))
/* FIXME: need better error handling */
DMWARN("log resume failed");
- rh_start_recovery(&ms->rh);
+ dm_rh_start_recovery(ms->rh);
}
/*
@@ -1821,7 +1236,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
{
unsigned int m, sz = 0;
struct mirror_set *ms = (struct mirror_set *) ti->private;
- struct dm_dirty_log *log = ms->rh.log;
+ struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
char buffer[ms->nr_mirrors + 1];
switch (type) {
@@ -1834,15 +1249,15 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
buffer[m] = '\0';
DMEMIT("%llu/%llu 1 %s ",
- (unsigned long long)log->type->get_sync_count(ms->rh.log),
+ (unsigned long long)log->type->get_sync_count(log),
(unsigned long long)ms->nr_regions, buffer);
- sz += log->type->status(ms->rh.log, type, result+sz, maxlen-sz);
+ sz += log->type->status(log, type, result+sz, maxlen-sz);
break;
case STATUSTYPE_TABLE:
- sz = log->type->status(ms->rh.log, type, result, maxlen);
+ sz = log->type->status(log, type, result, maxlen);
DMEMIT("%d", ms->nr_mirrors);
for (m = 0; m < ms->nr_mirrors; m++)
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
new file mode 100644
index 00000000000..59f8d9df9e1
--- /dev/null
+++ b/drivers/md/dm-region-hash.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/dm-dirty-log.h>
+#include <linux/dm-region-hash.h>
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include "dm.h"
+#include "dm-bio-list.h"
+
+#define DM_MSG_PREFIX "region hash"
+
+/*-----------------------------------------------------------------
+ * Region hash
+ *
+ * The mirror splits itself up into discrete regions. Each
+ * region can be in one of three states: clean, dirty,
+ * nosync. There is no need to put clean regions in the hash.
+ *
+ * In addition to being present in the hash table a region _may_
+ * be present on one of three lists.
+ *
+ * clean_regions: Regions on this list have no io pending to
+ * them, they are in sync, we are no longer interested in them,
+ * they are dull. dm_rh_update_states() will remove them from the
+ * hash table.
+ *
+ * quiesced_regions: These regions have been spun down, ready
+ * for recovery. rh_recovery_start() will remove regions from
+ * this list and hand them to kmirrord, which will schedule the
+ * recovery io with kcopyd.
+ *
+ * recovered_regions: Regions that kcopyd has successfully
+ * recovered. dm_rh_update_states() will now schedule any delayed
+ * io, up the recovery_count, and remove the region from the
+ * hash.
+ *
+ * There are 2 locks:
+ * A rw spin lock 'hash_lock' protects just the hash table,
+ * this is never held in write mode from interrupt context,
+ * which I believe means that we only have to disable irqs when
+ * doing a write lock.
+ *
+ * An ordinary spin lock 'region_lock' that protects the three
+ * lists in the region_hash, with the 'state', 'list' and
+ * 'delayed_bios' fields of the regions. This is used from irq
+ * context, so all other uses will have to suspend local irqs.
+ *---------------------------------------------------------------*/
+struct dm_region_hash {
+ uint32_t region_size;
+ unsigned region_shift;
+
+ /* holds persistent region state */
+ struct dm_dirty_log *log;
+
+ /* hash table */
+ rwlock_t hash_lock;
+ mempool_t *region_pool;
+ unsigned mask;
+ unsigned nr_buckets;
+ unsigned prime;
+ unsigned shift;
+ struct list_head *buckets;
+
+ unsigned max_recovery; /* Max # of regions to recover in parallel */
+
+ spinlock_t region_lock;
+ atomic_t recovery_in_flight;
+ struct semaphore recovery_count;
+ struct list_head clean_regions;
+ struct list_head quiesced_regions;
+ struct list_head recovered_regions;
+ struct list_head failed_recovered_regions;
+
+ void *context;
+ sector_t target_begin;
+
+ /* Callback function to schedule bios writes */
+ void (*dispatch_bios)(void *context, struct bio_list *bios);
+
+ /* Callback function to wakeup callers worker thread. */
+ void (*wakeup_workers)(void *context);
+
+ /* Callback function to wakeup callers recovery waiters. */
+ void (*wakeup_all_recovery_waiters)(void *context);
+};
+
+struct dm_region {
+ struct dm_region_hash *rh; /* FIXME: can we get rid of this ? */
+ region_t key;
+ int state;
+
+ struct list_head hash_list;
+ struct list_head list;
+
+ atomic_t pending;
+ struct bio_list delayed_bios;
+};
+
+/*
+ * Conversion fns
+ */
+static region_t dm_rh_sector_to_region(struct dm_region_hash *rh, sector_t sector)
+{
+ return sector >> rh->region_shift;
+}
+
+sector_t dm_rh_region_to_sector(struct dm_region_hash *rh, region_t region)
+{
+ return region << rh->region_shift;
+}
+EXPORT_SYMBOL_GPL(dm_rh_region_to_sector);
+
+region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio)
+{
+ return dm_rh_sector_to_region(rh, bio->bi_sector - rh->target_begin);
+}
+EXPORT_SYMBOL_GPL(dm_rh_bio_to_region);
+
+void *dm_rh_region_context(struct dm_region *reg)
+{
+ return reg->rh->context;
+}
+EXPORT_SYMBOL_GPL(dm_rh_region_context);
+
+region_t dm_rh_get_region_key(struct dm_region *reg)
+{
+ return reg->key;
+}
+EXPORT_SYMBOL_GPL(dm_rh_get_region_key);
+
+sector_t dm_rh_get_region_size(struct dm_region_hash *rh)
+{
+ return rh->region_size;
+}
+EXPORT_SYMBOL_GPL(dm_rh_get_region_size);
+
+/*
+ * FIXME: shall we pass in a structure instead of all these args to
+ * dm_region_hash_create()????
+ */
+#define RH_HASH_MULT 2654435387U
+#define RH_HASH_SHIFT 12
+
+#define MIN_REGIONS 64
+struct dm_region_hash *dm_region_hash_create(
+ void *context, void (*dispatch_bios)(void *context,
+ struct bio_list *bios),
+ void (*wakeup_workers)(void *context),
+ void (*wakeup_all_recovery_waiters)(void *context),
+ sector_t target_begin, unsigned max_recovery,
+ struct dm_dirty_log *log, uint32_t region_size,
+ region_t nr_regions)
+{
+ struct dm_region_hash *rh;
+ unsigned nr_buckets, max_buckets;
+ size_t i;
+
+ /*
+ * Calculate a suitable number of buckets for our hash
+ * table.
+ */
+ max_buckets = nr_regions >> 6;
+ for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1)
+ ;
+ nr_buckets >>= 1;
+
+ rh = kmalloc(sizeof(*rh), GFP_KERNEL);
+ if (!rh) {
+ DMERR("unable to allocate region hash memory");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rh->context = context;
+ rh->dispatch_bios = dispatch_bios;
+ rh->wakeup_workers = wakeup_workers;
+ rh->wakeup_all_recovery_waiters = wakeup_all_recovery_waiters;
+ rh->target_begin = target_begin;
+ rh->max_recovery = max_recovery;
+ rh->log = log;
+ rh->region_size = region_size;
+ rh->region_shift = ffs(region_size) - 1;
+ rwlock_init(&rh->hash_lock);
+ rh->mask = nr_buckets - 1;
+ rh->nr_buckets = nr_buckets;
+
+ rh->shift = RH_HASH_SHIFT;
+ rh->prime = RH_HASH_MULT;
+
+ rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets));
+ if (!rh->buckets) {
+ DMERR("unable to allocate region hash bucket memory");
+ kfree(rh);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (i = 0; i < nr_buckets; i++)
+ INIT_LIST_HEAD(rh->buckets + i);
+
+ spin_lock_init(&rh->region_lock);
+ sema_init(&rh->recovery_count, 0);
+ atomic_set(&rh->recovery_in_flight, 0);
+ INIT_LIST_HEAD(&rh->clean_regions);
+ INIT_LIST_HEAD(&rh->quiesced_regions);
+ INIT_LIST_HEAD(&rh->recovered_regions);
+ INIT_LIST_HEAD(&rh->failed_recovered_regions);
+
+ rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
+ sizeof(struct dm_region));
+ if (!rh->region_pool) {
+ vfree(rh->buckets);
+ kfree(rh);
+ rh = ERR_PTR(-ENOMEM);
+ }
+
+ return rh;
+}
+EXPORT_SYMBOL_GPL(dm_region_hash_create);
+
+void dm_region_hash_destroy(struct dm_region_hash *rh)
+{
+ unsigned h;
+ struct dm_region *reg, *nreg;
+
+ BUG_ON(!list_empty(&rh->quiesced_regions));
+ for (h = 0; h < rh->nr_buckets; h++) {
+ list_for_each_entry_safe(reg, nreg, rh->buckets + h,
+ hash_list) {
+ BUG_ON(atomic_read(&reg->pending));
+ mempool_free(reg, rh->region_pool);
+ }
+ }
+
+ if (rh->log)
+ dm_dirty_log_destroy(rh->log);
+
+ if (rh->region_pool)
+ mempool_destroy(rh->region_pool);
+
+ vfree(rh->buckets);
+ kfree(rh);
+}
+EXPORT_SYMBOL_GPL(dm_region_hash_destroy);
+
+struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh)
+{
+ return rh->log;
+}
+EXPORT_SYMBOL_GPL(dm_rh_dirty_log);
+
+static unsigned rh_hash(struct dm_region_hash *rh, region_t region)
+{
+ return (unsigned) ((region * rh->prime) >> rh->shift) & rh->mask;
+}
+
+static struct dm_region *__rh_lookup(struct dm_region_hash *rh, region_t region)
+{
+ struct dm_region *reg;
+ struct list_head *bucket = rh->buckets + rh_hash(rh, region);
+
+ list_for_each_entry(reg, bucket, hash_list)
+ if (reg->key == region)
+ return reg;
+
+ return NULL;
+}
+
+static void __rh_insert(struct dm_region_hash *rh, struct dm_region *reg)
+{
+ list_add(&reg->hash_list, rh->buckets + rh_hash(rh, reg->key));
+}
+
+static struct dm_region *__rh_alloc(struct dm_region_hash *rh, region_t region)
+{
+ struct dm_region *reg, *nreg;
+
+ nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
+ if (unlikely(!nreg))
+ nreg = kmalloc(sizeof(*nreg), GFP_NOIO);
+
+ nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
+ DM_RH_CLEAN : DM_RH_NOSYNC;
+ nreg->rh = rh;
+ nreg->key = region;
+ INIT_LIST_HEAD(&nreg->list);
+ atomic_set(&nreg->pending, 0);
+ bio_list_init(&nreg->delayed_bios);
+
+ write_lock_irq(&rh->hash_lock);
+ reg = __rh_lookup(rh, region);
+ if (reg)
+ /* We lost the race. */
+ mempool_free(nreg, rh->region_pool);
+ else {
+ __rh_insert(rh, nreg);
+ if (nreg->state == DM_RH_CLEAN) {
+ spin_lock(&rh->region_lock);
+ list_add(&nreg->list, &rh->clean_regions);
+ spin_unlock(&rh->region_lock);
+ }
+
+ reg = nreg;
+ }
+ write_unlock_irq(&rh->hash_lock);
+
+ return reg;
+}
+
+static struct dm_region *__rh_find(struct dm_region_hash *rh, region_t region)
+{
+ struct dm_region *reg;
+
+ reg = __rh_lookup(rh, region);
+ if (!reg) {
+ read_unlock(&rh->hash_lock);
+ reg = __rh_alloc(rh, region);
+ read_lock(&rh->hash_lock);
+ }
+
+ return reg;
+}
+
+int dm_rh_get_state(struct dm_region_hash *rh, region_t region, int may_block)
+{
+ int r;
+ struct dm_region *reg;
+
+ read_lock(&rh->hash_lock);
+ reg = __rh_lookup(rh, region);
+ read_unlock(&rh->hash_lock);
+
+ if (reg)
+ return reg->state;
+
+ /*
+ * The region wasn't in the hash, so we fall back to the
+ * dirty log.
+ */
+ r = rh->log->type->in_sync(rh->log, region, may_block);
+
+ /*
+ * Any error from the dirty log (eg. -EWOULDBLOCK) gets
+ * taken as a DM_RH_NOSYNC
+ */
+ return r == 1 ? DM_RH_CLEAN : DM_RH_NOSYNC;
+}
+EXPORT_SYMBOL_GPL(dm_rh_get_state);
+
+static void complete_resync_work(struct dm_region *reg, int success)
+{
+ struct dm_region_hash *rh = reg->rh;
+
+ rh->log->type->set_region_sync(rh->log, reg->key, success);
+
+ /*
+ * Dispatch the bios before we call 'wake_up_all'.
+ * This is important because if we are suspending,
+ * we want to know that recovery is complete and
+ * the work queue is flushed. If we wake_up_all
+ * before we dispatch_bios (queue bios and call wake()),
+ * then we risk suspending before the work queue
+ * has been properly flushed.
+ */
+ rh->dispatch_bios(rh->context, &reg->delayed_bios);
+ if (atomic_dec_and_test(&rh->recovery_in_flight))
+ rh->wakeup_all_recovery_waiters(rh->context);
+ up(&rh->recovery_count);
+}
+
+/* dm_rh_mark_nosync
+ * @ms
+ * @bio
+ * @done
+ * @error
+ *
+ * The bio was written on some mirror(s) but failed on other mirror(s).
+ * We can successfully endio the bio but should avoid the region being
+ * marked clean by setting the state DM_RH_NOSYNC.
+ *
+ * This function is _not_ safe in interrupt context!
+ */
+void dm_rh_mark_nosync(struct dm_region_hash *rh,
+ struct bio *bio, unsigned done, int error)
+{
+ unsigned long flags;
+ struct dm_dirty_log *log = rh->log;
+ struct dm_region *reg;
+ region_t region = dm_rh_bio_to_region(rh, bio);
+ int recovering = 0;
+
+ /* We must inform the log that the sync count has changed. */
+ log->type->set_region_sync(log, region, 0);
+
+ read_lock(&rh->hash_lock);
+ reg = __rh_find(rh, region);
+ read_unlock(&rh->hash_lock);
+
+ /* region hash entry should exist because write was in-flight */
+ BUG_ON(!reg);
+ BUG_ON(!list_empty(&reg->list));
+
+ spin_lock_irqsave(&rh->region_lock, flags);
+ /*
+ * Possible cases:
+ * 1) DM_RH_DIRTY
+ * 2) DM_RH_NOSYNC: was dirty, other preceeding writes failed
+ * 3) DM_RH_RECOVERING: flushing pending writes
+ * Either case, the region should have not been connected to list.
+ */
+ recovering = (reg->state == DM_RH_RECOVERING);
+ reg->state = DM_RH_NOSYNC;
+ BUG_ON(!list_empty(&reg->list));
+ spin_unlock_irqrestore(&rh->region_lock, flags);
+
+ bio_endio(bio, error);
+ if (recovering)
+ complete_resync_work(reg, 0);
+}
+EXPORT_SYMBOL_GPL(dm_rh_mark_nosync);
+
+void dm_rh_update_states(struct dm_region_hash *rh, int errors_handled)
+{
+ struct dm_region *reg, *next;
+
+ LIST_HEAD(clean);
+ LIST_HEAD(recovered);
+ LIST_HEAD(failed_recovered);
+
+ /*
+ * Quickly grab the lists.
+ */
+ write_lock_irq(&rh->hash_lock);
+ spin_lock(&rh->region_lock);
+ if (!list_empty(&rh->clean_regions)) {
+ list_splice_init(&rh->clean_regions, &clean);
+
+ list_for_each_entry(reg, &clean, list)
+ list_del(&reg->hash_list);
+ }
+
+ if (!list_empty(&rh->recovered_regions)) {
+ list_splice_init(&rh->recovered_regions, &recovered);
+
+ list_for_each_entry(reg, &recovered, list)
+ list_del(&reg->hash_list);
+ }
+
+ if (!list_empty(&rh->failed_recovered_regions)) {
+ list_splice_init(&rh->failed_recovered_regions,
+ &failed_recovered);
+
+ list_for_each_entry(reg, &failed_recovered, list)
+ list_del(&reg->hash_list);
+ }
+
+ spin_unlock(&rh->region_lock);
+ write_unlock_irq(&rh->hash_lock);
+
+ /*
+ * All the regions on the recovered and clean lists have
+ * now been pulled out of the system, so no need to do
+ * any more locking.
+ */
+ list_for_each_entry_safe(reg, next, &recovered, list) {
+ rh->log->type->clear_region(rh->log, reg->key);
+ complete_resync_work(reg, 1);
+ mempool_free(reg, rh->region_pool);
+ }
+
+ list_for_each_entry_safe(reg, next, &failed_recovered, list) {
+ complete_resync_work(reg, errors_handled ? 0 : 1);
+ mempool_free(reg, rh->region_pool);
+ }
+
+ list_for_each_entry_safe(reg, next, &clean, list) {
+ rh->log->type->clear_region(rh->log, reg->key);
+ mempool_free(reg, rh->region_pool);
+ }
+
+ rh->log->type->flush(rh->log);
+}
+EXPORT_SYMBOL_GPL(dm_rh_update_states);
+
+static void rh_inc(struct dm_region_hash *rh, region_t region)
+{
+ struct dm_region *reg;
+
+ read_lock(&rh->hash_lock);
+ reg = __rh_find(rh, region);
+
+ spin_lock_irq(&rh->region_lock);
+ atomic_inc(&reg->pending);
+
+ if (reg->state == DM_RH_CLEAN) {
+ reg->state = DM_RH_DIRTY;
+ list_del_init(&reg->list); /* take off the clean list */
+ spin_unlock_irq(&rh->region_lock);
+
+ rh->log->type->mark_region(rh->log, reg->key);
+ } else
+ spin_unlock_irq(&rh->region_lock);
+
+
+ read_unlock(&rh->hash_lock);
+}
+
+void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
+{
+ struct bio *bio;
+
+ for (bio = bios->head; bio; bio = bio->bi_next)
+ rh_inc(rh, dm_rh_bio_to_region(rh, bio));
+}
+EXPORT_SYMBOL_GPL(dm_rh_inc_pending);
+
+void dm_rh_dec(struct dm_region_hash *rh, region_t region)
+{
+ unsigned long flags;
+ struct dm_region *reg;
+ int should_wake = 0;
+
+ read_lock(&rh->hash_lock);
+ reg = __rh_lookup(rh, region);
+ read_unlock(&rh->hash_lock);
+
+ spin_lock_irqsave(&rh->region_lock, flags);
+ if (atomic_dec_and_test(&reg->pending)) {
+ /*
+ * There is no pending I/O for this region.
+ * We can move the region to corresponding list for next action.
+ * At this point, the region is not yet connected to any list.
+ *
+ * If the state is DM_RH_NOSYNC, the region should be kept off
+ * from clean list.
+ * The hash entry for DM_RH_NOSYNC will remain in memory
+ * until the region is recovered or the map is reloaded.
+ */
+
+ /* do nothing for DM_RH_NOSYNC */
+ if (reg->state == DM_RH_RECOVERING) {
+ list_add_tail(&reg->list, &rh->quiesced_regions);
+ } else if (reg->state == DM_RH_DIRTY) {
+ reg->state = DM_RH_CLEAN;
+ list_add(&reg->list, &rh->clean_regions);
+ }
+ should_wake = 1;
+ }
+ spin_unlock_irqrestore(&rh->region_lock, flags);
+
+ if (should_wake)
+ rh->wakeup_workers(rh->context);
+}
+EXPORT_SYMBOL_GPL(dm_rh_dec);
+
+/*
+ * Starts quiescing a region in preparation for recovery.
+ */
+static int __rh_recovery_prepare(struct dm_region_hash *rh)
+{
+ int r;
+ region_t region;
+ struct dm_region *reg;
+
+ /*
+ * Ask the dirty log what's next.
+ */
+ r = rh->log->type->get_resync_work(rh->log, &region);
+ if (r <= 0)
+ return r;
+
+ /*
+ * Get this region, and start it quiescing by setting the
+ * recovering flag.
+ */
+ read_lock(&rh->hash_lock);
+ reg = __rh_find(rh, region);
+ read_unlock(&rh->hash_lock);
+
+ spin_lock_irq(&rh->region_lock);
+ reg->state = DM_RH_RECOVERING;
+
+ /* Already quiesced ? */
+ if (atomic_read(&reg->pending))
+ list_del_init(&reg->list);
+ else
+ list_move(&reg->list, &rh->quiesced_regions);
+
+ spin_unlock_irq(&rh->region_lock);
+
+ return 1;
+}
+
+void dm_rh_recovery_prepare(struct dm_region_hash *rh)
+{
+ /* Extra reference to avoid race with dm_rh_stop_recovery */
+ atomic_inc(&rh->recovery_in_flight);
+
+ while (!down_trylock(&rh->recovery_count)) {
+ atomic_inc(&rh->recovery_in_flight);
+ if (__rh_recovery_prepare(rh) <= 0) {
+ atomic_dec(&rh->recovery_in_flight);
+ up(&rh->recovery_count);
+ break;
+ }
+ }
+
+ /* Drop the extra reference */
+ if (atomic_dec_and_test(&rh->recovery_in_flight))
+ rh->wakeup_all_recovery_waiters(rh->context);
+}
+EXPORT_SYMBOL_GPL(dm_rh_recovery_prepare);
+
+/*
+ * Returns any quiesced regions.
+ */
+struct dm_region *dm_rh_recovery_start(struct dm_region_hash *rh)
+{
+ struct dm_region *reg = NULL;
+
+ spin_lock_irq(&rh->region_lock);
+ if (!list_empty(&rh->quiesced_regions)) {
+ reg = list_entry(rh->quiesced_regions.next,
+ struct dm_region, list);
+ list_del_init(&reg->list); /* remove from the quiesced list */
+ }
+ spin_unlock_irq(&rh->region_lock);
+
+ return reg;
+}
+EXPORT_SYMBOL_GPL(dm_rh_recovery_start);
+
+void dm_rh_recovery_end(struct dm_region *reg, int success)
+{
+ struct dm_region_hash *rh = reg->rh;
+
+ spin_lock_irq(&rh->region_lock);
+ if (success)
+ list_add(&reg->list, &reg->rh->recovered_regions);
+ else {
+ reg->state = DM_RH_NOSYNC;
+ list_add(&reg->list, &reg->rh->failed_recovered_regions);
+ }
+ spin_unlock_irq(&rh->region_lock);
+
+ rh->wakeup_workers(rh->context);
+}
+EXPORT_SYMBOL_GPL(dm_rh_recovery_end);
+
+/* Return recovery in flight count. */
+int dm_rh_recovery_in_flight(struct dm_region_hash *rh)
+{
+ return atomic_read(&rh->recovery_in_flight);
+}
+EXPORT_SYMBOL_GPL(dm_rh_recovery_in_flight);
+
+int dm_rh_flush(struct dm_region_hash *rh)
+{
+ return rh->log->type->flush(rh->log);
+}
+EXPORT_SYMBOL_GPL(dm_rh_flush);
+
+void dm_rh_delay(struct dm_region_hash *rh, struct bio *bio)
+{
+ struct dm_region *reg;
+
+ read_lock(&rh->hash_lock);
+ reg = __rh_find(rh, dm_rh_bio_to_region(rh, bio));
+ bio_list_add(&reg->delayed_bios, bio);
+ read_unlock(&rh->hash_lock);
+}
+EXPORT_SYMBOL_GPL(dm_rh_delay);
+
+void dm_rh_stop_recovery(struct dm_region_hash *rh)
+{
+ int i;
+
+ /* wait for any recovering regions */
+ for (i = 0; i < rh->max_recovery; i++)
+ down(&rh->recovery_count);
+}
+EXPORT_SYMBOL_GPL(dm_rh_stop_recovery);
+
+void dm_rh_start_recovery(struct dm_region_hash *rh)
+{
+ int i;
+
+ for (i = 0; i < rh->max_recovery; i++)
+ up(&rh->recovery_count);
+
+ rh->wakeup_workers(rh->context);
+}
+EXPORT_SYMBOL_GPL(dm_rh_start_recovery);
+
+MODULE_DESCRIPTION(DM_NAME " region hash");
+MODULE_AUTHOR("Joe Thornber/Heinz Mauelshagen <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
index 391dfa2ad43..cdfbf65b28c 100644
--- a/drivers/md/dm-round-robin.c
+++ b/drivers/md/dm-round-robin.c
@@ -9,7 +9,8 @@
* Round-robin path selector.
*/
-#include "dm.h"
+#include <linux/device-mapper.h>
+
#include "dm-path-selector.h"
#include <linux/slab.h>
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 6e5528aecc9..b2d9d1ac28a 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -600,7 +600,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
s->valid = 1;
s->active = 0;
- s->last_percent = 0;
init_rwsem(&s->lock);
spin_lock_init(&s->pe_lock);
s->ti = ti;
@@ -824,8 +823,10 @@ static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe)
* the bios for the original write to the origin.
*/
if (primary_pe &&
- atomic_dec_and_test(&primary_pe->ref_count))
+ atomic_dec_and_test(&primary_pe->ref_count)) {
origin_bios = bio_list_get(&primary_pe->origin_bios);
+ free_pending_exception(primary_pe);
+ }
/*
* Free the pe if it's not linked to an origin write or if
@@ -834,12 +835,6 @@ static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe)
if (!primary_pe || primary_pe != pe)
free_pending_exception(pe);
- /*
- * Free the primary pe if nothing references it.
- */
- if (primary_pe && !atomic_read(&primary_pe->ref_count))
- free_pending_exception(primary_pe);
-
return origin_bios;
}
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 292c15609ae..f07315fe236 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -9,7 +9,7 @@
#ifndef DM_SNAPSHOT_H
#define DM_SNAPSHOT_H
-#include "dm.h"
+#include <linux/device-mapper.h>
#include "dm-bio-list.h"
#include <linux/blkdev.h>
#include <linux/workqueue.h>
@@ -158,9 +158,6 @@ struct dm_snapshot {
/* Used for display of table */
char type;
- /* The last percentage we notified */
- int last_percent;
-
mempool_t *pending_pool;
struct exception_table pending;
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index b745d8ac625..a2d068dbe9e 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -4,7 +4,7 @@
* This file is released under the GPL.
*/
-#include "dm.h"
+#include <linux/device-mapper.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -60,8 +60,8 @@ static inline struct stripe_c *alloc_context(unsigned int stripes)
{
size_t len;
- if (array_too_big(sizeof(struct stripe_c), sizeof(struct stripe),
- stripes))
+ if (dm_array_too_big(sizeof(struct stripe_c), sizeof(struct stripe),
+ stripes))
return NULL;
len = sizeof(struct stripe_c) + (sizeof(struct stripe) * stripes);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a740a6950f5..a63161aec48 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -43,7 +43,7 @@ struct dm_table {
* device. This should be a combination of FMODE_READ
* and FMODE_WRITE.
*/
- int mode;
+ fmode_t mode;
/* a list of devices used by this table */
struct list_head devices;
@@ -217,7 +217,7 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
return 0;
}
-int dm_table_create(struct dm_table **result, int mode,
+int dm_table_create(struct dm_table **result, fmode_t mode,
unsigned num_targets, struct mapped_device *md)
{
struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
@@ -313,19 +313,6 @@ static inline int check_space(struct dm_table *t)
}
/*
- * Convert a device path to a dev_t.
- */
-static int lookup_device(const char *path, dev_t *dev)
-{
- struct block_device *bdev = lookup_bdev(path);
- if (IS_ERR(bdev))
- return PTR_ERR(bdev);
- *dev = bdev->bd_dev;
- bdput(bdev);
- return 0;
-}
-
-/*
* See if we've already got a device in the list.
*/
static struct dm_dev_internal *find_device(struct list_head *l, dev_t dev)
@@ -357,7 +344,7 @@ static int open_dev(struct dm_dev_internal *d, dev_t dev,
return PTR_ERR(bdev);
r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md));
if (r)
- blkdev_put(bdev);
+ blkdev_put(bdev, d->dm_dev.mode);
else
d->dm_dev.bdev = bdev;
return r;
@@ -372,7 +359,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
return;
bd_release_from_disk(d->dm_dev.bdev, dm_disk(md));
- blkdev_put(d->dm_dev.bdev);
+ blkdev_put(d->dm_dev.bdev, d->dm_dev.mode);
d->dm_dev.bdev = NULL;
}
@@ -395,7 +382,7 @@ static int check_device_area(struct dm_dev_internal *dd, sector_t start,
* careful to leave things as they were if we fail to reopen the
* device.
*/
-static int upgrade_mode(struct dm_dev_internal *dd, int new_mode,
+static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
struct mapped_device *md)
{
int r;
@@ -421,7 +408,7 @@ static int upgrade_mode(struct dm_dev_internal *dd, int new_mode,
*/
static int __table_get_device(struct dm_table *t, struct dm_target *ti,
const char *path, sector_t start, sector_t len,
- int mode, struct dm_dev **result)
+ fmode_t mode, struct dm_dev **result)
{
int r;
dev_t uninitialized_var(dev);
@@ -437,8 +424,12 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
return -EOVERFLOW;
} else {
/* convert the path to a device */
- if ((r = lookup_device(path, &dev)))
- return r;
+ struct block_device *bdev = lookup_bdev(path);
+
+ if (IS_ERR(bdev))
+ return PTR_ERR(bdev);
+ dev = bdev->bd_dev;
+ bdput(bdev);
}
dd = find_device(&t->devices, dev);
@@ -537,7 +528,7 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev)
EXPORT_SYMBOL_GPL(dm_set_device_limits);
int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
- sector_t len, int mode, struct dm_dev **result)
+ sector_t len, fmode_t mode, struct dm_dev **result)
{
int r = __table_get_device(ti->table, ti, path,
start, len, mode, result);
@@ -887,7 +878,7 @@ struct list_head *dm_table_get_devices(struct dm_table *t)
return &t->devices;
}
-int dm_table_get_mode(struct dm_table *t)
+fmode_t dm_table_get_mode(struct dm_table *t)
{
return t->mode;
}
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index bdec206c404..cdbf126ec10 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -4,7 +4,7 @@
* This file is released under the GPL.
*/
-#include "dm.h"
+#include <linux/device-mapper.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 327de03a5bd..6963ad14840 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -21,7 +21,6 @@
#include <linux/idr.h>
#include <linux/hdreg.h>
#include <linux/blktrace_api.h>
-#include <linux/smp_lock.h>
#define DM_MSG_PREFIX "core"
@@ -76,7 +75,6 @@ union map_info *dm_get_mapinfo(struct bio *bio)
*/
struct dm_wq_req {
enum {
- DM_WQ_FLUSH_ALL,
DM_WQ_FLUSH_DEFERRED,
} type;
struct work_struct work;
@@ -151,40 +149,40 @@ static struct kmem_cache *_tio_cache;
static int __init local_init(void)
{
- int r;
+ int r = -ENOMEM;
/* allocate a slab for the dm_ios */
_io_cache = KMEM_CACHE(dm_io, 0);
if (!_io_cache)
- return -ENOMEM;
+ return r;
/* allocate a slab for the target ios */
_tio_cache = KMEM_CACHE(dm_target_io, 0);
- if (!_tio_cache) {
- kmem_cache_destroy(_io_cache);
- return -ENOMEM;
- }
+ if (!_tio_cache)
+ goto out_free_io_cache;
r = dm_uevent_init();
- if (r) {
- kmem_cache_destroy(_tio_cache);
- kmem_cache_destroy(_io_cache);
- return r;
- }
+ if (r)
+ goto out_free_tio_cache;
_major = major;
r = register_blkdev(_major, _name);
- if (r < 0) {
- kmem_cache_destroy(_tio_cache);
- kmem_cache_destroy(_io_cache);
- dm_uevent_exit();
- return r;
- }
+ if (r < 0)
+ goto out_uevent_exit;
if (!_major)
_major = r;
return 0;
+
+out_uevent_exit:
+ dm_uevent_exit();
+out_free_tio_cache:
+ kmem_cache_destroy(_tio_cache);
+out_free_io_cache:
+ kmem_cache_destroy(_io_cache);
+
+ return r;
}
static void local_exit(void)
@@ -249,13 +247,13 @@ static void __exit dm_exit(void)
/*
* Block device functions
*/
-static int dm_blk_open(struct inode *inode, struct file *file)
+static int dm_blk_open(struct block_device *bdev, fmode_t mode)
{
struct mapped_device *md;
spin_lock(&_minor_lock);
- md = inode->i_bdev->bd_disk->private_data;
+ md = bdev->bd_disk->private_data;
if (!md)
goto out;
@@ -274,11 +272,9 @@ out:
return md ? 0 : -ENXIO;
}
-static int dm_blk_close(struct inode *inode, struct file *file)
+static int dm_blk_close(struct gendisk *disk, fmode_t mode)
{
- struct mapped_device *md;
-
- md = inode->i_bdev->bd_disk->private_data;
+ struct mapped_device *md = disk->private_data;
atomic_dec(&md->open_count);
dm_put(md);
return 0;
@@ -315,21 +311,14 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return dm_get_geometry(md, geo);
}
-static int dm_blk_ioctl(struct inode *inode, struct file *file,
+static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct mapped_device *md;
- struct dm_table *map;
+ struct mapped_device *md = bdev->bd_disk->private_data;
+ struct dm_table *map = dm_get_table(md);
struct dm_target *tgt;
int r = -ENOTTY;
- /* We don't really need this lock, but we do need 'inode'. */
- unlock_kernel();
-
- md = inode->i_bdev->bd_disk->private_data;
-
- map = dm_get_table(md);
-
if (!map || !dm_table_get_size(map))
goto out;
@@ -345,12 +334,11 @@ static int dm_blk_ioctl(struct inode *inode, struct file *file,
}
if (tgt->type->ioctl)
- r = tgt->type->ioctl(tgt, inode, file, cmd, arg);
+ r = tgt->type->ioctl(tgt, cmd, arg);
out:
dm_table_put(map);
- lock_kernel();
return r;
}
@@ -669,6 +657,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
clone->bi_size = to_bytes(len);
clone->bi_io_vec->bv_offset = offset;
clone->bi_io_vec->bv_len = clone->bi_size;
+ clone->bi_flags |= 1 << BIO_CLONED;
return clone;
}
@@ -1394,9 +1383,6 @@ static void dm_wq_work(struct work_struct *work)
down_write(&md->io_lock);
switch (req->type) {
- case DM_WQ_FLUSH_ALL:
- __merge_pushback_list(md);
- /* pass through */
case DM_WQ_FLUSH_DEFERRED:
__flush_deferred_io(md);
break;
@@ -1526,7 +1512,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
if (!md->suspended_bdev) {
DMWARN("bdget failed in dm_suspend");
r = -ENOMEM;
- goto flush_and_out;
+ goto out;
}
/*
@@ -1577,14 +1563,6 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
set_bit(DMF_SUSPENDED, &md->flags);
-flush_and_out:
- if (r && noflush)
- /*
- * Because there may be already I/Os in the pushback list,
- * flush them before return.
- */
- dm_queue_flush(md, DM_WQ_FLUSH_ALL, NULL);
-
out:
if (r && md->suspended_bdev) {
bdput(md->suspended_bdev);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index cd189da2b2f..0ade60cdef4 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -62,15 +62,6 @@ void dm_put_target_type(struct target_type *t);
int dm_target_iterate(void (*iter_func)(struct target_type *tt,
void *param), void *param);
-/*-----------------------------------------------------------------
- * Useful inlines.
- *---------------------------------------------------------------*/
-static inline int array_too_big(unsigned long fixed, unsigned long obj,
- unsigned long num)
-{
- return (num > (ULONG_MAX - fixed) / obj);
-}
-
int dm_split_args(int *argc, char ***argvp, char *input);
/*
diff --git a/drivers/md/md.c b/drivers/md/md.c
index aaa3d465de4..c1a837ca193 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1520,7 +1520,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
if (err) {
printk(KERN_ERR "md: could not bd_claim %s.\n",
bdevname(bdev, b));
- blkdev_put(bdev);
+ blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
return err;
}
if (!shared)
@@ -1536,7 +1536,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
if (!bdev)
MD_BUG();
bd_release(bdev);
- blkdev_put(bdev);
+ blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
}
void md_autodetect_dev(dev_t dev);
@@ -4785,7 +4785,7 @@ static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int md_ioctl(struct inode *inode, struct file *file,
+static int md_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
int err = 0;
@@ -4823,7 +4823,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
* Commands creating/starting a new array:
*/
- mddev = inode->i_bdev->bd_disk->private_data;
+ mddev = bdev->bd_disk->private_data;
if (!mddev) {
BUG();
@@ -4996,13 +4996,13 @@ abort:
return err;
}
-static int md_open(struct inode *inode, struct file *file)
+static int md_open(struct block_device *bdev, fmode_t mode)
{
/*
* Succeed if we can lock the mddev, which confirms that
* it isn't being stopped right now.
*/
- mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
+ mddev_t *mddev = bdev->bd_disk->private_data;
int err;
if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
@@ -5013,14 +5013,14 @@ static int md_open(struct inode *inode, struct file *file)
atomic_inc(&mddev->openers);
mddev_unlock(mddev);
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
out:
return err;
}
-static int md_release(struct inode *inode, struct file * file)
+static int md_release(struct gendisk *disk, fmode_t mode)
{
- mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
+ mddev_t *mddev = disk->private_data;
BUG_ON(!mddev);
atomic_dec(&mddev->openers);
@@ -5048,7 +5048,7 @@ static struct block_device_operations md_fops =
.owner = THIS_MODULE,
.open = md_open,
.release = md_release,
- .ioctl = md_ioctl,
+ .locked_ioctl = md_ioctl,
.getgeo = md_getgeo,
.media_changed = md_media_changed,
.revalidate_disk= md_revalidate,
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 5b34c134aa2..127b0526a72 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -545,11 +545,11 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
if( VFL_TYPE_GRABBER == type ) {
vv->video_minor = vfd->minor;
INFO(("%s: registered device video%d [v4l2]\n",
- dev->name, vfd->minor & 0x1f));
+ dev->name, vfd->num));
} else {
vv->vbi_minor = vfd->minor;
INFO(("%s: registered device vbi%d [v4l2]\n",
- dev->name, vfd->minor & 0x1f));
+ dev->name, vfd->num));
}
*vid = vfd;
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 99be9e5c85f..fe0bd55977e 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -834,7 +834,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
* copying is done already, arg is a kernel pointer.
*/
-int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+static int __saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
@@ -1215,12 +1215,18 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
}
#endif
default:
- return v4l_compat_translate_ioctl(inode,file,cmd,arg,
- saa7146_video_do_ioctl);
+ return v4l_compat_translate_ioctl(file, cmd, arg,
+ __saa7146_video_do_ioctl);
}
return 0;
}
+int saa7146_video_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ return __saa7146_video_do_ioctl(file, cmd, arg);
+}
+
/*********************************************************************************/
/* buffer handling functions */
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
index 2febfb5a846..40644aacffc 100644
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ b/drivers/media/dvb/frontends/s5h1411.c
@@ -38,6 +38,7 @@ struct s5h1411_state {
struct dvb_frontend frontend;
fe_modulation_t current_modulation;
+ unsigned int first_tune:1;
u32 current_frequency;
int if_freq;
@@ -62,7 +63,7 @@ static struct init_tab {
{ S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
{ S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
{ S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
- { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
+ { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342c, },
{ S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
{ S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
{ S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
@@ -100,7 +101,6 @@ static struct init_tab {
{ S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
{ S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
{ S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
- { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
{ S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
{ S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
{ S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
@@ -393,7 +393,7 @@ static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
switch (KHz) {
case 3250:
- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d5);
s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
break;
@@ -464,13 +464,25 @@ static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
if (inversion == 1)
val |= 0x1000; /* Inverted */
- else
- val |= 0x0000;
state->inversion = inversion;
return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
}
+static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 val;
+
+ dprintk("%s(%d)\n", __func__, serial);
+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100;
+
+ if (serial == 1)
+ val |= 0x100;
+
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val);
+}
+
static int s5h1411_enable_modulation(struct dvb_frontend *fe,
fe_modulation_t m)
{
@@ -478,6 +490,12 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe,
dprintk("%s(0x%08x)\n", __func__, m);
+ if ((state->first_tune == 0) && (m == state->current_modulation)) {
+ dprintk("%s() Already at desired modulation. Skipping...\n",
+ __func__);
+ return 0;
+ }
+
switch (m) {
case VSB_8:
dprintk("%s() VSB_8\n", __func__);
@@ -502,6 +520,7 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe,
}
state->current_modulation = m;
+ state->first_tune = 0;
s5h1411_softreset(fe);
return 0;
@@ -535,7 +554,7 @@ static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
}
-static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
+static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable)
{
struct s5h1411_state *state = fe->demodulator_priv;
@@ -551,6 +570,11 @@ static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
return 0;
}
+static int s5h1411_sleep(struct dvb_frontend *fe)
+{
+ return s5h1411_set_powerstate(fe, 1);
+}
+
static int s5h1411_register_reset(struct dvb_frontend *fe)
{
struct s5h1411_state *state = fe->demodulator_priv;
@@ -574,9 +598,6 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe,
s5h1411_enable_modulation(fe, p->u.vsb.modulation);
- /* Allow the demod to settle */
- msleep(100);
-
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -587,6 +608,10 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 0);
}
+ /* Issue a reset to the demod so it knows to resync against the
+ newly tuned frequency */
+ s5h1411_softreset(fe);
+
return 0;
}
@@ -599,7 +624,7 @@ static int s5h1411_init(struct dvb_frontend *fe)
dprintk("%s()\n", __func__);
- s5h1411_sleep(fe, 0);
+ s5h1411_set_powerstate(fe, 0);
s5h1411_register_reset(fe);
for (i = 0; i < ARRAY_SIZE(init_tab); i++)
@@ -610,12 +635,17 @@ static int s5h1411_init(struct dvb_frontend *fe)
/* The datasheet says that after initialisation, VSB is default */
state->current_modulation = VSB_8;
+ /* Although the datasheet says it's in VSB, empirical evidence
+ shows problems getting lock on the first tuning request. Make
+ sure we call enable_modulation the first time around */
+ state->first_tune = 1;
+
if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
/* Serial */
- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
+ s5h1411_set_serialmode(fe, 1);
else
/* Parallel */
- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
+ s5h1411_set_serialmode(fe, 0);
s5h1411_set_spectralinversion(fe, state->config->inversion);
s5h1411_set_if_freq(fe, state->config->vsb_if);
@@ -637,28 +667,29 @@ static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
*status = 0;
- /* Get the demodulator status */
- reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
- & 0x0001;
- if (reg)
- *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ /* Register F2 bit 15 = Master Lock, removed */
switch (state->current_modulation) {
case QAM_64:
case QAM_256:
reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
- if (reg & 0x100)
- *status |= FE_HAS_VITERBI;
- if (reg & 0x10)
- *status |= FE_HAS_SYNC;
+ if (reg & 0x10) /* QAM FEC Lock */
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+ if (reg & 0x100) /* QAM EQ Lock */
+ *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
break;
case VSB_8:
- reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
- if (reg & 0x0001)
- *status |= FE_HAS_SYNC;
reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
- if (reg & 0x1000)
- *status |= FE_HAS_VITERBI;
+ if (reg & 0x1000) /* FEC Lock */
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+ if (reg & 0x2000) /* EQ Lock */
+ *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x53);
+ if (reg & 0x1) /* AFC Lock */
+ *status |= FE_HAS_SIGNAL;
+
break;
default:
return -EINVAL;
@@ -863,6 +894,7 @@ static struct dvb_frontend_ops s5h1411_ops = {
},
.init = s5h1411_init,
+ .sleep = s5h1411_sleep,
.i2c_gate_ctrl = s5h1411_i2c_gate_ctrl,
.set_frontend = s5h1411_set_frontend,
.get_frontend = s5h1411_get_frontend,
diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
index 7d542bc00c4..45ec0f82989 100644
--- a/drivers/media/dvb/frontends/s5h1411.h
+++ b/drivers/media/dvb/frontends/s5h1411.h
@@ -47,7 +47,7 @@ struct s5h1411_config {
u16 mpeg_timing;
/* IF Freq for QAM and VSB in KHz */
-#define S5H1411_IF_2500 2500
+#define S5H1411_IF_3250 3250
#define S5H1411_IF_3500 3500
#define S5H1411_IF_4000 4000
#define S5H1411_IF_5380 5380
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index c7c770c2898..aa1ff524256 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -36,7 +36,6 @@
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/poll.h>
-#include <linux/byteorder/swabb.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
@@ -52,6 +51,7 @@
#include <linux/i2c.h>
#include <linux/kthread.h>
#include <asm/unaligned.h>
+#include <asm/byteorder.h>
#include <asm/system.h>
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 78f56944e64..a5ca176a7b0 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -171,11 +171,11 @@ static int dsbr100_start(struct dsbr100_device *radio)
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
+ 0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
+ 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0)
return -1;
radio->muted=0;
return (radio->transfer_buffer)[0];
@@ -188,11 +188,11 @@ static int dsbr100_stop(struct dsbr100_device *radio)
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
+ 0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
+ 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0)
return -1;
radio->muted=1;
return (radio->transfer_buffer)[0];
@@ -201,24 +201,24 @@ static int dsbr100_stop(struct dsbr100_device *radio)
/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
{
- freq = (freq/16*80)/1000+856;
+ freq = (freq / 16 * 80) / 1000 + 856;
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_TUNE,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- (freq>>8)&0x00ff, freq&0xff,
- radio->transfer_buffer, 8, 300)<0 ||
+ (freq >> 8) & 0x00ff, freq & 0xff,
+ radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
+ 0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
+ 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) {
radio->stereo = -1;
return -1;
}
- radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
+ radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
return (radio->transfer_buffer)[0];
}
@@ -229,10 +229,10 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
+ 0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0)
radio->stereo = -1;
else
- radio->stereo = ! (radio->transfer_buffer[0]&0x01);
+ radio->stereo = !(radio->transfer_buffer[0] & 0x01);
}
@@ -265,7 +265,7 @@ static int vidioc_querycap(struct file *file, void *priv,
{
strlcpy(v->driver, "dsbr100", sizeof(v->driver));
strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
- sprintf(v->bus_info, "ISA");
+ sprintf(v->bus_info, "USB");
v->version = RADIO_VERSION;
v->capabilities = V4L2_CAP_TUNER;
return 0;
@@ -282,9 +282,9 @@ static int vidioc_g_tuner(struct file *file, void *priv,
dsbr100_getstat(radio);
strcpy(v->name, "FM");
v->type = V4L2_TUNER_RADIO;
- v->rangelow = FREQ_MIN*FREQ_MUL;
- v->rangehigh = FREQ_MAX*FREQ_MUL;
- v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+ v->rangelow = FREQ_MIN * FREQ_MUL;
+ v->rangehigh = FREQ_MAX * FREQ_MUL;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
v->capability = V4L2_TUNER_CAP_LOW;
if(radio->stereo)
v->audmode = V4L2_TUNER_MODE_STEREO;
@@ -309,7 +309,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
struct dsbr100_device *radio = video_drvdata(file);
radio->curfreq = f->frequency;
- if (dsbr100_setfreq(radio, radio->curfreq)==-1)
+ if (dsbr100_setfreq(radio, radio->curfreq) == -1)
dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
return 0;
}
@@ -331,8 +331,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
if (qc->id && qc->id == radio_qctrl[i].id) {
- memcpy(qc, &(radio_qctrl[i]),
- sizeof(*qc));
+ memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
return 0;
}
}
@@ -412,19 +411,25 @@ static int vidioc_s_audio(struct file *file, void *priv,
static int usb_dsbr100_open(struct inode *inode, struct file *file)
{
struct dsbr100_device *radio = video_drvdata(file);
+ int retval;
lock_kernel();
radio->users = 1;
radio->muted = 1;
- if (dsbr100_start(radio)<0) {
+ if (dsbr100_start(radio) < 0) {
dev_warn(&radio->usbdev->dev,
"Radio did not start up properly\n");
radio->users = 0;
unlock_kernel();
return -EIO;
}
- dsbr100_setfreq(radio, radio->curfreq);
+
+ retval = dsbr100_setfreq(radio, radio->curfreq);
+
+ if (retval == -1)
+ printk(KERN_WARNING KBUILD_MODNAME ": Set frequency failed\n");
+
unlock_kernel();
return 0;
}
@@ -485,13 +490,20 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
{
struct dsbr100_device *radio;
- if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
+ radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL);
+
+ if (!radio)
return -ENOMEM;
- if (!(radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL))) {
+
+ radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
+
+ if (!(radio->transfer_buffer)) {
kfree(radio);
return -ENOMEM;
}
- if (!(radio->videodev = video_device_alloc())) {
+ radio->videodev = video_device_alloc();
+
+ if (!(radio->videodev)) {
kfree(radio->transfer_buffer);
kfree(radio);
return -ENOMEM;
@@ -501,7 +513,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
radio->removed = 0;
radio->users = 0;
radio->usbdev = interface_to_usbdev(intf);
- radio->curfreq = FREQ_MIN*FREQ_MUL;
+ radio->curfreq = FREQ_MIN * FREQ_MUL;
video_set_drvdata(radio->videodev, radio);
if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
dev_warn(&intf->dev, "Could not register video device\n");
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index a33717c4800..256cbeffdcb 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -469,16 +469,21 @@ static int usb_amradio_open(struct inode *inode, struct file *file)
{
struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+ lock_kernel();
+
radio->users = 1;
radio->muted = 1;
if (amradio_start(radio) < 0) {
warn("Radio did not start up properly");
radio->users = 0;
+ unlock_kernel();
return -EIO;
}
if (amradio_setfreq(radio, radio->curfreq) < 0)
warn("Set frequency failed");
+
+ unlock_kernel();
return 0;
}
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 218754b4906..e09b0069323 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -866,7 +866,7 @@ static int __init ar_init(void)
}
printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
- ar->vdev->minor, M32R_IRQ_INT3, freq);
+ ar->vdev->num, M32R_IRQ_INT3, freq);
return 0;
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 5858bf5ff41..9ec4cec2e52 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -4246,7 +4246,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
video_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
- btv->c.nr,btv->video_dev->minor & 0x1f);
+ btv->c.nr, btv->video_dev->num);
if (device_create_file(&btv->video_dev->dev,
&dev_attr_card)<0) {
printk(KERN_ERR "bttv%d: device_create_file 'card' "
@@ -4263,7 +4263,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
vbi_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device vbi%d\n",
- btv->c.nr,btv->vbi_dev->minor & 0x1f);
+ btv->c.nr, btv->vbi_dev->num);
if (!btv->has_radio)
return 0;
@@ -4275,7 +4275,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
radio_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device radio%d\n",
- btv->c.nr,btv->radio_dev->minor & 0x1f);
+ btv->c.nr, btv->radio_dev->num);
/* all done */
return 0;
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 17aa0adb346..0f930d35146 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -815,7 +815,7 @@ static int init_cqcam(struct parport *port)
}
printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
- qcam->vdev.minor, qcam->pport->name);
+ qcam->vdev.num, qcam->pport->name);
qcams[num_cams++] = qcam;
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index fc9497bdd32..a8c068e1de1 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -2059,10 +2059,10 @@ static void cafe_dfs_cam_setup(struct cafe_camera *cam)
if (!cafe_dfs_root)
return;
- sprintf(fname, "regs-%d", cam->v4ldev.minor);
+ sprintf(fname, "regs-%d", cam->v4ldev.num);
cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
cam, &cafe_dfs_reg_ops);
- sprintf(fname, "cam-%d", cam->v4ldev.minor);
+ sprintf(fname, "cam-%d", cam->v4ldev.num);
cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
cam, &cafe_dfs_cam_ops);
}
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 1798b779a25..16c094f7785 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -1347,7 +1347,7 @@ static void create_proc_cpia_cam(struct cam_data *cam)
if (!cpia_proc_root || !cam)
return;
- snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
+ snprintf(name, sizeof(name), "video%d", cam->vdev.num);
ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
if (!ent)
@@ -1372,7 +1372,7 @@ static void destroy_proc_cpia_cam(struct cam_data *cam)
if (!cam || !cam->proc_entry)
return;
- snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
+ snprintf(name, sizeof(name), "video%d", cam->vdev.num);
remove_proc_entry(name, cpia_proc_root);
cam->proc_entry = NULL;
}
@@ -4005,7 +4005,7 @@ void cpia_unregister_camera(struct cam_data *cam)
}
#ifdef CONFIG_PROC_FS
- DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor);
+ DBG("destroying /proc/cpia/video%d\n", cam->vdev.num);
destroy_proc_cpia_cam(cam);
#endif
if (!cam->open_count) {
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 897e8d1a5c3..1c6bd633f19 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -1973,7 +1973,7 @@ void cpia2_unregister_camera(struct camera_data *cam)
} else {
LOG("/dev/video%d removed while open, "
"deferring video_unregister_device\n",
- cam->vdev->minor);
+ cam->vdev->num);
}
}
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 085121c2b47..7a1a7830a6b 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -613,6 +613,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
int retval = 0;
+ int i;
int vbi_buf_size;
u32 devtype;
struct cx18 *cx;
@@ -698,7 +699,8 @@ static int __devinit cx18_probe(struct pci_dev *dev,
/* active i2c */
CX18_DEBUG_INFO("activating i2c...\n");
- if (init_cx18_i2c(cx)) {
+ retval = init_cx18_i2c(cx);
+ if (retval) {
CX18_ERR("Could not initialize i2c\n");
goto free_map;
}
@@ -836,8 +838,11 @@ err:
CX18_ERR("Error %d on initialization\n", retval);
cx18_log_statistics(cx);
- kfree(cx18_cards[cx18_cards_active]);
- cx18_cards[cx18_cards_active] = NULL;
+ i = cx->num;
+ spin_lock(&cx18_cards_lock);
+ kfree(cx18_cards[i]);
+ cx18_cards[i] = NULL;
+ spin_unlock(&cx18_cards_lock);
return retval;
}
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index fa8be0731a3..a4b1708fafe 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -41,6 +41,7 @@
#include <linux/pagemap.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
+#include <asm/byteorder.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
index 197d4fbd9f9..287a5e8bf67 100644
--- a/drivers/media/video/cx18/cx18-io.h
+++ b/drivers/media/video/cx18/cx18-io.h
@@ -39,7 +39,7 @@ static inline void cx18_io_delay(struct cx18 *cx)
/* Statistics gathering */
static inline
-void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr)
+void cx18_log_write_retries(struct cx18 *cx, int i, const void __iomem *addr)
{
if (i > CX18_MAX_MMIO_RETRIES)
i = CX18_MAX_MMIO_RETRIES;
@@ -48,7 +48,7 @@ void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr)
}
static inline
-void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr)
+void cx18_log_read_retries(struct cx18 *cx, int i, const void __iomem *addr)
{
if (i > CX18_MAX_MMIO_RETRIES)
i = CX18_MAX_MMIO_RETRIES;
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 0c8e7542cf6..e5ff7705b7a 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -200,16 +200,18 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
/* Initialize v4l2 variables and register v4l2 devices */
int cx18_streams_setup(struct cx18 *cx)
{
- int type;
+ int type, ret;
/* Setup V4L2 Devices */
for (type = 0; type < CX18_MAX_STREAMS; type++) {
/* Prepare device */
- if (cx18_prep_dev(cx, type))
+ ret = cx18_prep_dev(cx, type);
+ if (ret < 0)
break;
/* Allocate Stream */
- if (cx18_stream_alloc(&cx->streams[type]))
+ ret = cx18_stream_alloc(&cx->streams[type]);
+ if (ret < 0)
break;
}
if (type == CX18_MAX_STREAMS)
@@ -217,14 +219,14 @@ int cx18_streams_setup(struct cx18 *cx)
/* One or more streams could not be initialized. Clean 'em all up. */
cx18_streams_cleanup(cx, 0);
- return -ENOMEM;
+ return ret;
}
static int cx18_reg_dev(struct cx18 *cx, int type)
{
struct cx18_stream *s = &cx->streams[type];
int vfl_type = cx18_stream_info[type].vfl_type;
- int num;
+ int num, ret;
/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
* We need a VFL_TYPE_TS defined.
@@ -233,9 +235,10 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
/* just return if no DVB is supported */
if ((cx->card->hw_all & CX18_HW_DVB) == 0)
return 0;
- if (cx18_dvb_register(s) < 0) {
+ ret = cx18_dvb_register(s);
+ if (ret < 0) {
CX18_ERR("DVB failed to register\n");
- return -EINVAL;
+ return ret;
}
}
@@ -252,12 +255,13 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
}
/* Register device. First try the desired minor, then any free one. */
- if (video_register_device(s->v4l2dev, vfl_type, num)) {
+ ret = video_register_device(s->v4l2dev, vfl_type, num);
+ if (ret < 0) {
CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
s->name, num);
video_device_release(s->v4l2dev);
s->v4l2dev = NULL;
- return -ENOMEM;
+ return ret;
}
num = s->v4l2dev->num;
@@ -290,18 +294,22 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
int cx18_streams_register(struct cx18 *cx)
{
int type;
- int err = 0;
+ int err;
+ int ret = 0;
/* Register V4L2 devices */
- for (type = 0; type < CX18_MAX_STREAMS; type++)
- err |= cx18_reg_dev(cx, type);
+ for (type = 0; type < CX18_MAX_STREAMS; type++) {
+ err = cx18_reg_dev(cx, type);
+ if (err && ret == 0)
+ ret = err;
+ }
- if (err == 0)
+ if (ret == 0)
return 0;
/* One or more streams could not be initialized. Clean 'em all up. */
cx18_streams_cleanup(cx, 1);
- return -ENOMEM;
+ return ret;
}
/* Unregister v4l2 devices */
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 395c11fa47c..00831f3ef8f 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -1815,7 +1815,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
cx23885_mc417_init(dev);
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
- dev->name, dev->v4l_device->minor & 0x1f);
+ dev->name, dev->v4l_device->num);
return 0;
}
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index ab3110d6046..c742a10be5c 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -1543,7 +1543,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
- dev->name, dev->video_dev->minor & 0x1f);
+ dev->name, dev->video_dev->num);
/* initial device configuration */
mutex_lock(&dev->lock);
cx23885_set_tvnorm(dev, dev->tvnorm);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index e7136975430..078be631955 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1285,7 +1285,7 @@ static int blackbird_register_video(struct cx8802_dev *dev)
return err;
}
printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n",
- dev->core->name,dev->mpeg_dev->minor & 0x1f);
+ dev->core->name, dev->mpeg_dev->num);
return 0;
}
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index fbc224f46e0..5bcbb4cc7c2 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -3044,8 +3044,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
- if (!core->board.num_frontends)
- core->board.num_frontends=1;
+ if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
+ core->board.num_frontends = 1;
info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
pci->subsystem_vendor, pci->subsystem_device, core->board.name,
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 6968ab0181a..cf6c30d4e54 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -789,7 +789,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (fe0->dvb.frontend)
fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
if (attach_xc3028(0x61, dev) < 0)
- return -EINVAL;
+ goto frontend_detach;
break;
case CX88_BOARD_PCHDTV_HD3000:
fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
@@ -1058,7 +1058,6 @@ static int dvb_register(struct cx8802_dev *dev)
goto frontend_detach;
core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
-
}
}
break;
@@ -1110,10 +1109,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->pci->dev, adapter_nr, mfe_shared);
frontend_detach:
- if (fe0->dvb.frontend) {
- dvb_frontend_detach(fe0->dvb.frontend);
- fe0->dvb.frontend = NULL;
- }
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
return -EINVAL;
}
@@ -1246,8 +1242,11 @@ fail_core:
static int cx8802_dvb_remove(struct cx8802_driver *drv)
{
+ struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
+ dprintk( 1, "%s\n", __func__);
+
videobuf_dvb_unregister_bus(&dev->frontends);
vp3054_i2c_remove(dev);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 01de2300709..1ab691d2069 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -116,8 +116,10 @@ static int detach_inform(struct i2c_client *client)
void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
struct videobuf_dvb_frontends *f = &core->dvbdev->frontends;
struct videobuf_dvb_frontend *fe = NULL;
+#endif
if (0 != core->i2c_rc)
return;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 6df5cf31418..a1c435b4b1c 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -768,8 +768,11 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
{
struct cx8802_dev *dev;
struct cx88_core *core;
+ int err;
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
struct videobuf_dvb_frontend *demod;
- int err,i;
+ int i;
+#endif
/* general setup */
core = cx88_core_get(pci_dev);
@@ -782,11 +785,6 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
if (!core->board.mpeg)
goto fail_core;
- if (!core->board.num_frontends) {
- printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __func__, err);
- goto fail_core;
- }
-
err = -ENOMEM;
dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
@@ -801,10 +799,12 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
INIT_LIST_HEAD(&dev->drvlist);
list_add_tail(&dev->devlist,&cx8802_devlist);
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
mutex_init(&dev->frontends.lock);
INIT_LIST_HEAD(&dev->frontends.felist);
- printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends);
+ if (core->board.num_frontends)
+ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends);
for (i = 1; i <= core->board.num_frontends; i++) {
demod = videobuf_dvb_alloc_frontend(&dev->frontends, i);
@@ -814,6 +814,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
goto fail_free;
}
}
+#endif
/* Maintain a reference so cx88-video can query the 8802 device. */
core->dvbdev = dev;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 3904b73f52e..61265fd04d5 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1911,7 +1911,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
- core->name,dev->video_dev->minor & 0x1f);
+ core->name, dev->video_dev->num);
dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
@@ -1922,7 +1922,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device vbi%d\n",
- core->name,dev->vbi_dev->minor & 0x1f);
+ core->name, dev->vbi_dev->num);
if (core->board.radio.type == CX88_RADIO) {
dev->radio_dev = cx88_vdev_init(core,dev->pci,
@@ -1935,7 +1935,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device radio%d\n",
- core->name,dev->radio_dev->minor & 0x1f);
+ core->name, dev->radio_dev->num);
}
/* everything worked */
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index c53649e5315..a1ab2ef4557 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -2042,7 +2042,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
goto fail_unreg;
}
em28xx_info("Registered radio device as /dev/radio%d\n",
- dev->radio_dev->minor & 0x1f);
+ dev->radio_dev->num);
}
/* init video dma queues */
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 7a85c41b0ee..9d0ef96c23f 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -588,7 +588,7 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "URB timeout reached. The camera is misconfigured. To "
"use it, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1195,7 +1195,7 @@ static void et61x251_release_resources(struct kref *kref)
cam = container_of(kref, struct et61x251_device, kref);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
@@ -1237,7 +1237,7 @@ static int et61x251_open(struct inode* inode, struct file* filp)
if (cam->users) {
DBG(2, "Device /dev/video%d is already in use",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
DBG(3, "Simultaneous opens are not supported");
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
@@ -1280,7 +1280,7 @@ static int et61x251_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
et61x251_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
out:
mutex_unlock(&cam->open_mutex);
@@ -1304,7 +1304,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->wait_open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
kref_put(&cam->kref, et61x251_release_resources);
@@ -1845,7 +1845,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1858,7 +1858,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2068,7 +2068,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -2080,7 +2080,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2128,7 +2128,7 @@ et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
"problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor);
+ "/dev/video%d again.", cam->v4ldev->num);
return -EIO;
}
@@ -2605,7 +2605,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
cam->module_param.force_munmap = force_munmap[dev_nr];
cam->module_param.frame_timeout = frame_timeout[dev_nr];
@@ -2658,7 +2658,7 @@ static void et61x251_usb_disconnect(struct usb_interface* intf)
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cam->state |= DEV_MISCONFIGURED;
et61x251_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index aeaa13f6cb3..d36485023b6 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -1211,6 +1211,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
+ /* Turn off the output signal. The mpeg decoder is not yet
+ active so without this you would get a green image until the
+ mpeg decoder becomes active. */
+ ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
}
/* clear interrupt mask, effectively disabling interrupts */
@@ -1330,6 +1334,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)
ivtv_s_frequency(NULL, &fh, &vf);
if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+ /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes
+ the mpeg decoder so now the saa7127 receives a proper
+ signal. */
+ ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
ivtv_init_mpeg_decoder(itv);
}
ivtv_s_std(NULL, &fh, &itv->tuner_std);
@@ -1366,6 +1374,10 @@ static void ivtv_remove(struct pci_dev *pci_dev)
/* Stop all decoding */
IVTV_DEBUG_INFO("Stopping decoding\n");
+
+ /* Turn off the TV-out */
+ if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+ ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
if (atomic_read(&itv->decoding) > 0) {
int type;
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index bc29436e8a3..3733b2afec5 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -55,6 +55,7 @@
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/byteorder.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 24700c211d5..41dbbe9621a 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -726,6 +726,7 @@ int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg)
{
return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg);
}
+EXPORT_SYMBOL(ivtv_saa7127);
int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg)
{
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 208fb54842f..4bae38d21ef 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1756,12 +1756,12 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
return 0;
}
-static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
+static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
- int ret;
+ long ret;
/* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */
switch (cmd) {
@@ -1830,20 +1830,19 @@ static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct f
if (ivtv_debug & IVTV_DBGFLG_IOCTL)
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
- ret = video_ioctl2(inode, filp, cmd, arg);
+ ret = __video_ioctl2(filp, cmd, arg);
vfd->debug = 0;
return ret;
}
-int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
struct ivtv *itv = id->itv;
- int res;
+ long res;
mutex_lock(&itv->serialize_lock);
- res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
+ res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
mutex_unlock(&itv->serialize_lock);
return res;
}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h
index 70188588b4f..58f003412af 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.h
+++ b/drivers/media/video/ivtv/ivtv-ioctl.h
@@ -30,7 +30,6 @@ void ivtv_set_funcs(struct video_device *vdev);
int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std);
int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
-int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg);
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
#endif
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 5bbf31e3930..9b7aa79eb26 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -48,7 +48,7 @@ static const struct file_operations ivtv_v4l2_enc_fops = {
.read = ivtv_v4l2_read,
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
+ .unlocked_ioctl = ivtv_v4l2_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_enc_poll,
@@ -59,7 +59,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = {
.read = ivtv_v4l2_read,
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
+ .unlocked_ioctl = ivtv_v4l2_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_dec_poll,
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 8a4a150b12f..921e281876f 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -48,6 +48,7 @@
#endif
#include "ivtv-driver.h"
+#include "ivtv-i2c.h"
#include "ivtv-udma.h"
#include "ivtv-mailbox.h"
@@ -894,11 +895,16 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
switch (blank_mode) {
case FB_BLANK_UNBLANK:
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
+ ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
break;
case FB_BLANK_NORMAL:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_VSYNC_SUSPEND:
+ ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+ ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
+ break;
case FB_BLANK_POWERDOWN:
+ ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
break;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index a1252d673b4..273d2a1aa22 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -402,6 +402,10 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
+ /* prevent the PTSs from slowly drifting away in the generated
+ MPEG stream */
+ ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
+
return ret;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 94265bd3d92..5b81ba46964 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -60,7 +60,6 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
static DEFINE_MUTEX(pvr2_unit_mtx);
static int ctlchg;
-static int initusbreset = 1;
static int procreload;
static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
@@ -71,8 +70,6 @@ module_param(ctlchg, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
-module_param(initusbreset, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");
module_param(procreload, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(procreload,
"Attempt init failure recovery with firmware reload");
@@ -1967,9 +1964,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
}
hdw->fw1_state = FW1_STATE_OK;
- if (initusbreset) {
- pvr2_hdw_device_reset(hdw);
- }
if (!pvr2_hdw_dev_ok(hdw)) return;
for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index f048d80b77e..97ed9595799 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -168,7 +168,7 @@ static const char *get_v4l_name(int v4l_type)
* This is part of Video 4 Linux API. The procedure handles ioctl() calls.
*
*/
-static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+static int __pvr2_v4l2_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct pvr2_v4l2_fh *fh = file->private_data;
@@ -863,8 +863,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
#endif
default :
- ret = v4l_compat_translate_ioctl(inode,file,cmd,
- arg,pvr2_v4l2_do_ioctl);
+ ret = v4l_compat_translate_ioctl(file, cmd,
+ arg, __pvr2_v4l2_do_ioctl);
}
pvr2_hdw_commit_ctl(hdw);
@@ -890,10 +890,15 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
return ret;
}
+static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ return __pvr2_v4l2_do_ioctl(file, cmd, arg);
+}
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
{
- int minor_id = dip->devbase.minor;
+ int num = dip->devbase.num;
struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
enum pvr2_config cfg = dip->config;
int v4l_type = dip->v4l_type;
@@ -909,7 +914,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
video_unregister_device(&dip->devbase);
printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
- get_v4l_name(v4l_type),minor_id & 0x1f,
+ get_v4l_name(v4l_type), num,
pvr2_config_get_name(cfg));
}
@@ -1310,7 +1315,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
}
printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
- get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
+ get_v4l_name(dip->v4l_type), dip->devbase.num,
pvr2_config_get_name(dip->config));
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index ab28389b4cd..f3897a3fdb7 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -1795,7 +1795,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
goto err;
}
else {
- PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
+ PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num);
}
/* occupy slot */
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index b686bfabbde..24918445294 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -996,7 +996,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
goto fail4;
}
printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
- dev->name,dev->video_dev->minor & 0x1f);
+ dev->name, dev->video_dev->num);
dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
@@ -1005,7 +1005,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (err < 0)
goto fail4;
printk(KERN_INFO "%s: registered device vbi%d\n",
- dev->name,dev->vbi_dev->minor & 0x1f);
+ dev->name, dev->vbi_dev->num);
if (card_has_radio(dev)) {
dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
@@ -1014,7 +1014,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (err < 0)
goto fail4;
printk(KERN_INFO "%s: registered device radio%d\n",
- dev->name,dev->radio_dev->minor & 0x1f);
+ dev->name, dev->radio_dev->num);
}
/* everything worked */
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 9a8766a78a0..7f40511bcc0 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -534,7 +534,7 @@ static int empress_init(struct saa7134_dev *dev)
return err;
}
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
- dev->name,dev->empress_dev->minor & 0x1f);
+ dev->name, dev->empress_dev->num);
videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
&dev->pci->dev, &dev->slock,
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index ae3949180c4..044a2e94c34 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -1412,7 +1412,7 @@ static int se401_probe(struct usb_interface *intf,
return -EIO;
}
dev_info(&intf->dev, "registered new video device: video%d\n",
- se401->vdev.minor);
+ se401->vdev.num);
usb_set_intfdata (intf, se401);
return 0;
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 20e30bd9364..fcd2b62f92c 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1008,7 +1008,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "URB timeout reached. The camera is misconfigured. "
"To use it, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1734,7 +1734,7 @@ static void sn9c102_release_resources(struct kref *kref)
cam = container_of(kref, struct sn9c102_device, kref);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
@@ -1792,7 +1792,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
if (cam->users) {
DBG(2, "Device /dev/video%d is already in use",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
DBG(3, "Simultaneous opens are not supported");
/*
open() must follow the open flags and should block
@@ -1845,7 +1845,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
sn9c102_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
out:
mutex_unlock(&cam->open_mutex);
@@ -1870,7 +1870,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->wait_open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
kref_put(&cam->kref, sn9c102_release_resources);
@@ -2432,7 +2432,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -2445,7 +2445,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2689,7 +2689,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -2701,7 +2701,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2748,7 +2748,7 @@ sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
"problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor);
+ "/dev/video%d again.", cam->v4ldev->num);
return -EIO;
}
@@ -3348,7 +3348,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, cam);
cam->module_param.force_munmap = force_munmap[dev_nr];
@@ -3402,7 +3402,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cam->state |= DEV_MISCONFIGURED;
sn9c102_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index edaea496451..e9eb6d754d5 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -1331,7 +1331,7 @@ static int stk_register_video_device(struct stk_camera *dev)
STK_ERROR("v4l registration failed\n");
else
STK_INFO("Syntek USB2.0 Camera is now controlling video device"
- " /dev/video%d\n", dev->vdev.minor);
+ " /dev/video%d\n", dev->vdev.num);
return err;
}
@@ -1426,7 +1426,7 @@ static void stk_camera_disconnect(struct usb_interface *interface)
stk_remove_sysfs_files(&dev->vdev);
STK_INFO("Syntek USB2.0 Camera release resources "
- "video device /dev/video%d\n", dev->vdev.minor);
+ "video device /dev/video%d\n", dev->vdev.num);
video_unregister_device(&dev->vdev);
}
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 9c549d93599..328c41b1517 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1470,7 +1470,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
retval = -EIO;
goto error_vdev;
}
- PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor);
+ PDEBUG(0, "STV(i): registered new video device: video%d",
+ stv680->vdev->num);
usb_set_intfdata (intf, stv680);
retval = stv680_create_sysfs_files(stv680->vdev);
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 07cd87d16f6..7c575bb8184 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -1059,7 +1059,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n",
(uvd->handle != NULL) ? uvd->handle->drvName : "???",
- uvd->vdev.minor, tmp2, tmp1);
+ uvd->vdev.num, tmp2, tmp1);
usb_get_dev(uvd->dev);
return 0;
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 7a127d6bfde..8e2d58bec48 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -877,7 +877,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
return -EIO;
}
- printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
+ printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",
+ cam->vdev.num);
usb_set_intfdata (intf, cam);
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 92427fdc145..9907b9aff2b 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -236,7 +236,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
sizeof(struct i2c_client));
sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
- " #%d", usbvision->vdev->minor & 0x1f);
+ " #%d", usbvision->vdev->num);
PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 77aeb39b275..d185b57fdcd 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1440,7 +1440,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// vbi Device:
if (usbvision->vbi) {
PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]",
- usbvision->vbi->minor & 0x1f);
+ usbvision->vbi->num);
if (usbvision->vbi->minor != -1) {
video_unregister_device(usbvision->vbi);
} else {
@@ -1452,7 +1452,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// Radio Device:
if (usbvision->rdev) {
PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]",
- usbvision->rdev->minor & 0x1f);
+ usbvision->rdev->num);
if (usbvision->rdev->minor != -1) {
video_unregister_device(usbvision->rdev);
} else {
@@ -1464,7 +1464,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// Video Device:
if (usbvision->vdev) {
PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]",
- usbvision->vdev->minor & 0x1f);
+ usbvision->vdev->num);
if (usbvision->vdev->minor != -1) {
video_unregister_device(usbvision->vdev);
} else {
@@ -1490,7 +1490,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
goto err_exit;
}
printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n",
- usbvision->nr,usbvision->vdev->minor & 0x1f);
+ usbvision->nr, usbvision->vdev->num);
// Radio Device:
if (usbvision_device_data[usbvision->DevModel].Radio) {
@@ -1507,7 +1507,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
goto err_exit;
}
printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n",
- usbvision->nr, usbvision->rdev->minor & 0x1f);
+ usbvision->nr, usbvision->rdev->num);
}
// vbi Device:
if (usbvision_device_data[usbvision->DevModel].vbi) {
@@ -1523,7 +1523,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
goto err_exit;
}
printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n",
- usbvision->nr,usbvision->vbi->minor & 0x1f);
+ usbvision->nr, usbvision->vbi->num);
}
// all done
return 0;
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 78e4c4e09d8..758dfefaba8 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -464,7 +464,7 @@ static int uvc_v4l2_release(struct inode *inode, struct file *file)
return 0;
}
-static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
+static int __uvc_v4l2_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
@@ -978,8 +978,8 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
return uvc_xu_ctrl_query(video, arg, 1);
default:
- if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg,
- uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD)
+ if ((ret = v4l_compat_translate_ioctl(file, cmd, arg,
+ __uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD)
uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n",
cmd);
return ret;
@@ -988,6 +988,12 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
return ret;
}
+static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ return __uvc_v4l2_do_ioctl(file, cmd, arg);
+}
+
static int uvc_v4l2_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 928cb403737..f13c0a9d684 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -57,8 +57,7 @@ MODULE_LICENSE("GPL");
*/
static int
-get_v4l_control(struct inode *inode,
- struct file *file,
+get_v4l_control(struct file *file,
int cid,
v4l2_kioctl drv)
{
@@ -67,12 +66,12 @@ get_v4l_control(struct inode *inode,
int err;
qctrl2.id = cid;
- err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
if (err < 0)
dprintk("VIDIOC_QUERYCTRL: %d\n", err);
if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
ctrl2.id = qctrl2.id;
- err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
+ err = drv(file, VIDIOC_G_CTRL, &ctrl2);
if (err < 0) {
dprintk("VIDIOC_G_CTRL: %d\n", err);
return 0;
@@ -85,8 +84,7 @@ get_v4l_control(struct inode *inode,
}
static int
-set_v4l_control(struct inode *inode,
- struct file *file,
+set_v4l_control(struct file *file,
int cid,
int value,
v4l2_kioctl drv)
@@ -96,7 +94,7 @@ set_v4l_control(struct inode *inode,
int err;
qctrl2.id = cid;
- err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
if (err < 0)
dprintk("VIDIOC_QUERYCTRL: %d\n", err);
if (err == 0 &&
@@ -114,7 +112,7 @@ set_v4l_control(struct inode *inode,
+ 32767)
/ 65535;
ctrl2.value += qctrl2.minimum;
- err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
+ err = drv(file, VIDIOC_S_CTRL, &ctrl2);
if (err < 0)
dprintk("VIDIOC_S_CTRL: %d\n", err);
}
@@ -222,7 +220,6 @@ static int poll_one(struct file *file, struct poll_wqueues *pwq)
}
static int count_inputs(
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -232,14 +229,13 @@ static int count_inputs(
for (i = 0;; i++) {
memset(&input2, 0, sizeof(input2));
input2.index = i;
- if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2))
+ if (0 != drv(file, VIDIOC_ENUMINPUT, &input2))
break;
}
return i;
}
static int check_size(
- struct inode *inode,
struct file *file,
v4l2_kioctl drv,
int *maxw,
@@ -252,14 +248,14 @@ static int check_size(
memset(&fmt2, 0, sizeof(fmt2));
desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2))
+ if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2))
goto done;
fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt2.fmt.pix.width = 10000;
fmt2.fmt.pix.height = 10000;
fmt2.fmt.pix.pixelformat = desc2.pixelformat;
- if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2))
+ if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2))
goto done;
*maxw = fmt2.fmt.pix.width;
@@ -273,7 +269,6 @@ done:
static noinline int v4l1_compat_get_capabilities(
struct video_capability *cap,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -289,13 +284,13 @@ static noinline int v4l1_compat_get_capabilities(
memset(cap, 0, sizeof(*cap));
memset(&fbuf, 0, sizeof(fbuf));
- err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
+ err = drv(file, VIDIOC_QUERYCAP, cap2);
if (err < 0) {
dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
goto done;
}
if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ err = drv(file, VIDIOC_G_FBUF, &fbuf);
if (err < 0) {
dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
memset(&fbuf, 0, sizeof(fbuf));
@@ -317,8 +312,8 @@ static noinline int v4l1_compat_get_capabilities(
if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
cap->type |= VID_TYPE_CLIPPING;
- cap->channels = count_inputs(inode, file, drv);
- check_size(inode, file, drv,
+ cap->channels = count_inputs(file, drv);
+ check_size(file, drv,
&cap->maxwidth, &cap->maxheight);
cap->audios = 0; /* FIXME */
cap->minwidth = 48; /* FIXME */
@@ -331,7 +326,6 @@ done:
static noinline int v4l1_compat_get_frame_buffer(
struct video_buffer *buffer,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -341,7 +335,7 @@ static noinline int v4l1_compat_get_frame_buffer(
memset(buffer, 0, sizeof(*buffer));
memset(&fbuf, 0, sizeof(fbuf));
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ err = drv(file, VIDIOC_G_FBUF, &fbuf);
if (err < 0) {
dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
goto done;
@@ -386,7 +380,6 @@ done:
static noinline int v4l1_compat_set_frame_buffer(
struct video_buffer *buffer,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -415,7 +408,7 @@ static noinline int v4l1_compat_set_frame_buffer(
break;
}
fbuf.fmt.bytesperline = buffer->bytesperline;
- err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+ err = drv(file, VIDIOC_S_FBUF, &fbuf);
if (err < 0)
dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
return err;
@@ -423,7 +416,6 @@ static noinline int v4l1_compat_set_frame_buffer(
static noinline int v4l1_compat_get_win_cap_dimensions(
struct video_window *win,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -438,7 +430,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
memset(win, 0, sizeof(*win));
fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0)
dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
if (err == 0) {
@@ -453,7 +445,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
}
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -472,7 +464,6 @@ done:
static noinline int v4l1_compat_set_win_cap_dimensions(
struct video_window *win,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -485,8 +476,8 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
return err;
}
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- drv(inode, file, VIDIOC_STREAMOFF, &fmt->type);
- err1 = drv(inode, file, VIDIOC_G_FMT, fmt);
+ drv(file, VIDIOC_STREAMOFF, &fmt->type);
+ err1 = drv(file, VIDIOC_G_FMT, fmt);
if (err1 < 0)
dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
if (err1 == 0) {
@@ -494,7 +485,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
fmt->fmt.pix.height = win->height;
fmt->fmt.pix.field = V4L2_FIELD_ANY;
fmt->fmt.pix.bytesperline = 0;
- err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ err = drv(file, VIDIOC_S_FMT, fmt);
if (err < 0)
dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
err);
@@ -511,7 +502,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
fmt->fmt.win.chromakey = win->chromakey;
fmt->fmt.win.clips = (void __user *)win->clips;
fmt->fmt.win.clipcount = win->clipcount;
- err2 = drv(inode, file, VIDIOC_S_FMT, fmt);
+ err2 = drv(file, VIDIOC_S_FMT, fmt);
if (err2 < 0)
dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
@@ -525,7 +516,6 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
static noinline int v4l1_compat_turn_preview_on_off(
int *on,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -536,9 +526,9 @@ static noinline int v4l1_compat_turn_preview_on_off(
/* dirty hack time. But v4l1 has no STREAMOFF
* equivalent in the API, and this one at
* least comes close ... */
- drv(inode, file, VIDIOC_STREAMOFF, &captype);
+ drv(file, VIDIOC_STREAMOFF, &captype);
}
- err = drv(inode, file, VIDIOC_OVERLAY, on);
+ err = drv(file, VIDIOC_OVERLAY, on);
if (err < 0)
dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
return err;
@@ -546,7 +536,6 @@ static noinline int v4l1_compat_turn_preview_on_off(
static noinline int v4l1_compat_get_input_info(
struct video_channel *chan,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -556,7 +545,7 @@ static noinline int v4l1_compat_get_input_info(
memset(&input2, 0, sizeof(input2));
input2.index = chan->channel;
- err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
+ err = drv(file, VIDIOC_ENUMINPUT, &input2);
if (err < 0) {
dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
"channel=%d err=%d\n", chan->channel, err);
@@ -578,7 +567,7 @@ static noinline int v4l1_compat_get_input_info(
break;
}
chan->norm = 0;
- err = drv(inode, file, VIDIOC_G_STD, &sid);
+ err = drv(file, VIDIOC_G_STD, &sid);
if (err < 0)
dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
if (err == 0) {
@@ -595,14 +584,13 @@ done:
static noinline int v4l1_compat_set_input(
struct video_channel *chan,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
int err;
v4l2_std_id sid = 0;
- err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
+ err = drv(file, VIDIOC_S_INPUT, &chan->channel);
if (err < 0)
dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
switch (chan->norm) {
@@ -617,7 +605,7 @@ static noinline int v4l1_compat_set_input(
break;
}
if (0 != sid) {
- err = drv(inode, file, VIDIOC_S_STD, &sid);
+ err = drv(file, VIDIOC_S_STD, &sid);
if (err < 0)
dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
}
@@ -626,7 +614,6 @@ static noinline int v4l1_compat_set_input(
static noinline int v4l1_compat_get_picture(
struct video_picture *pict,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -639,19 +626,19 @@ static noinline int v4l1_compat_get_picture(
return err;
}
- pict->brightness = get_v4l_control(inode, file,
+ pict->brightness = get_v4l_control(file,
V4L2_CID_BRIGHTNESS, drv);
- pict->hue = get_v4l_control(inode, file,
+ pict->hue = get_v4l_control(file,
V4L2_CID_HUE, drv);
- pict->contrast = get_v4l_control(inode, file,
+ pict->contrast = get_v4l_control(file,
V4L2_CID_CONTRAST, drv);
- pict->colour = get_v4l_control(inode, file,
+ pict->colour = get_v4l_control(file,
V4L2_CID_SATURATION, drv);
- pict->whiteness = get_v4l_control(inode, file,
+ pict->whiteness = get_v4l_control(file,
V4L2_CID_WHITENESS, drv);
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -669,7 +656,6 @@ done:
static noinline int v4l1_compat_set_picture(
struct video_picture *pict,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -685,15 +671,15 @@ static noinline int v4l1_compat_set_picture(
}
memset(&fbuf, 0, sizeof(fbuf));
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_BRIGHTNESS, pict->brightness, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_HUE, pict->hue, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_CONTRAST, pict->contrast, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_SATURATION, pict->colour, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_WHITENESS, pict->whiteness, drv);
/*
* V4L1 uses this ioctl to set both memory capture and overlay
@@ -703,7 +689,7 @@ static noinline int v4l1_compat_set_picture(
*/
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
/* If VIDIOC_G_FMT failed, then the driver likely doesn't
support memory capture. Trying to set the memory capture
parameters would be pointless. */
@@ -714,13 +700,13 @@ static noinline int v4l1_compat_set_picture(
palette_to_pixelformat(pict->palette)) {
fmt->fmt.pix.pixelformat = palette_to_pixelformat(
pict->palette);
- mem_err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ mem_err = drv(file, VIDIOC_S_FMT, fmt);
if (mem_err < 0)
dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
mem_err);
}
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ err = drv(file, VIDIOC_G_FBUF, &fbuf);
/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
support overlay. Trying to set the overlay parameters
would be quite pointless. */
@@ -731,7 +717,7 @@ static noinline int v4l1_compat_set_picture(
palette_to_pixelformat(pict->palette)) {
fbuf.fmt.pixelformat = palette_to_pixelformat(
pict->palette);
- ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+ ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf);
if (ovl_err < 0)
dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
ovl_err);
@@ -752,7 +738,6 @@ static noinline int v4l1_compat_set_picture(
static noinline int v4l1_compat_get_tuner(
struct video_tuner *tun,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -762,7 +747,7 @@ static noinline int v4l1_compat_get_tuner(
v4l2_std_id sid;
memset(&tun2, 0, sizeof(tun2));
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+ err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
goto done;
@@ -778,7 +763,7 @@ static noinline int v4l1_compat_get_tuner(
for (i = 0; i < 64; i++) {
memset(&std2, 0, sizeof(std2));
std2.index = i;
- if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+ if (0 != drv(file, VIDIOC_ENUMSTD, &std2))
break;
if (std2.id & V4L2_STD_PAL)
tun->flags |= VIDEO_TUNER_PAL;
@@ -788,7 +773,7 @@ static noinline int v4l1_compat_get_tuner(
tun->flags |= VIDEO_TUNER_SECAM;
}
- err = drv(inode, file, VIDIOC_G_STD, &sid);
+ err = drv(file, VIDIOC_G_STD, &sid);
if (err < 0)
dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
if (err == 0) {
@@ -811,7 +796,6 @@ done:
static noinline int v4l1_compat_select_tuner(
struct video_tuner *tun,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -821,7 +805,7 @@ static noinline int v4l1_compat_select_tuner(
t.index = tun->tuner;
- err = drv(inode, file, VIDIOC_S_INPUT, &t);
+ err = drv(file, VIDIOC_S_INPUT, &t);
if (err < 0)
dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
return err;
@@ -829,7 +813,6 @@ static noinline int v4l1_compat_select_tuner(
static noinline int v4l1_compat_get_frequency(
unsigned long *freq,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -838,7 +821,7 @@ static noinline int v4l1_compat_get_frequency(
memset(&freq2, 0, sizeof(freq2));
freq2.tuner = 0;
- err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+ err = drv(file, VIDIOC_G_FREQUENCY, &freq2);
if (err < 0)
dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
if (0 == err)
@@ -848,7 +831,6 @@ static noinline int v4l1_compat_get_frequency(
static noinline int v4l1_compat_set_frequency(
unsigned long *freq,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -856,9 +838,9 @@ static noinline int v4l1_compat_set_frequency(
struct v4l2_frequency freq2;
memset(&freq2, 0, sizeof(freq2));
- drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+ drv(file, VIDIOC_G_FREQUENCY, &freq2);
freq2.frequency = *freq;
- err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
+ err = drv(file, VIDIOC_S_FREQUENCY, &freq2);
if (err < 0)
dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
return err;
@@ -866,7 +848,6 @@ static noinline int v4l1_compat_set_frequency(
static noinline int v4l1_compat_get_audio(
struct video_audio *aud,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -876,7 +857,7 @@ static noinline int v4l1_compat_get_audio(
struct v4l2_tuner tun2;
memset(&aud2, 0, sizeof(aud2));
- err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
+ err = drv(file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
goto done;
@@ -886,27 +867,27 @@ static noinline int v4l1_compat_get_audio(
aud->name[sizeof(aud->name) - 1] = 0;
aud->audio = aud2.index;
aud->flags = 0;
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv);
if (i >= 0) {
aud->volume = i;
aud->flags |= VIDEO_AUDIO_VOLUME;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv);
if (i >= 0) {
aud->bass = i;
aud->flags |= VIDEO_AUDIO_BASS;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv);
if (i >= 0) {
aud->treble = i;
aud->flags |= VIDEO_AUDIO_TREBLE;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv);
if (i >= 0) {
aud->balance = i;
aud->flags |= VIDEO_AUDIO_BALANCE;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv);
if (i >= 0) {
if (i)
aud->flags |= VIDEO_AUDIO_MUTE;
@@ -914,13 +895,13 @@ static noinline int v4l1_compat_get_audio(
}
aud->step = 1;
qctrl2.id = V4L2_CID_AUDIO_VOLUME;
- if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+ if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
!(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
aud->step = qctrl2.step;
aud->mode = 0;
memset(&tun2, 0, sizeof(tun2));
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+ err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
err = 0;
@@ -939,7 +920,6 @@ done:
static noinline int v4l1_compat_set_audio(
struct video_audio *aud,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -951,24 +931,24 @@ static noinline int v4l1_compat_set_audio(
memset(&tun2, 0, sizeof(tun2));
aud2.index = aud->audio;
- err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
+ err = drv(file, VIDIOC_S_AUDIO, &aud2);
if (err < 0) {
dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
goto done;
}
- set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
+ set_v4l_control(file, V4L2_CID_AUDIO_VOLUME,
aud->volume, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
+ set_v4l_control(file, V4L2_CID_AUDIO_BASS,
aud->bass, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
+ set_v4l_control(file, V4L2_CID_AUDIO_TREBLE,
aud->treble, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
+ set_v4l_control(file, V4L2_CID_AUDIO_BALANCE,
aud->balance, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
+ set_v4l_control(file, V4L2_CID_AUDIO_MUTE,
!!(aud->flags & VIDEO_AUDIO_MUTE), drv);
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+ err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0)
dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
if (err == 0) {
@@ -985,7 +965,7 @@ static noinline int v4l1_compat_set_audio(
tun2.audmode = V4L2_TUNER_MODE_LANG2;
break;
}
- err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
+ err = drv(file, VIDIOC_S_TUNER, &tun2);
if (err < 0)
dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
}
@@ -996,7 +976,6 @@ done:
static noinline int v4l1_compat_capture_frame(
struct video_mmap *mm,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1013,7 +992,7 @@ static noinline int v4l1_compat_capture_frame(
memset(&buf, 0, sizeof(buf));
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -1029,7 +1008,7 @@ static noinline int v4l1_compat_capture_frame(
palette_to_pixelformat(mm->format);
fmt->fmt.pix.field = V4L2_FIELD_ANY;
fmt->fmt.pix.bytesperline = 0;
- err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ err = drv(file, VIDIOC_S_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
goto done;
@@ -1037,17 +1016,17 @@ static noinline int v4l1_compat_capture_frame(
}
buf.index = mm->frame;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+ err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
goto done;
}
- err = drv(inode, file, VIDIOC_QBUF, &buf);
+ err = drv(file, VIDIOC_QBUF, &buf);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
goto done;
}
- err = drv(inode, file, VIDIOC_STREAMON, &captype);
+ err = drv(file, VIDIOC_STREAMON, &captype);
if (err < 0)
dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
done:
@@ -1057,7 +1036,6 @@ done:
static noinline int v4l1_compat_sync(
int *i,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1069,7 +1047,7 @@ static noinline int v4l1_compat_sync(
memset(&buf, 0, sizeof(buf));
buf.index = *i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+ err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0) {
/* No such buffer */
dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
@@ -1082,7 +1060,7 @@ static noinline int v4l1_compat_sync(
}
/* make sure capture actually runs so we don't block forever */
- err = drv(inode, file, VIDIOC_STREAMON, &captype);
+ err = drv(file, VIDIOC_STREAMON, &captype);
if (err < 0) {
dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
goto done;
@@ -1096,7 +1074,7 @@ static noinline int v4l1_compat_sync(
if (err < 0 || /* error or sleep was interrupted */
err == 0) /* timeout? Shouldn't occur. */
break;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+ err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0)
dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
}
@@ -1104,7 +1082,7 @@ static noinline int v4l1_compat_sync(
if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
goto done;
do {
- err = drv(inode, file, VIDIOC_DQBUF, &buf);
+ err = drv(file, VIDIOC_DQBUF, &buf);
if (err < 0)
dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
} while (err == 0 && buf.index != *i);
@@ -1114,7 +1092,6 @@ done:
static noinline int v4l1_compat_get_vbi_format(
struct vbi_format *fmt,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1128,7 +1105,7 @@ static noinline int v4l1_compat_get_vbi_format(
}
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+ err = drv(file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -1153,7 +1130,6 @@ done:
static noinline int v4l1_compat_set_vbi_format(
struct vbi_format *fmt,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1179,7 +1155,7 @@ static noinline int v4l1_compat_set_vbi_format(
fmt2->fmt.vbi.start[1] = fmt->start[1];
fmt2->fmt.vbi.count[1] = fmt->count[1];
fmt2->fmt.vbi.flags = fmt->flags;
- err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+ err = drv(file, VIDIOC_TRY_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
goto done;
@@ -1196,7 +1172,7 @@ static noinline int v4l1_compat_set_vbi_format(
err = -EINVAL;
goto done;
}
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+ err = drv(file, VIDIOC_S_FMT, fmt2);
if (err < 0)
dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
done:
@@ -1208,8 +1184,7 @@ done:
* This function is exported.
*/
int
-v4l_compat_translate_ioctl(struct inode *inode,
- struct file *file,
+v4l_compat_translate_ioctl(struct file *file,
int cmd,
void *arg,
v4l2_kioctl drv)
@@ -1218,64 +1193,64 @@ v4l_compat_translate_ioctl(struct inode *inode,
switch (cmd) {
case VIDIOCGCAP: /* capability */
- err = v4l1_compat_get_capabilities(arg, inode, file, drv);
+ err = v4l1_compat_get_capabilities(arg, file, drv);
break;
case VIDIOCGFBUF: /* get frame buffer */
- err = v4l1_compat_get_frame_buffer(arg, inode, file, drv);
+ err = v4l1_compat_get_frame_buffer(arg, file, drv);
break;
case VIDIOCSFBUF: /* set frame buffer */
- err = v4l1_compat_set_frame_buffer(arg, inode, file, drv);
+ err = v4l1_compat_set_frame_buffer(arg, file, drv);
break;
case VIDIOCGWIN: /* get window or capture dimensions */
- err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv);
+ err = v4l1_compat_get_win_cap_dimensions(arg, file, drv);
break;
case VIDIOCSWIN: /* set window and/or capture dimensions */
- err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv);
+ err = v4l1_compat_set_win_cap_dimensions(arg, file, drv);
break;
case VIDIOCCAPTURE: /* turn on/off preview */
- err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv);
+ err = v4l1_compat_turn_preview_on_off(arg, file, drv);
break;
case VIDIOCGCHAN: /* get input information */
- err = v4l1_compat_get_input_info(arg, inode, file, drv);
+ err = v4l1_compat_get_input_info(arg, file, drv);
break;
case VIDIOCSCHAN: /* set input */
- err = v4l1_compat_set_input(arg, inode, file, drv);
+ err = v4l1_compat_set_input(arg, file, drv);
break;
case VIDIOCGPICT: /* get tone controls & partial capture format */
- err = v4l1_compat_get_picture(arg, inode, file, drv);
+ err = v4l1_compat_get_picture(arg, file, drv);
break;
case VIDIOCSPICT: /* set tone controls & partial capture format */
- err = v4l1_compat_set_picture(arg, inode, file, drv);
+ err = v4l1_compat_set_picture(arg, file, drv);
break;
case VIDIOCGTUNER: /* get tuner information */
- err = v4l1_compat_get_tuner(arg, inode, file, drv);
+ err = v4l1_compat_get_tuner(arg, file, drv);
break;
case VIDIOCSTUNER: /* select a tuner input */
- err = v4l1_compat_select_tuner(arg, inode, file, drv);
+ err = v4l1_compat_select_tuner(arg, file, drv);
break;
case VIDIOCGFREQ: /* get frequency */
- err = v4l1_compat_get_frequency(arg, inode, file, drv);
+ err = v4l1_compat_get_frequency(arg, file, drv);
break;
case VIDIOCSFREQ: /* set frequency */
- err = v4l1_compat_set_frequency(arg, inode, file, drv);
+ err = v4l1_compat_set_frequency(arg, file, drv);
break;
case VIDIOCGAUDIO: /* get audio properties/controls */
- err = v4l1_compat_get_audio(arg, inode, file, drv);
+ err = v4l1_compat_get_audio(arg, file, drv);
break;
case VIDIOCSAUDIO: /* set audio controls */
- err = v4l1_compat_set_audio(arg, inode, file, drv);
+ err = v4l1_compat_set_audio(arg, file, drv);
break;
case VIDIOCMCAPTURE: /* capture a frame */
- err = v4l1_compat_capture_frame(arg, inode, file, drv);
+ err = v4l1_compat_capture_frame(arg, file, drv);
break;
case VIDIOCSYNC: /* wait for a frame */
- err = v4l1_compat_sync(arg, inode, file, drv);
+ err = v4l1_compat_sync(arg, file, drv);
break;
case VIDIOCGVBIFMT: /* query VBI data capture format */
- err = v4l1_compat_get_vbi_format(arg, inode, file, drv);
+ err = v4l1_compat_get_vbi_format(arg, file, drv);
break;
case VIDIOCSVBIFMT:
- err = v4l1_compat_set_vbi_format(arg, inode, file, drv);
+ err = v4l1_compat_set_vbi_format(arg, file, drv);
break;
default:
err = -ENOIOCTLCMD;
diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
index 0e4549922f2..a935bae538e 100644
--- a/drivers/media/video/v4l2-int-device.c
+++ b/drivers/media/video/v4l2-int-device.c
@@ -32,7 +32,7 @@
static DEFINE_MUTEX(mutex);
static LIST_HEAD(int_list);
-static void v4l2_int_device_try_attach_all(void)
+void v4l2_int_device_try_attach_all(void)
{
struct v4l2_int_device *m, *s;
@@ -66,6 +66,7 @@ static void v4l2_int_device_try_attach_all(void)
}
}
}
+EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all);
static int ioctl_sort_cmp(const void *a, const void *b)
{
@@ -144,6 +145,7 @@ int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd)
find_ioctl(d->u.slave, cmd,
(v4l2_int_ioctl_func *)no_such_ioctl_0))(d);
}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_0);
static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg)
{
@@ -156,5 +158,6 @@ int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
find_ioctl(d->u.slave, cmd,
(v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_1);
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 155c9d77a46..710e1a40c42 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -625,13 +625,13 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
return -EINVAL;
}
-static int __video_do_ioctl(struct inode *inode, struct file *file,
+static int __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
- void *fh = file->private_data;
- int ret = -EINVAL;
+ void *fh = file->private_data;
+ int ret = -EINVAL;
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
@@ -675,7 +675,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
V4L2 ioctls.
********************************************************/
if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE)
- return v4l_compat_translate_ioctl(inode, file, cmd, arg,
+ return v4l_compat_translate_ioctl(file, cmd, arg,
__video_do_ioctl);
#endif
@@ -1768,7 +1768,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
return ret;
}
-int video_ioctl2(struct inode *inode, struct file *file,
+int __video_ioctl2(struct file *file,
unsigned int cmd, unsigned long arg)
{
char sbuf[128];
@@ -1832,7 +1832,7 @@ int video_ioctl2(struct inode *inode, struct file *file,
}
/* Handles IOCTL */
- err = __video_do_ioctl(inode, file, cmd, parg);
+ err = __video_do_ioctl(file, cmd, parg);
if (err == -ENOIOCTLCMD)
err = -EINVAL;
if (is_ext_ctrl) {
@@ -1860,4 +1860,11 @@ out:
kfree(mbuf);
return err;
}
+EXPORT_SYMBOL(__video_ioctl2);
+
+int video_ioctl2(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return __video_ioctl2(file, cmd, arg);
+}
EXPORT_SYMBOL(video_ioctl2);
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index 917277d3660..0e7dcba8e4a 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -296,29 +296,7 @@ EXPORT_SYMBOL(videobuf_dvb_register_bus);
void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
{
- struct list_head *list, *q;
- struct videobuf_dvb_frontend *fe;
-
- mutex_lock(&f->lock);
- list_for_each_safe(list, q, &f->felist) {
- fe = list_entry(list, struct videobuf_dvb_frontend, felist);
- if (fe->dvb.net.dvbdev) {
- dvb_net_release(&fe->dvb.net);
- fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
- &fe->dvb.fe_mem);
- fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
- &fe->dvb.fe_hw);
- dvb_dmxdev_release(&fe->dvb.dmxdev);
- dvb_dmx_release(&fe->dvb.demux);
- dvb_unregister_frontend(fe->dvb.frontend);
- }
- if (fe->dvb.frontend)
- /* always allocated, may have been reset */
- dvb_frontend_detach(fe->dvb.frontend);
- list_del(list);
- kfree(fe);
- }
- mutex_unlock(&f->lock);
+ videobuf_dvb_dealloc_frontends(f);
dvb_unregister_adapter(&f->adapter);
}
@@ -389,3 +367,31 @@ fail_alloc:
return fe;
}
EXPORT_SYMBOL(videobuf_dvb_alloc_frontend);
+
+void videobuf_dvb_dealloc_frontends(struct videobuf_dvb_frontends *f)
+{
+ struct list_head *list, *q;
+ struct videobuf_dvb_frontend *fe;
+
+ mutex_lock(&f->lock);
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ if (fe->dvb.net.dvbdev) {
+ dvb_net_release(&fe->dvb.net);
+ fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+ &fe->dvb.fe_mem);
+ fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+ &fe->dvb.fe_hw);
+ dvb_dmxdev_release(&fe->dvb.dmxdev);
+ dvb_dmx_release(&fe->dvb.demux);
+ dvb_unregister_frontend(fe->dvb.frontend);
+ }
+ if (fe->dvb.frontend)
+ /* always allocated, may have been reset */
+ dvb_frontend_detach(fe->dvb.frontend);
+ list_del(list); /* remove list entry */
+ kfree(fe); /* free frontend allocation */
+ }
+ mutex_unlock(&f->lock);
+}
+EXPORT_SYMBOL(videobuf_dvb_dealloc_frontends);
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 7d7e51def46..e15e48f04be 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -1163,11 +1163,11 @@ static int vivi_release(void)
if (-1 != dev->vfd->minor) {
printk(KERN_INFO "%s: unregistering /dev/video%d\n",
- VIVI_MODULE_NAME, dev->vfd->minor);
+ VIVI_MODULE_NAME, dev->vfd->num);
video_unregister_device(dev->vfd);
} else {
printk(KERN_INFO "%s: releasing /dev/video%d\n",
- VIVI_MODULE_NAME, dev->vfd->minor);
+ VIVI_MODULE_NAME, dev->vfd->num);
video_device_release(dev->vfd);
}
@@ -1307,7 +1307,7 @@ static int __init vivi_init(void)
dev->vfd = vfd;
printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
- VIVI_MODULE_NAME, vfd->minor);
+ VIVI_MODULE_NAME, vfd->num);
}
if (ret < 0) {
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index dcd45dbd82d..4dfb43bd184 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -2398,7 +2398,7 @@ error:
cam->sensor = CC_UNKNOWN;
DBG(1, "Image sensor initialization failed for %s (/dev/video%d). "
"Try to detach and attach this device again",
- symbolic(camlist, cam->id), cam->v4ldev->minor)
+ symbolic(camlist, cam->id), cam->v4ldev->num)
return err;
}
@@ -2644,7 +2644,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
{
mutex_lock(&w9968cf_devlist_mutex);
- DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor)
+ DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->num)
video_unregister_device(cam->v4ldev);
list_del(&cam->v4llist);
@@ -2679,7 +2679,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
DBG(2, "No supported image sensor has been detected by the "
"'ovcamchip' module for the %s (/dev/video%d). Make "
"sure it is loaded *before* (re)connecting the camera.",
- symbolic(camlist, cam->id), cam->v4ldev->minor)
+ symbolic(camlist, cam->id), cam->v4ldev->num)
mutex_unlock(&cam->dev_mutex);
up_read(&w9968cf_disconnect);
return -ENODEV;
@@ -2687,7 +2687,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
if (cam->users) {
DBG(2, "%s (/dev/video%d) has been already occupied by '%s'",
- symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command)
+ symbolic(camlist, cam->id), cam->v4ldev->num, cam->command)
if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
mutex_unlock(&cam->dev_mutex);
up_read(&w9968cf_disconnect);
@@ -2709,7 +2709,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
}
DBG(5, "Opening '%s', /dev/video%d ...",
- symbolic(camlist, cam->id), cam->v4ldev->minor)
+ symbolic(camlist, cam->id), cam->v4ldev->num)
cam->streaming = 0;
cam->misconfigured = 0;
@@ -2947,7 +2947,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
.minheight = cam->minheight,
};
sprintf(cap.name, "W996[87]CF USB Camera #%d",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cap.maxwidth = (cam->upscaling && w9968cf_vpp)
? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
: cam->maxwidth;
@@ -3567,7 +3567,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor)
+ DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->num)
/* Set some basic constants */
w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
@@ -3618,7 +3618,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
DBG(2, "The device is open (/dev/video%d)! "
"Process name: %s. Deregistration and memory "
"deallocation are deferred on close.",
- cam->v4ldev->minor, cam->command)
+ cam->v4ldev->num, cam->command)
cam->misconfigured = 1;
w9968cf_stop_transfer(cam);
wake_up_interruptible(&cam->wait_queue);
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 6a0902bcba6..9fc58170763 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -539,7 +539,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "URB timeout reached. The camera is misconfigured. To "
"use it, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -640,7 +640,7 @@ static void zc0301_release_resources(struct kref *kref)
{
struct zc0301_device *cam = container_of(kref, struct zc0301_device,
kref);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
@@ -679,7 +679,7 @@ static int zc0301_open(struct inode* inode, struct file* filp)
}
if (cam->users) {
- DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+ DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->num);
DBG(3, "Simultaneous opens are not supported");
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
@@ -722,7 +722,7 @@ static int zc0301_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
zc0301_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
out:
mutex_unlock(&cam->open_mutex);
@@ -746,7 +746,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->wait_open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
kref_put(&cam->kref, zc0301_release_resources);
@@ -1275,7 +1275,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1288,7 +1288,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -1470,7 +1470,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1482,7 +1482,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -1529,7 +1529,7 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
"problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor);
+ "/dev/video%d again.", cam->v4ldev->num);
return -EIO;
}
@@ -2005,7 +2005,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
cam->module_param.force_munmap = force_munmap[dev_nr];
cam->module_param.frame_timeout = frame_timeout[dev_nr];
@@ -2044,7 +2044,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf)
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cam->state |= DEV_MISCONFIGURED;
zc0301_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index 7cdac99deea..a1d81ed44c7 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -885,7 +885,7 @@ static int zr364xx_probe(struct usb_interface *intf,
usb_set_intfdata(intf, cam);
dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
- cam->vdev->minor);
+ cam->vdev->num);
return 0;
}
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 6e291bf8237..7911151e56a 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -172,9 +172,9 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error);
/*** Block device ***/
-static int mspro_block_bd_open(struct inode *inode, struct file *filp)
+static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
struct mspro_block_data *msb = disk->private_data;
int rc = -ENXIO;
@@ -182,7 +182,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp)
if (msb && msb->card) {
msb->usage_count++;
- if ((filp->f_mode & FMODE_WRITE) && msb->read_only)
+ if ((mode & FMODE_WRITE) && msb->read_only)
rc = -EROFS;
else
rc = 0;
@@ -218,9 +218,8 @@ static int mspro_block_disk_release(struct gendisk *disk)
return 0;
}
-static int mspro_block_bd_release(struct inode *inode, struct file *filp)
+static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
return mspro_block_disk_release(disk);
}
@@ -1044,7 +1043,6 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
s_attr->dev_attr.attr.name = s_attr->name;
s_attr->dev_attr.attr.mode = S_IRUGO;
- s_attr->dev_attr.attr.owner = THIS_MODULE;
s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id);
if (!rc)
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 9f9354fd351..d62fd4f6b52 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1760,10 +1760,9 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
case FC:
return 40;
case SAS:
- return 10;
case SPI:
default:
- return 2;
+ return 10;
}
}
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 81483de8c0f..11a617ab424 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -575,9 +575,9 @@ static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls,
*
* Returns 0 on success or negative error code on failure.
*/
-static int i2o_block_open(struct inode *inode, struct file *file)
+static int i2o_block_open(struct block_device *bdev, fmode_t mode)
{
- struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data;
+ struct i2o_block_device *dev = bdev->bd_disk->private_data;
if (!dev->i2o_dev)
return -ENODEV;
@@ -604,9 +604,8 @@ static int i2o_block_open(struct inode *inode, struct file *file)
*
* Returns 0 on success or negative error code on failure.
*/
-static int i2o_block_release(struct inode *inode, struct file *file)
+static int i2o_block_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2o_block_device *dev = disk->private_data;
u8 operation;
@@ -653,10 +652,10 @@ static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
*
* Return 0 on success or negative error on failure.
*/
-static int i2o_block_ioctl(struct inode *inode, struct file *file,
+static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
struct i2o_block_device *dev = disk->private_data;
/* Anyone capable of this syscall can do *real bad* things */
@@ -933,7 +932,7 @@ static struct block_device_operations i2o_block_fops = {
.owner = THIS_MODULE,
.open = i2o_block_open,
.release = i2o_block_release,
- .ioctl = i2o_block_ioctl,
+ .locked_ioctl = i2o_block_ioctl,
.getgeo = i2o_block_getgeo,
.media_changed = i2o_block_media_changed
};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 5eff8ad834d..5a79d2d4cda 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -52,6 +52,8 @@ config HTC_PASIC3
config UCB1400_CORE
tristate "Philips UCB1400 Core driver"
+ depends on AC97_BUS
+ depends on GPIOLIB
help
This enables support for the Philips UCB1400 core functions.
The UCB1400 is an AC97 audio codec.
@@ -59,6 +61,20 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the
module will be called ucb1400_core.
+config TWL4030_CORE
+ bool "Texas Instruments TWL4030/TPS659x0 Support"
+ depends on I2C=y && GENERIC_HARDIRQS && (ARCH_OMAP2 || ARCH_OMAP3)
+ help
+ Say yes here if you have TWL4030 family chip on your board.
+ This core driver provides register access and IRQ handling
+ facilities, and registers devices for the various functions
+ so that function-specific drivers can bind to them.
+
+ These multi-function chips are found on many OMAP2 and OMAP3
+ boards, providing power management, RTC, GPIO, keypad, a
+ high speed USB OTG transceiver, an audio codec (on most
+ versions) and many other features.
+
config MFD_TMIO
bool
default n
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 759b1fe1c89..0acefe8aff8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -17,6 +17,8 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
+obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
+
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_MCP) += mcp-core.o
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index ba5aa200827..e4c0db4dc7b 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -123,7 +123,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
irqnr = asic->irq_base +
(ASIC3_GPIOS_PER_BANK * bank)
+ i;
- desc = irq_desc + irqnr;
+ desc = irq_to_desc(irqnr);
desc->handle_irq(irqnr, desc);
if (asic->irq_bothedge[bank] & bit)
asic3_irq_flip_edge(asic, base,
@@ -136,7 +136,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
/* They start at bit 4 and go up */
if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
- desc = irq_desc + asic->irq_base + i;
+ desc = irq_to_desc(asic->irq_base + i);
desc->handle_irq(asic->irq_base + i,
desc);
}
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
new file mode 100644
index 00000000000..b57326ae464
--- /dev/null
+++ b/drivers/mfd/da903x.c
@@ -0,0 +1,563 @@
+/*
+ * Base driver for Dialog Semiconductor DA9030/DA9034
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Eric Miao <eric.miao@marvell.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/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/mfd/da903x.h>
+
+#define DA9030_CHIP_ID 0x00
+#define DA9030_EVENT_A 0x01
+#define DA9030_EVENT_B 0x02
+#define DA9030_EVENT_C 0x03
+#define DA9030_STATUS 0x04
+#define DA9030_IRQ_MASK_A 0x05
+#define DA9030_IRQ_MASK_B 0x06
+#define DA9030_IRQ_MASK_C 0x07
+#define DA9030_SYS_CTRL_A 0x08
+#define DA9030_SYS_CTRL_B 0x09
+#define DA9030_FAULT_LOG 0x0a
+
+#define DA9034_CHIP_ID 0x00
+#define DA9034_EVENT_A 0x01
+#define DA9034_EVENT_B 0x02
+#define DA9034_EVENT_C 0x03
+#define DA9034_EVENT_D 0x04
+#define DA9034_STATUS_A 0x05
+#define DA9034_STATUS_B 0x06
+#define DA9034_IRQ_MASK_A 0x07
+#define DA9034_IRQ_MASK_B 0x08
+#define DA9034_IRQ_MASK_C 0x09
+#define DA9034_IRQ_MASK_D 0x0a
+#define DA9034_SYS_CTRL_A 0x0b
+#define DA9034_SYS_CTRL_B 0x0c
+#define DA9034_FAULT_LOG 0x0d
+
+struct da903x_chip;
+
+struct da903x_chip_ops {
+ int (*init_chip)(struct da903x_chip *);
+ int (*unmask_events)(struct da903x_chip *, unsigned int events);
+ int (*mask_events)(struct da903x_chip *, unsigned int events);
+ int (*read_events)(struct da903x_chip *, unsigned int *events);
+ int (*read_status)(struct da903x_chip *, unsigned int *status);
+};
+
+struct da903x_chip {
+ struct i2c_client *client;
+ struct device *dev;
+ struct da903x_chip_ops *ops;
+
+ int type;
+ uint32_t events_mask;
+
+ struct mutex lock;
+ struct work_struct irq_work;
+
+ struct blocking_notifier_head notifier_list;
+};
+
+static inline int __da903x_read(struct i2c_client *client,
+ int reg, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
+ return ret;
+ }
+
+ *val = (uint8_t)ret;
+ return 0;
+}
+
+static inline int __da903x_reads(struct i2c_client *client, int reg,
+ int len, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
+ return ret;
+ }
+ return 0;
+}
+
+static inline int __da903x_write(struct i2c_client *client,
+ int reg, uint8_t val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
+ val, reg);
+ return ret;
+ }
+ return 0;
+}
+
+static inline int __da903x_writes(struct i2c_client *client, int reg,
+ int len, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
+ return ret;
+ }
+ return 0;
+}
+
+int da903x_register_notifier(struct device *dev, struct notifier_block *nb,
+ unsigned int events)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+
+ chip->ops->unmask_events(chip, events);
+ return blocking_notifier_chain_register(&chip->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(da903x_register_notifier);
+
+int da903x_unregister_notifier(struct device *dev, struct notifier_block *nb,
+ unsigned int events)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+
+ chip->ops->mask_events(chip, events);
+ return blocking_notifier_chain_unregister(&chip->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(da903x_unregister_notifier);
+
+int da903x_write(struct device *dev, int reg, uint8_t val)
+{
+ return __da903x_write(to_i2c_client(dev), reg, val);
+}
+EXPORT_SYMBOL_GPL(da903x_write);
+
+int da903x_read(struct device *dev, int reg, uint8_t *val)
+{
+ return __da903x_read(to_i2c_client(dev), reg, val);
+}
+EXPORT_SYMBOL_GPL(da903x_read);
+
+int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ uint8_t reg_val;
+ int ret = 0;
+
+ mutex_lock(&chip->lock);
+
+ ret = __da903x_read(chip->client, reg, &reg_val);
+ if (ret)
+ goto out;
+
+ if ((reg_val & bit_mask) == 0) {
+ reg_val |= bit_mask;
+ ret = __da903x_write(chip->client, reg, reg_val);
+ }
+out:
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(da903x_set_bits);
+
+int da903x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ uint8_t reg_val;
+ int ret = 0;
+
+ mutex_lock(&chip->lock);
+
+ ret = __da903x_read(chip->client, reg, &reg_val);
+ if (ret)
+ goto out;
+
+ if (reg_val & bit_mask) {
+ reg_val &= ~bit_mask;
+ ret = __da903x_write(chip->client, reg, reg_val);
+ }
+out:
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(da903x_clr_bits);
+
+int da903x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ uint8_t reg_val;
+ int ret = 0;
+
+ mutex_lock(&chip->lock);
+
+ ret = __da903x_read(chip->client, reg, &reg_val);
+ if (ret)
+ goto out;
+
+ if ((reg_val & mask) != val) {
+ reg_val = (reg_val & ~mask) | val;
+ ret = __da903x_write(chip->client, reg, reg_val);
+ }
+out:
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(da903x_update);
+
+int da903x_query_status(struct device *dev, unsigned int sbits)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ unsigned int status = 0;
+
+ chip->ops->read_status(chip, &status);
+ return ((status & sbits) == sbits);
+}
+EXPORT_SYMBOL(da903x_query_status);
+
+static int __devinit da9030_init_chip(struct da903x_chip *chip)
+{
+ uint8_t chip_id;
+ int err;
+
+ err = __da903x_read(chip->client, DA9030_CHIP_ID, &chip_id);
+ if (err)
+ return err;
+
+ err = __da903x_write(chip->client, DA9030_SYS_CTRL_A, 0xE8);
+ if (err)
+ return err;
+
+ dev_info(chip->dev, "DA9030 (CHIP ID: 0x%02x) detected\n", chip_id);
+ return 0;
+}
+
+static int da9030_unmask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[3];
+
+ chip->events_mask &= ~events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+
+ return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v);
+}
+
+static int da9030_mask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[3];
+
+ chip->events_mask &= ~events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+
+ return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v);
+}
+
+static int da9030_read_events(struct da903x_chip *chip, unsigned int *events)
+{
+ uint8_t v[3] = {0, 0, 0};
+ int ret;
+
+ ret = __da903x_reads(chip->client, DA9030_EVENT_A, 3, v);
+ if (ret < 0)
+ return ret;
+
+ *events = (v[2] << 16) | (v[1] << 8) | v[0];
+ return 0;
+}
+
+static int da9030_read_status(struct da903x_chip *chip, unsigned int *status)
+{
+ return __da903x_read(chip->client, DA9030_STATUS, (uint8_t *)status);
+}
+
+static int da9034_init_chip(struct da903x_chip *chip)
+{
+ uint8_t chip_id;
+ int err;
+
+ err = __da903x_read(chip->client, DA9034_CHIP_ID, &chip_id);
+ if (err)
+ return err;
+
+ err = __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0xE8);
+ if (err)
+ return err;
+
+ /* avoid SRAM power off during sleep*/
+ __da903x_write(chip->client, 0x10, 0x07);
+ __da903x_write(chip->client, 0x11, 0xff);
+ __da903x_write(chip->client, 0x12, 0xff);
+
+ /* Enable the ONKEY power down functionality */
+ __da903x_write(chip->client, DA9034_SYS_CTRL_B, 0x20);
+ __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0x60);
+
+ /* workaround to make LEDs work */
+ __da903x_write(chip->client, 0x90, 0x01);
+ __da903x_write(chip->client, 0xB0, 0x08);
+
+ /* make ADTV1 and SDTV1 effective */
+ __da903x_write(chip->client, 0x20, 0x00);
+
+ dev_info(chip->dev, "DA9034 (CHIP ID: 0x%02x) detected\n", chip_id);
+ return 0;
+}
+
+static int da9034_unmask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[4];
+
+ chip->events_mask &= ~events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+ v[3] = (chip->events_mask >> 24) & 0xff;
+
+ return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v);
+}
+
+static int da9034_mask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[4];
+
+ chip->events_mask |= events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+ v[3] = (chip->events_mask >> 24) & 0xff;
+
+ return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v);
+}
+
+static int da9034_read_events(struct da903x_chip *chip, unsigned int *events)
+{
+ uint8_t v[4] = {0, 0, 0, 0};
+ int ret;
+
+ ret = __da903x_reads(chip->client, DA9034_EVENT_A, 4, v);
+ if (ret < 0)
+ return ret;
+
+ *events = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0];
+ return 0;
+}
+
+static int da9034_read_status(struct da903x_chip *chip, unsigned int *status)
+{
+ uint8_t v[2] = {0, 0};
+ int ret = 0;
+
+ ret = __da903x_reads(chip->client, DA9034_STATUS_A, 2, v);
+ if (ret)
+ return ret;
+
+ *status = (v[1] << 8) | v[0];
+ return 0;
+}
+
+static void da903x_irq_work(struct work_struct *work)
+{
+ struct da903x_chip *chip =
+ container_of(work, struct da903x_chip, irq_work);
+ unsigned int events = 0;
+
+ while (1) {
+ if (chip->ops->read_events(chip, &events))
+ break;
+
+ events &= ~chip->events_mask;
+ if (events == 0)
+ break;
+
+ blocking_notifier_call_chain(
+ &chip->notifier_list, events, NULL);
+ }
+ enable_irq(chip->client->irq);
+}
+
+static int da903x_irq_handler(int irq, void *data)
+{
+ struct da903x_chip *chip = data;
+
+ disable_irq_nosync(irq);
+ (void)schedule_work(&chip->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static struct da903x_chip_ops da903x_ops[] = {
+ [0] = {
+ .init_chip = da9030_init_chip,
+ .unmask_events = da9030_unmask_events,
+ .mask_events = da9030_mask_events,
+ .read_events = da9030_read_events,
+ .read_status = da9030_read_status,
+ },
+ [1] = {
+ .init_chip = da9034_init_chip,
+ .unmask_events = da9034_unmask_events,
+ .mask_events = da9034_mask_events,
+ .read_events = da9034_read_events,
+ .read_status = da9034_read_status,
+ }
+};
+
+static const struct i2c_device_id da903x_id_table[] = {
+ { "da9030", 0 },
+ { "da9034", 1 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, da903x_id_table);
+
+static int __devexit __remove_subdev(struct device *dev, void *unused)
+{
+ platform_device_unregister(to_platform_device(dev));
+ return 0;
+}
+
+static int __devexit da903x_remove_subdevs(struct da903x_chip *chip)
+{
+ return device_for_each_child(chip->dev, NULL, __remove_subdev);
+}
+
+static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
+ struct da903x_platform_data *pdata)
+{
+ struct da903x_subdev_info *subdev;
+ struct platform_device *pdev;
+ int i, ret = 0;
+
+ for (i = 0; i < pdata->num_subdevs; i++) {
+ subdev = &pdata->subdevs[i];
+
+ pdev = platform_device_alloc(subdev->name, subdev->id);
+
+ pdev->dev.parent = chip->dev;
+ pdev->dev.platform_data = subdev->platform_data;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto failed;
+ }
+ return 0;
+
+failed:
+ da903x_remove_subdevs(chip);
+ return ret;
+}
+
+static int __devinit da903x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct da903x_platform_data *pdata = client->dev.platform_data;
+ struct da903x_chip *chip;
+ unsigned int tmp;
+ int ret;
+
+ chip = kzalloc(sizeof(struct da903x_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ chip->client = client;
+ chip->dev = &client->dev;
+ chip->ops = &da903x_ops[id->driver_data];
+
+ mutex_init(&chip->lock);
+ INIT_WORK(&chip->irq_work, da903x_irq_work);
+ BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list);
+
+ i2c_set_clientdata(client, chip);
+
+ ret = chip->ops->init_chip(chip);
+ if (ret)
+ goto out_free_chip;
+
+ /* mask and clear all IRQs */
+ chip->events_mask = 0xffffffff;
+ chip->ops->mask_events(chip, chip->events_mask);
+ chip->ops->read_events(chip, &tmp);
+
+ ret = request_irq(client->irq, da903x_irq_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "da903x", chip);
+ if (ret) {
+ dev_err(&client->dev, "failed to request irq %d\n",
+ client->irq);
+ goto out_free_chip;
+ }
+
+ ret = da903x_add_subdevs(chip, pdata);
+ if (ret)
+ goto out_free_irq;
+
+ return 0;
+
+out_free_irq:
+ free_irq(client->irq, chip);
+out_free_chip:
+ i2c_set_clientdata(client, NULL);
+ kfree(chip);
+ return ret;
+}
+
+static int __devexit da903x_remove(struct i2c_client *client)
+{
+ struct da903x_chip *chip = i2c_get_clientdata(client);
+
+ da903x_remove_subdevs(chip);
+ kfree(chip);
+ return 0;
+}
+
+static struct i2c_driver da903x_driver = {
+ .driver = {
+ .name = "da903x",
+ .owner = THIS_MODULE,
+ },
+ .probe = da903x_probe,
+ .remove = __devexit_p(da903x_remove),
+ .id_table = da903x_id_table,
+};
+
+static int __init da903x_init(void)
+{
+ return i2c_add_driver(&da903x_driver);
+}
+module_init(da903x_init);
+
+static void __exit da903x_exit(void)
+{
+ i2c_del_driver(&da903x_driver);
+}
+module_exit(da903x_exit);
+
+MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+ "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index 6be43172dc6..1a4d04664d6 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -112,7 +112,7 @@ static void egpio_handler(unsigned int irq, struct irq_desc *desc)
/* Run irq handler */
pr_debug("got IRQ %d\n", irqpin);
irq = ei->irq_start + irqpin;
- desc = &irq_desc[irq];
+ desc = irq_to_desc(irq);
desc->handle_irq(irq, desc);
}
}
@@ -289,7 +289,7 @@ static int __init egpio_probe(struct platform_device *pdev)
ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
if (!ei->base_addr)
goto fail;
- pr_debug("EGPIO phys=%08x virt=%p\n", res->start, ei->base_addr);
+ pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
goto fail;
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 9c9c126ed33..6c0d1bec4b7 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -20,7 +20,7 @@ static int mfd_add_device(struct device *parent, int id,
struct resource *mem_base,
int irq_base)
{
- struct resource res[cell->num_resources];
+ struct resource *res;
struct platform_device *pdev;
int ret = -ENOMEM;
int r;
@@ -29,14 +29,17 @@ static int mfd_add_device(struct device *parent, int id,
if (!pdev)
goto fail_alloc;
+ res = kzalloc(sizeof(*res) * cell->num_resources, GFP_KERNEL);
+ if (!res)
+ goto fail_device;
+
pdev->dev.parent = parent;
ret = platform_device_add_data(pdev,
cell->platform_data, cell->data_size);
if (ret)
- goto fail_device;
+ goto fail_res;
- 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;
@@ -64,11 +67,15 @@ static int mfd_add_device(struct device *parent, int id,
ret = platform_device_add(pdev);
if (ret)
- goto fail_device;
+ goto fail_res;
+
+ kfree(res);
return 0;
/* platform_device_del(pdev); */
+fail_res:
+ kfree(res);
fail_device:
platform_device_put(pdev);
fail_alloc:
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 7aebad4c06f..170f9d47c2f 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -623,8 +623,8 @@ unsigned long sm501_set_clock(struct device *dev,
sm501_sync_regs(sm);
- dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
- gate, clock, mode);
+ dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
+ gate, clock, mode);
sm501_mdelay(sm, 16);
mutex_unlock(&sm->clock_lock);
@@ -742,7 +742,7 @@ static int sm501_register_device(struct sm501_devdata *sm,
int ret;
for (ptr = 0; ptr < pdev->num_resources; ptr++) {
- printk("%s[%d] flags %08lx: %08llx..%08llx\n",
+ printk(KERN_DEBUG "%s[%d] flags %08lx: %08llx..%08llx\n",
pdev->name, ptr,
pdev->resource[ptr].flags,
(unsigned long long)pdev->resource[ptr].start,
@@ -1374,31 +1374,31 @@ static int sm501_init_dev(struct sm501_devdata *sm)
static int sm501_plat_probe(struct platform_device *dev)
{
struct sm501_devdata *sm;
- int err;
+ int ret;
sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
if (sm == NULL) {
dev_err(&dev->dev, "no memory for device data\n");
- err = -ENOMEM;
+ ret = -ENOMEM;
goto err1;
}
sm->dev = &dev->dev;
sm->pdev_id = dev->id;
- sm->irq = platform_get_irq(dev, 0);
- sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
- sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
sm->platdata = dev->dev.platform_data;
- if (sm->irq < 0) {
+ ret = platform_get_irq(dev, 0);
+ if (ret < 0) {
dev_err(&dev->dev, "failed to get irq resource\n");
- err = sm->irq;
goto err_res;
}
+ sm->irq = ret;
+ sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (sm->io_res == NULL || sm->mem_res == NULL) {
dev_err(&dev->dev, "failed to get IO resource\n");
- err = -ENOENT;
+ ret = -ENOENT;
goto err_res;
}
@@ -1407,7 +1407,7 @@ static int sm501_plat_probe(struct platform_device *dev)
if (sm->regs_claim == NULL) {
dev_err(&dev->dev, "cannot claim registers\n");
- err= -EBUSY;
+ ret = -EBUSY;
goto err_res;
}
@@ -1418,7 +1418,7 @@ static int sm501_plat_probe(struct platform_device *dev)
if (sm->regs == NULL) {
dev_err(&dev->dev, "cannot remap registers\n");
- err = -EIO;
+ ret = -EIO;
goto err_claim;
}
@@ -1430,7 +1430,7 @@ static int sm501_plat_probe(struct platform_device *dev)
err_res:
kfree(sm);
err1:
- return err;
+ return ret;
}
@@ -1625,8 +1625,7 @@ static int sm501_pci_probe(struct pci_dev *dev,
goto err3;
}
- sm->regs = ioremap(pci_resource_start(dev, 1),
- pci_resource_len(dev, 1));
+ sm->regs = pci_ioremap_bar(dev, 1);
if (sm->regs == NULL) {
dev_err(&dev->dev, "cannot remap registers\n");
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 49a0fffc02a..9f7024c0f8e 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -24,8 +24,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tmio.h>
@@ -56,6 +58,8 @@ struct t7l66xb {
spinlock_t lock;
struct resource rscr;
+ struct clk *clk48m;
+ struct clk *clk32k;
int irq;
int irq_base;
};
@@ -65,13 +69,11 @@ struct t7l66xb {
static int t7l66xb_mmc_enable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
- struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
unsigned long flags;
u8 dev_ctl;
- if (pdata->enable_clk32k)
- pdata->enable_clk32k(dev);
+ clk_enable(t7l66xb->clk32k);
spin_lock_irqsave(&t7l66xb->lock, flags);
@@ -87,7 +89,6 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
static int t7l66xb_mmc_disable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
- struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
unsigned long flags;
u8 dev_ctl;
@@ -100,8 +101,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
spin_unlock_irqrestore(&t7l66xb->lock, flags);
- if (pdata->disable_clk32k)
- pdata->disable_clk32k(dev);
+ clk_disable(t7l66xb->clk32k);
return 0;
}
@@ -258,18 +258,22 @@ static void t7l66xb_detach_irq(struct platform_device *dev)
#ifdef CONFIG_PM
static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
{
+ struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
if (pdata && pdata->suspend)
pdata->suspend(dev);
+ clk_disable(t7l66xb->clk48m);
return 0;
}
static int t7l66xb_resume(struct platform_device *dev)
{
+ struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
+ clk_enable(t7l66xb->clk48m);
if (pdata && pdata->resume)
pdata->resume(dev);
@@ -309,6 +313,19 @@ static int t7l66xb_probe(struct platform_device *dev)
t7l66xb->irq_base = pdata->irq_base;
+ t7l66xb->clk32k = clk_get(&dev->dev, "CLK_CK32K");
+ if (IS_ERR(t7l66xb->clk32k)) {
+ ret = PTR_ERR(t7l66xb->clk32k);
+ goto err_clk32k_get;
+ }
+
+ t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M");
+ if (IS_ERR(t7l66xb->clk48m)) {
+ ret = PTR_ERR(t7l66xb->clk48m);
+ clk_put(t7l66xb->clk32k);
+ goto err_clk48m_get;
+ }
+
rscr = &t7l66xb->rscr;
rscr->name = "t7l66xb-core";
rscr->start = iomem->start;
@@ -325,6 +342,8 @@ static int t7l66xb_probe(struct platform_device *dev)
goto err_ioremap;
}
+ clk_enable(t7l66xb->clk48m);
+
if (pdata && pdata->enable)
pdata->enable(dev);
@@ -359,9 +378,13 @@ static int t7l66xb_probe(struct platform_device *dev)
iounmap(t7l66xb->scr);
err_ioremap:
release_resource(&t7l66xb->rscr);
-err_noirq:
err_request_scr:
kfree(t7l66xb);
+ clk_put(t7l66xb->clk48m);
+err_clk48m_get:
+ clk_put(t7l66xb->clk32k);
+err_clk32k_get:
+err_noirq:
return ret;
}
@@ -372,7 +395,8 @@ static int t7l66xb_remove(struct platform_device *dev)
int ret;
ret = pdata->disable(dev);
-
+ clk_disable(t7l66xb->clk48m);
+ clk_put(t7l66xb->clk48m);
t7l66xb_detach_irq(dev);
iounmap(t7l66xb->scr);
release_resource(&t7l66xb->rscr);
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index a22b21ac6cf..43222c12fec 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tmio.h>
@@ -24,18 +25,22 @@ enum {
#ifdef CONFIG_PM
static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
{
- struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev);
+ struct clk *clk32k = platform_get_drvdata(dev);
+ struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
if (pdata && pdata->suspend)
pdata->suspend(dev);
+ clk_disable(clk32k);
return 0;
}
static int tc6387xb_resume(struct platform_device *dev)
{
- struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev);
+ struct clk *clk32k = platform_get_drvdata(dev);
+ struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
+ clk_enable(clk32k);
if (pdata && pdata->resume)
pdata->resume(dev);
@@ -51,10 +56,9 @@ static int tc6387xb_resume(struct platform_device *dev)
static int tc6387xb_mmc_enable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
- struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data;
+ struct clk *clk32k = platform_get_drvdata(dev);
- if (tc6387xb->enable_clk32k)
- tc6387xb->enable_clk32k(dev);
+ clk_enable(clk32k);
return 0;
}
@@ -62,10 +66,9 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
static int tc6387xb_mmc_disable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
- struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data;
+ struct clk *clk32k = platform_get_drvdata(dev);
- if (tc6387xb->disable_clk32k)
- tc6387xb->disable_clk32k(dev);
+ clk_disable(clk32k);
return 0;
}
@@ -102,14 +105,14 @@ static struct mfd_cell tc6387xb_cells[] = {
static int tc6387xb_probe(struct platform_device *dev)
{
- struct tc6387xb_platform_data *data = platform_get_drvdata(dev);
+ struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
struct resource *iomem;
+ struct clk *clk32k;
int irq, ret;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!iomem) {
- ret = -EINVAL;
- goto err_resource;
+ return -EINVAL;
}
ret = platform_get_irq(dev, 0);
@@ -118,8 +121,15 @@ static int tc6387xb_probe(struct platform_device *dev)
else
goto err_resource;
- if (data && data->enable)
- data->enable(dev);
+ clk32k = clk_get(&dev->dev, "CLK_CK32K");
+ if (IS_ERR(clk32k)) {
+ ret = PTR_ERR(clk32k);
+ goto err_resource;
+ }
+ platform_set_drvdata(dev, clk32k);
+
+ if (pdata && pdata->enable)
+ pdata->enable(dev);
printk(KERN_INFO "Toshiba tc6387xb initialised\n");
@@ -134,18 +144,19 @@ static int tc6387xb_probe(struct platform_device *dev)
if (!ret)
return 0;
+ clk_put(clk32k);
err_resource:
return ret;
}
static int tc6387xb_remove(struct platform_device *dev)
{
- struct tc6387xb_platform_data *data = platform_get_drvdata(dev);
-
- if (data && data->disable)
- data->disable(dev);
+ struct clk *clk32k = platform_get_drvdata(dev);
- /* FIXME - free the resources! */
+ mfd_remove_devices(&dev->dev);
+ clk_disable(clk32k);
+ clk_put(clk32k);
+ platform_set_drvdata(dev, NULL);
return 0;
}
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index e4c1c788b5f..f856e9463a9 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -113,6 +113,8 @@ struct tc6393xb {
enum {
TC6393XB_CELL_NAND,
TC6393XB_CELL_MMC,
+ TC6393XB_CELL_OHCI,
+ TC6393XB_CELL_FB,
};
/*--------------------------------------------------------------------------*/
@@ -170,6 +172,176 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
},
};
+const static struct resource tc6393xb_ohci_resources[] = {
+ {
+ .start = 0x3000,
+ .end = 0x31ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0300,
+ .end = 0x03ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x010000,
+ .end = 0x017fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x018000,
+ .end = 0x01ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_TC6393_OHCI,
+ .end = IRQ_TC6393_OHCI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource __devinitdata tc6393xb_fb_resources[] = {
+ {
+ .start = 0x5000,
+ .end = 0x51ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0500,
+ .end = 0x05ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x100000,
+ .end = 0x1fffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_TC6393_FB,
+ .end = IRQ_TC6393_FB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int tc6393xb_ohci_enable(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
+ unsigned long flags;
+ u16 ccr;
+ u8 fer;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
+ ccr |= SCR_CCR_USBCK;
+ tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
+
+ fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
+ fer |= SCR_FER_USBEN;
+ tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_ohci_disable(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
+ unsigned long flags;
+ u16 ccr;
+ u8 fer;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
+ fer &= ~SCR_FER_USBEN;
+ tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
+
+ ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
+ ccr &= ~SCR_CCR_USBCK;
+ tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_fb_enable(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
+ unsigned long flags;
+ u16 ccr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
+ ccr &= ~SCR_CCR_MCLK_MASK;
+ ccr |= SCR_CCR_MCLK_48;
+ tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_fb_disable(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
+ unsigned long flags;
+ u16 ccr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
+ ccr &= ~SCR_CCR_MCLK_MASK;
+ ccr |= SCR_CCR_MCLK_OFF;
+ tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
+{
+ struct platform_device *dev = to_platform_device(fb->dev.parent);
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ u8 fer;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ fer = ioread8(tc6393xb->scr + SCR_FER);
+ if (on)
+ fer |= SCR_FER_SLCDEN;
+ else
+ fer &= ~SCR_FER_SLCDEN;
+ iowrite8(fer, tc6393xb->scr + SCR_FER);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(tc6393xb_lcd_set_power);
+
+int tc6393xb_lcd_mode(struct platform_device *fb,
+ const struct fb_videomode *mode) {
+ struct platform_device *dev = to_platform_device(fb->dev.parent);
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0);
+ iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(tc6393xb_lcd_mode);
+
static struct mfd_cell __devinitdata tc6393xb_cells[] = {
[TC6393XB_CELL_NAND] = {
.name = "tmio-nand",
@@ -182,6 +354,24 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources,
},
+ [TC6393XB_CELL_OHCI] = {
+ .name = "tmio-ohci",
+ .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
+ .resources = tc6393xb_ohci_resources,
+ .enable = tc6393xb_ohci_enable,
+ .suspend = tc6393xb_ohci_disable,
+ .resume = tc6393xb_ohci_enable,
+ .disable = tc6393xb_ohci_disable,
+ },
+ [TC6393XB_CELL_FB] = {
+ .name = "tmio-fb",
+ .num_resources = ARRAY_SIZE(tc6393xb_fb_resources),
+ .resources = tc6393xb_fb_resources,
+ .enable = tc6393xb_fb_enable,
+ .suspend = tc6393xb_fb_disable,
+ .resume = tc6393xb_fb_enable,
+ .disable = tc6393xb_fb_disable,
+ },
};
/*--------------------------------------------------------------------------*/
@@ -369,41 +559,12 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
/*--------------------------------------------------------------------------*/
-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, *rscr;
int ret, temp;
- int i;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!iomem)
@@ -458,21 +619,16 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
if (ret)
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;
- }
-
- tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 |
- SCR_CCR_HCLK_48;
-
- ret = tc6393xb_hw_init(dev);
- if (ret)
- goto err_hw_init;
+ iowrite8(0, tc6393xb->scr + SCR_FER);
+ iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
+ iowrite16(SCR_CCR_UNK1 | SCR_CCR_HCLK_48,
+ 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);
printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
tmio_ioread8(tc6393xb->scr + SCR_REVID),
@@ -488,16 +644,33 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
tc6393xb_attach_irq(dev);
+ if (tcpd->setup) {
+ ret = tcpd->setup(dev);
+ if (ret)
+ goto err_setup;
+ }
+
tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_NAND].platform_data =
&tc6393xb_cells[TC6393XB_CELL_NAND];
tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
+
tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
&tc6393xb_cells[TC6393XB_CELL_MMC];
tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]);
+ tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data =
+ &tc6393xb_cells[TC6393XB_CELL_OHCI];
+ tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
+ sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
+
+ tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
+ tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
+ &tc6393xb_cells[TC6393XB_CELL_FB];
+ tc6393xb_cells[TC6393XB_CELL_FB].data_size =
+ sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);
ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
@@ -506,12 +679,15 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
if (!ret)
return 0;
+ if (tcpd->teardown)
+ tcpd->teardown(dev);
+
+err_setup:
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);
@@ -535,6 +711,10 @@ static int __devexit tc6393xb_remove(struct platform_device *dev)
int ret;
mfd_remove_devices(&dev->dev);
+
+ if (tcpd->teardown)
+ tcpd->teardown(dev);
+
tc6393xb_detach_irq(dev);
if (tc6393xb->gpio.base != -1) {
@@ -585,15 +765,37 @@ static int tc6393xb_resume(struct platform_device *dev)
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
int ret;
+ int i;
clk_enable(tc6393xb->clk);
ret = tcpd->resume(dev);
-
if (ret)
return ret;
- return tc6393xb_hw_init(dev);
+ if (!tcpd->resume_restore)
+ return 0;
+
+ 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;
}
#else
#define tc6393xb_suspend NULL
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
new file mode 100644
index 00000000000..dd843c4fbcc
--- /dev/null
+++ b/drivers/mfd/twl4030-core.c
@@ -0,0 +1,806 @@
+/*
+ * twl4030_core.c - driver for TWL4030/TPS659x0 PM and audio CODEC devices
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * Modifications to defer interrupt handling to a kernel thread:
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * Based on tlv320aic23.c:
+ * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
+ *
+ * Code cleanup and modifications to IRQ handler.
+ * by syed khasim <x0khasim@ti.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/init.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/twl4030.h>
+
+
+/*
+ * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
+ * Management and System Companion Device" chips originally designed for
+ * use in OMAP2 and OMAP 3 based systems. Its control interfaces use I2C,
+ * often at around 3 Mbit/sec, including for interrupt handling.
+ *
+ * This driver core provides genirq support for the interrupts emitted,
+ * by the various modules, and exports register access primitives.
+ *
+ * FIXME this driver currently requires use of the first interrupt line
+ * (and associated registers).
+ */
+
+#define DRIVER_NAME "twl4030"
+
+#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
+ defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
+#define twl_has_bci() true
+#else
+#define twl_has_bci() false
+#endif
+
+#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
+#define twl_has_keypad() true
+#else
+#define twl_has_keypad() false
+#endif
+
+#if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE)
+#define twl_has_gpio() true
+#else
+#define twl_has_gpio() false
+#endif
+
+#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
+#define twl_has_madc() true
+#else
+#define twl_has_madc() false
+#endif
+
+#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
+#define twl_has_rtc() true
+#else
+#define twl_has_rtc() false
+#endif
+
+#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
+#define twl_has_usb() true
+#else
+#define twl_has_usb() false
+#endif
+
+
+/* Triton Core internal information (BEGIN) */
+
+/* Last - for index max*/
+#define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG
+
+#define TWL4030_NUM_SLAVES 4
+
+
+/* Base Address defns for twl4030_map[] */
+
+/* subchip/slave 0 - USB ID */
+#define TWL4030_BASEADD_USB 0x0000
+
+/* subchip/slave 1 - AUD ID */
+#define TWL4030_BASEADD_AUDIO_VOICE 0x0000
+#define TWL4030_BASEADD_GPIO 0x0098
+#define TWL4030_BASEADD_INTBR 0x0085
+#define TWL4030_BASEADD_PIH 0x0080
+#define TWL4030_BASEADD_TEST 0x004C
+
+/* subchip/slave 2 - AUX ID */
+#define TWL4030_BASEADD_INTERRUPTS 0x00B9
+#define TWL4030_BASEADD_LED 0x00EE
+#define TWL4030_BASEADD_MADC 0x0000
+#define TWL4030_BASEADD_MAIN_CHARGE 0x0074
+#define TWL4030_BASEADD_PRECHARGE 0x00AA
+#define TWL4030_BASEADD_PWM0 0x00F8
+#define TWL4030_BASEADD_PWM1 0x00FB
+#define TWL4030_BASEADD_PWMA 0x00EF
+#define TWL4030_BASEADD_PWMB 0x00F1
+#define TWL4030_BASEADD_KEYPAD 0x00D2
+
+/* subchip/slave 3 - POWER ID */
+#define TWL4030_BASEADD_BACKUP 0x0014
+#define TWL4030_BASEADD_INT 0x002E
+#define TWL4030_BASEADD_PM_MASTER 0x0036
+#define TWL4030_BASEADD_PM_RECEIVER 0x005B
+#define TWL4030_BASEADD_RTC 0x001C
+#define TWL4030_BASEADD_SECURED_REG 0x0000
+
+/* Triton Core internal information (END) */
+
+
+/* Few power values */
+#define R_CFG_BOOT 0x05
+#define R_PROTECT_KEY 0x0E
+
+/* access control values for R_PROTECT_KEY */
+#define KEY_UNLOCK1 0xce
+#define KEY_UNLOCK2 0xec
+#define KEY_LOCK 0x00
+
+/* some fields in R_CFG_BOOT */
+#define HFCLK_FREQ_19p2_MHZ (1 << 0)
+#define HFCLK_FREQ_26_MHZ (2 << 0)
+#define HFCLK_FREQ_38p4_MHZ (3 << 0)
+#define HIGH_PERF_SQ (1 << 3)
+
+
+/*----------------------------------------------------------------------*/
+
+/* is driver active, bound to a chip? */
+static bool inuse;
+
+/* Structure for each TWL4030 Slave */
+struct twl4030_client {
+ struct i2c_client *client;
+ u8 address;
+
+ /* max numb of i2c_msg required is for read =2 */
+ struct i2c_msg xfer_msg[2];
+
+ /* To lock access to xfer_msg */
+ struct mutex xfer_lock;
+};
+
+static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES];
+
+
+/* mapping the module id to slave id and base address */
+struct twl4030mapping {
+ unsigned char sid; /* Slave ID */
+ unsigned char base; /* base address */
+};
+
+static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
+ /*
+ * NOTE: don't change this table without updating the
+ * <linux/i2c/twl4030.h> defines for TWL4030_MODULE_*
+ * so they continue to match the order in this table.
+ */
+
+ { 0, TWL4030_BASEADD_USB },
+
+ { 1, TWL4030_BASEADD_AUDIO_VOICE },
+ { 1, TWL4030_BASEADD_GPIO },
+ { 1, TWL4030_BASEADD_INTBR },
+ { 1, TWL4030_BASEADD_PIH },
+ { 1, TWL4030_BASEADD_TEST },
+
+ { 2, TWL4030_BASEADD_KEYPAD },
+ { 2, TWL4030_BASEADD_MADC },
+ { 2, TWL4030_BASEADD_INTERRUPTS },
+ { 2, TWL4030_BASEADD_LED },
+ { 2, TWL4030_BASEADD_MAIN_CHARGE },
+ { 2, TWL4030_BASEADD_PRECHARGE },
+ { 2, TWL4030_BASEADD_PWM0 },
+ { 2, TWL4030_BASEADD_PWM1 },
+ { 2, TWL4030_BASEADD_PWMA },
+ { 2, TWL4030_BASEADD_PWMB },
+
+ { 3, TWL4030_BASEADD_BACKUP },
+ { 3, TWL4030_BASEADD_INT },
+ { 3, TWL4030_BASEADD_PM_MASTER },
+ { 3, TWL4030_BASEADD_PM_RECEIVER },
+ { 3, TWL4030_BASEADD_RTC },
+ { 3, TWL4030_BASEADD_SECURED_REG },
+};
+
+/*----------------------------------------------------------------------*/
+
+/* Exported Functions */
+
+/**
+ * twl4030_i2c_write - Writes a n bit register in TWL4030
+ * @mod_no: module number
+ * @value: an array of num_bytes+1 containing data to write
+ * @reg: register address (just offset will do)
+ * @num_bytes: number of bytes to transfer
+ *
+ * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and
+ * valid data starts at Offset 1.
+ *
+ * Returns the result of operation - 0 is success
+ */
+int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
+{
+ int ret;
+ int sid;
+ struct twl4030_client *twl;
+ struct i2c_msg *msg;
+
+ if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
+ pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
+ return -EPERM;
+ }
+ sid = twl4030_map[mod_no].sid;
+ twl = &twl4030_modules[sid];
+
+ if (unlikely(!inuse)) {
+ pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
+ return -EPERM;
+ }
+ mutex_lock(&twl->xfer_lock);
+ /*
+ * [MSG1]: fill the register address data
+ * fill the data Tx buffer
+ */
+ msg = &twl->xfer_msg[0];
+ msg->addr = twl->address;
+ msg->len = num_bytes + 1;
+ msg->flags = 0;
+ msg->buf = value;
+ /* over write the first byte of buffer with the register address */
+ *value = twl4030_map[mod_no].base + reg;
+ ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
+ mutex_unlock(&twl->xfer_lock);
+
+ /* i2cTransfer returns num messages.translate it pls.. */
+ if (ret >= 0)
+ ret = 0;
+ return ret;
+}
+EXPORT_SYMBOL(twl4030_i2c_write);
+
+/**
+ * twl4030_i2c_read - Reads a n bit register in TWL4030
+ * @mod_no: module number
+ * @value: an array of num_bytes containing data to be read
+ * @reg: register address (just offset will do)
+ * @num_bytes: number of bytes to transfer
+ *
+ * Returns result of operation - num_bytes is success else failure.
+ */
+int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
+{
+ int ret;
+ u8 val;
+ int sid;
+ struct twl4030_client *twl;
+ struct i2c_msg *msg;
+
+ if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
+ pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
+ return -EPERM;
+ }
+ sid = twl4030_map[mod_no].sid;
+ twl = &twl4030_modules[sid];
+
+ if (unlikely(!inuse)) {
+ pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
+ return -EPERM;
+ }
+ mutex_lock(&twl->xfer_lock);
+ /* [MSG1] fill the register address data */
+ msg = &twl->xfer_msg[0];
+ msg->addr = twl->address;
+ msg->len = 1;
+ msg->flags = 0; /* Read the register value */
+ val = twl4030_map[mod_no].base + reg;
+ msg->buf = &val;
+ /* [MSG2] fill the data rx buffer */
+ msg = &twl->xfer_msg[1];
+ msg->addr = twl->address;
+ msg->flags = I2C_M_RD; /* Read the register value */
+ msg->len = num_bytes; /* only n bytes */
+ msg->buf = value;
+ ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2);
+ mutex_unlock(&twl->xfer_lock);
+
+ /* i2cTransfer returns num messages.translate it pls.. */
+ if (ret >= 0)
+ ret = 0;
+ return ret;
+}
+EXPORT_SYMBOL(twl4030_i2c_read);
+
+/**
+ * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030
+ * @mod_no: module number
+ * @value: the value to be written 8 bit
+ * @reg: register address (just offset will do)
+ *
+ * Returns result of operation - 0 is success
+ */
+int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
+{
+
+ /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
+ u8 temp_buffer[2] = { 0 };
+ /* offset 1 contains the data */
+ temp_buffer[1] = value;
+ return twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
+}
+EXPORT_SYMBOL(twl4030_i2c_write_u8);
+
+/**
+ * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030
+ * @mod_no: module number
+ * @value: the value read 8 bit
+ * @reg: register address (just offset will do)
+ *
+ * Returns result of operation - 0 is success
+ */
+int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
+{
+ return twl4030_i2c_read(mod_no, value, reg, 1);
+}
+EXPORT_SYMBOL(twl4030_i2c_read_u8);
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * NOTE: We know the first 8 IRQs after pdata->base_irq are
+ * for the PIH, and the next are for the PWR_INT SIH, since
+ * that's how twl_init_irq() sets things up.
+ */
+
+static int add_children(struct twl4030_platform_data *pdata)
+{
+ struct platform_device *pdev = NULL;
+ struct twl4030_client *twl = NULL;
+ int status = 0;
+
+ if (twl_has_bci() && pdata->bci) {
+ twl = &twl4030_modules[3];
+
+ pdev = platform_device_alloc("twl4030_bci", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ status = platform_device_add_data(pdev, pdata->bci,
+ sizeof(*pdata->bci));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add bci data, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 8 + 1,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create bci dev, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (twl_has_gpio() && pdata->gpio) {
+ twl = &twl4030_modules[1];
+
+ pdev = platform_device_alloc("twl4030_gpio", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+
+ /* more driver model init */
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ /* device_init_wakeup(&pdev->dev, 1); */
+
+ status = platform_device_add_data(pdev, pdata->gpio,
+ sizeof(*pdata->gpio));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add gpio data, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ /* GPIO module IRQ */
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 0,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create gpio dev, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (twl_has_keypad() && pdata->keypad) {
+ pdev = platform_device_alloc("twl4030_keypad", -1);
+ if (pdev) {
+ twl = &twl4030_modules[2];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->keypad,
+ sizeof(*pdata->keypad));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add keypad data, %d\n",
+ status);
+ platform_device_put(pdev);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create keypad dev, %d\n",
+ status);
+ goto err;
+ }
+ } else {
+ pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+ }
+
+ if (twl_has_madc() && pdata->madc) {
+ pdev = platform_device_alloc("twl4030_madc", -1);
+ if (pdev) {
+ twl = &twl4030_modules[2];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->madc,
+ sizeof(*pdata->madc));
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't add madc data, %d\n",
+ status);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create madc dev, %d\n",
+ status);
+ goto err;
+ }
+ } else {
+ pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+ }
+
+ if (twl_has_rtc()) {
+ twl = &twl4030_modules[3];
+
+ pdev = platform_device_alloc("twl4030_rtc", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ } else {
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ }
+
+ /*
+ * REVISIT platform_data here currently might use of
+ * "msecure" line ... but for now we just expect board
+ * setup to tell the chip "we are secure" at all times.
+ * Eventually, Linux might become more aware of such
+ * HW security concerns, and "least privilege".
+ */
+
+ /* RTC module IRQ */
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 8 + 3,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create rtc dev, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (twl_has_usb() && pdata->usb) {
+ twl = &twl4030_modules[0];
+
+ pdev = platform_device_alloc("twl4030_usb", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->usb,
+ sizeof(*pdata->usb));
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't add usb data, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 8 + 2,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create usb dev, %d\n",
+ status);
+ }
+ }
+
+err:
+ if (status)
+ pr_err("failed to add twl4030's children (status %d)\n", status);
+ return status;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * These three functions initialize the on-chip clock framework,
+ * letting it generate the right frequencies for USB, MADC, and
+ * other purposes.
+ */
+static inline int __init protect_pm_master(void)
+{
+ int e = 0;
+
+ e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
+ R_PROTECT_KEY);
+ return e;
+}
+
+static inline int __init unprotect_pm_master(void)
+{
+ int e = 0;
+
+ e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
+ R_PROTECT_KEY);
+ e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
+ R_PROTECT_KEY);
+ return e;
+}
+
+static void __init clocks_init(void)
+{
+ int e = 0;
+ struct clk *osc;
+ u32 rate;
+ u8 ctrl = HFCLK_FREQ_26_MHZ;
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ if (cpu_is_omap2430())
+ osc = clk_get(NULL, "osc_ck");
+ else
+ osc = clk_get(NULL, "osc_sys_ck");
+#else
+ /* REVISIT for non-OMAP systems, pass the clock rate from
+ * board init code, using platform_data.
+ */
+ osc = ERR_PTR(-EIO);
+#endif
+ if (IS_ERR(osc)) {
+ printk(KERN_WARNING "Skipping twl4030 internal clock init and "
+ "using bootloader value (unknown osc rate)\n");
+ return;
+ }
+
+ rate = clk_get_rate(osc);
+ clk_put(osc);
+
+ switch (rate) {
+ case 19200000:
+ ctrl = HFCLK_FREQ_19p2_MHZ;
+ break;
+ case 26000000:
+ ctrl = HFCLK_FREQ_26_MHZ;
+ break;
+ case 38400000:
+ ctrl = HFCLK_FREQ_38p4_MHZ;
+ break;
+ }
+
+ ctrl |= HIGH_PERF_SQ;
+ e |= unprotect_pm_master();
+ /* effect->MADC+USB ck en */
+ e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
+ e |= protect_pm_master();
+
+ if (e < 0)
+ pr_err("%s: clock init err [%d]\n", DRIVER_NAME, e);
+}
+
+/*----------------------------------------------------------------------*/
+
+int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
+int twl_exit_irq(void);
+
+static int twl4030_remove(struct i2c_client *client)
+{
+ unsigned i;
+ int status;
+
+ status = twl_exit_irq();
+ if (status < 0)
+ return status;
+
+ for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
+ struct twl4030_client *twl = &twl4030_modules[i];
+
+ if (twl->client && twl->client != client)
+ i2c_unregister_device(twl->client);
+ twl4030_modules[i].client = NULL;
+ }
+ inuse = false;
+ return 0;
+}
+
+/* NOTE: this driver only handles a single twl4030/tps659x0 chip */
+static int
+twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int status;
+ unsigned i;
+ struct twl4030_platform_data *pdata = client->dev.platform_data;
+
+ if (!pdata) {
+ dev_dbg(&client->dev, "no platform data?\n");
+ return -EINVAL;
+ }
+
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
+ dev_dbg(&client->dev, "can't talk I2C?\n");
+ return -EIO;
+ }
+
+ if (inuse) {
+ dev_dbg(&client->dev, "driver is already in use\n");
+ return -EBUSY;
+ }
+
+ for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
+ struct twl4030_client *twl = &twl4030_modules[i];
+
+ twl->address = client->addr + i;
+ if (i == 0)
+ twl->client = client;
+ else {
+ twl->client = i2c_new_dummy(client->adapter,
+ twl->address);
+ if (!twl->client) {
+ dev_err(&twl->client->dev,
+ "can't attach client %d\n", i);
+ status = -ENOMEM;
+ goto fail;
+ }
+ strlcpy(twl->client->name, id->name,
+ sizeof(twl->client->name));
+ }
+ mutex_init(&twl->xfer_lock);
+ }
+ inuse = true;
+
+ /* setup clock framework */
+ clocks_init();
+
+ /* Maybe init the T2 Interrupt subsystem */
+ if (client->irq
+ && pdata->irq_base
+ && pdata->irq_end > pdata->irq_base) {
+ status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end);
+ if (status < 0)
+ goto fail;
+ }
+
+ status = add_children(pdata);
+fail:
+ if (status < 0)
+ twl4030_remove(client);
+ return status;
+}
+
+static const struct i2c_device_id twl4030_ids[] = {
+ { "twl4030", 0 }, /* "Triton 2" */
+ { "tps65950", 0 }, /* catalog version of twl4030 */
+ { "tps65930", 0 }, /* fewer LDOs and DACs; no charger */
+ { "tps65920", 0 }, /* fewer LDOs; no codec or charger */
+ { "twl5030", 0 }, /* T2 updated */
+ { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(i2c, twl4030_ids);
+
+/* One Client Driver , 4 Clients */
+static struct i2c_driver twl4030_driver = {
+ .driver.name = DRIVER_NAME,
+ .id_table = twl4030_ids,
+ .probe = twl4030_probe,
+ .remove = twl4030_remove,
+};
+
+static int __init twl4030_init(void)
+{
+ return i2c_add_driver(&twl4030_driver);
+}
+subsys_initcall(twl4030_init);
+
+static void __exit twl4030_exit(void)
+{
+ i2c_del_driver(&twl4030_driver);
+}
+module_exit(twl4030_exit);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("I2C Core interface for TWL4030");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
new file mode 100644
index 00000000000..fae868a8d49
--- /dev/null
+++ b/drivers/mfd/twl4030-irq.c
@@ -0,0 +1,743 @@
+/*
+ * twl4030-irq.c - TWL4030/TPS659x0 irq support
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * Modifications to defer interrupt handling to a kernel thread:
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * Based on tlv320aic23.c:
+ * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
+ *
+ * Code cleanup and modifications to IRQ handler.
+ * by syed khasim <x0khasim@ti.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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+
+#include <linux/i2c/twl4030.h>
+
+
+/*
+ * TWL4030 IRQ handling has two stages in hardware, and thus in software.
+ * The Primary Interrupt Handler (PIH) stage exposes status bits saying
+ * which Secondary Interrupt Handler (SIH) stage is raising an interrupt.
+ * SIH modules are more traditional IRQ components, which support per-IRQ
+ * enable/disable and trigger controls; they do most of the work.
+ *
+ * These chips are designed to support IRQ handling from two different
+ * I2C masters. Each has a dedicated IRQ line, and dedicated IRQ status
+ * and mask registers in the PIH and SIH modules.
+ *
+ * We set up IRQs starting at a platform-specified base, always starting
+ * with PIH and the SIH for PWR_INT and then usually adding GPIO:
+ * base + 0 .. base + 7 PIH
+ * base + 8 .. base + 15 SIH for PWR_INT
+ * base + 16 .. base + 33 SIH for GPIO
+ */
+
+/* PIH register offsets */
+#define REG_PIH_ISR_P1 0x01
+#define REG_PIH_ISR_P2 0x02
+#define REG_PIH_SIR 0x03 /* for testing */
+
+
+/* Linux could (eventually) use either IRQ line */
+static int irq_line;
+
+struct sih {
+ char name[8];
+ u8 module; /* module id */
+ u8 control_offset; /* for SIH_CTRL */
+ bool set_cor;
+
+ u8 bits; /* valid in isr/imr */
+ u8 bytes_ixr; /* bytelen of ISR/IMR/SIR */
+
+ u8 edr_offset;
+ u8 bytes_edr; /* bytelen of EDR */
+
+ /* SIR ignored -- set interrupt, for testing only */
+ struct irq_data {
+ u8 isr_offset;
+ u8 imr_offset;
+ } mask[2];
+ /* + 2 bytes padding */
+};
+
+#define SIH_INITIALIZER(modname, nbits) \
+ .module = TWL4030_MODULE_ ## modname, \
+ .control_offset = TWL4030_ ## modname ## _SIH_CTRL, \
+ .bits = nbits, \
+ .bytes_ixr = DIV_ROUND_UP(nbits, 8), \
+ .edr_offset = TWL4030_ ## modname ## _EDR, \
+ .bytes_edr = DIV_ROUND_UP((2*(nbits)), 8), \
+ .mask = { { \
+ .isr_offset = TWL4030_ ## modname ## _ISR1, \
+ .imr_offset = TWL4030_ ## modname ## _IMR1, \
+ }, \
+ { \
+ .isr_offset = TWL4030_ ## modname ## _ISR2, \
+ .imr_offset = TWL4030_ ## modname ## _IMR2, \
+ }, },
+
+/* register naming policies are inconsistent ... */
+#define TWL4030_INT_PWR_EDR TWL4030_INT_PWR_EDR1
+#define TWL4030_MODULE_KEYPAD_KEYP TWL4030_MODULE_KEYPAD
+#define TWL4030_MODULE_INT_PWR TWL4030_MODULE_INT
+
+
+/* Order in this table matches order in PIH_ISR. That is,
+ * BIT(n) in PIH_ISR is sih_modules[n].
+ */
+static const struct sih sih_modules[6] = {
+ [0] = {
+ .name = "gpio",
+ .module = TWL4030_MODULE_GPIO,
+ .control_offset = REG_GPIO_SIH_CTRL,
+ .set_cor = true,
+ .bits = TWL4030_GPIO_MAX,
+ .bytes_ixr = 3,
+ /* Note: *all* of these IRQs default to no-trigger */
+ .edr_offset = REG_GPIO_EDR1,
+ .bytes_edr = 5,
+ .mask = { {
+ .isr_offset = REG_GPIO_ISR1A,
+ .imr_offset = REG_GPIO_IMR1A,
+ }, {
+ .isr_offset = REG_GPIO_ISR1B,
+ .imr_offset = REG_GPIO_IMR1B,
+ }, },
+ },
+ [1] = {
+ .name = "keypad",
+ .set_cor = true,
+ SIH_INITIALIZER(KEYPAD_KEYP, 4)
+ },
+ [2] = {
+ .name = "bci",
+ .module = TWL4030_MODULE_INTERRUPTS,
+ .control_offset = TWL4030_INTERRUPTS_BCISIHCTRL,
+ .bits = 12,
+ .bytes_ixr = 2,
+ .edr_offset = TWL4030_INTERRUPTS_BCIEDR1,
+ /* Note: most of these IRQs default to no-trigger */
+ .bytes_edr = 3,
+ .mask = { {
+ .isr_offset = TWL4030_INTERRUPTS_BCIISR1A,
+ .imr_offset = TWL4030_INTERRUPTS_BCIIMR1A,
+ }, {
+ .isr_offset = TWL4030_INTERRUPTS_BCIISR1B,
+ .imr_offset = TWL4030_INTERRUPTS_BCIIMR1B,
+ }, },
+ },
+ [3] = {
+ .name = "madc",
+ SIH_INITIALIZER(MADC, 4)
+ },
+ [4] = {
+ /* USB doesn't use the same SIH organization */
+ .name = "usb",
+ },
+ [5] = {
+ .name = "power",
+ .set_cor = true,
+ SIH_INITIALIZER(INT_PWR, 8)
+ },
+ /* there are no SIH modules #6 or #7 ... */
+};
+
+#undef TWL4030_MODULE_KEYPAD_KEYP
+#undef TWL4030_MODULE_INT_PWR
+#undef TWL4030_INT_PWR_EDR
+
+/*----------------------------------------------------------------------*/
+
+static unsigned twl4030_irq_base;
+
+static struct completion irq_event;
+
+/*
+ * This thread processes interrupts reported by the Primary Interrupt Handler.
+ */
+static int twl4030_irq_thread(void *data)
+{
+ long irq = (long)data;
+ irq_desc_t *desc = irq_desc + irq;
+ static unsigned i2c_errors;
+ const static unsigned max_i2c_errors = 100;
+
+ current->flags |= PF_NOFREEZE;
+
+ while (!kthread_should_stop()) {
+ int ret;
+ int module_irq;
+ u8 pih_isr;
+
+ /* Wait for IRQ, then read PIH irq status (also blocking) */
+ wait_for_completion_interruptible(&irq_event);
+
+ ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
+ REG_PIH_ISR_P1);
+ if (ret) {
+ pr_warning("twl4030: I2C error %d reading PIH ISR\n",
+ ret);
+ if (++i2c_errors >= max_i2c_errors) {
+ printk(KERN_ERR "Maximum I2C error count"
+ " exceeded. Terminating %s.\n",
+ __func__);
+ break;
+ }
+ complete(&irq_event);
+ continue;
+ }
+
+ /* these handlers deal with the relevant SIH irq status */
+ local_irq_disable();
+ for (module_irq = twl4030_irq_base;
+ pih_isr;
+ pih_isr >>= 1, module_irq++) {
+ if (pih_isr & 0x1) {
+ irq_desc_t *d = irq_desc + module_irq;
+
+ /* These can't be masked ... always warn
+ * if we get any surprises.
+ */
+ if (d->status & IRQ_DISABLED)
+ note_interrupt(module_irq, d,
+ IRQ_NONE);
+ else
+ d->handle_irq(module_irq, d);
+ }
+ }
+ local_irq_enable();
+
+ desc->chip->unmask(irq);
+ }
+
+ return 0;
+}
+
+/*
+ * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt.
+ * This is a chained interrupt, so there is no desc->action method for it.
+ * Now we need to query the interrupt controller in the twl4030 to determine
+ * which module is generating the interrupt request. However, we can't do i2c
+ * transactions in interrupt context, so we must defer that work to a kernel
+ * thread. All we do here is acknowledge and mask the interrupt and wakeup
+ * the kernel thread.
+ */
+static void handle_twl4030_pih(unsigned int irq, irq_desc_t *desc)
+{
+ /* Acknowledge, clear *AND* mask the interrupt... */
+ desc->chip->ack(irq);
+ complete(&irq_event);
+}
+
+static struct task_struct *start_twl4030_irq_thread(long irq)
+{
+ struct task_struct *thread;
+
+ init_completion(&irq_event);
+ thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq");
+ if (!thread)
+ pr_err("twl4030: could not create irq %ld thread!\n", irq);
+
+ return thread;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * twl4030_init_sih_modules() ... start from a known state where no
+ * IRQs will be coming in, and where we can quickly enable them then
+ * handle them as they arrive. Mask all IRQs: maybe init SIH_CTRL.
+ *
+ * NOTE: we don't touch EDR registers here; they stay with hardware
+ * defaults or whatever the last value was. Note that when both EDR
+ * bits for an IRQ are clear, that's as if its IMR bit is set...
+ */
+static int twl4030_init_sih_modules(unsigned line)
+{
+ const struct sih *sih;
+ u8 buf[4];
+ int i;
+ int status;
+
+ /* line 0 == int1_n signal; line 1 == int2_n signal */
+ if (line > 1)
+ return -EINVAL;
+
+ irq_line = line;
+
+ /* disable all interrupts on our line */
+ memset(buf, 0xff, sizeof buf);
+ sih = sih_modules;
+ for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) {
+
+ /* skip USB -- it's funky */
+ if (!sih->bytes_ixr)
+ continue;
+
+ status = twl4030_i2c_write(sih->module, buf,
+ sih->mask[line].imr_offset, sih->bytes_ixr);
+ if (status < 0)
+ pr_err("twl4030: err %d initializing %s %s\n",
+ status, sih->name, "IMR");
+
+ /* Maybe disable "exclusive" mode; buffer second pending irq;
+ * set Clear-On-Read (COR) bit.
+ *
+ * NOTE that sometimes COR polarity is documented as being
+ * inverted: for MADC and BCI, COR=1 means "clear on write".
+ * And for PWR_INT it's not documented...
+ */
+ if (sih->set_cor) {
+ status = twl4030_i2c_write_u8(sih->module,
+ TWL4030_SIH_CTRL_COR_MASK,
+ sih->control_offset);
+ if (status < 0)
+ pr_err("twl4030: err %d initializing %s %s\n",
+ status, sih->name, "SIH_CTRL");
+ }
+ }
+
+ sih = sih_modules;
+ for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) {
+ u8 rxbuf[4];
+ int j;
+
+ /* skip USB */
+ if (!sih->bytes_ixr)
+ continue;
+
+ /* Clear pending interrupt status. Either the read was
+ * enough, or we need to write those bits. Repeat, in
+ * case an IRQ is pending (PENDDIS=0) ... that's not
+ * uncommon with PWR_INT.PWRON.
+ */
+ for (j = 0; j < 2; j++) {
+ status = twl4030_i2c_read(sih->module, rxbuf,
+ sih->mask[line].isr_offset, sih->bytes_ixr);
+ if (status < 0)
+ pr_err("twl4030: err %d initializing %s %s\n",
+ status, sih->name, "ISR");
+
+ if (!sih->set_cor)
+ status = twl4030_i2c_write(sih->module, buf,
+ sih->mask[line].isr_offset,
+ sih->bytes_ixr);
+ /* else COR=1 means read sufficed.
+ * (for most SIH modules...)
+ */
+ }
+ }
+
+ return 0;
+}
+
+static inline void activate_irq(int irq)
+{
+#ifdef CONFIG_ARM
+ /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+ * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
+ */
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ /* same effect on other architectures */
+ set_irq_noprobe(irq);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+
+static DEFINE_SPINLOCK(sih_agent_lock);
+
+static struct workqueue_struct *wq;
+
+struct sih_agent {
+ int irq_base;
+ const struct sih *sih;
+
+ u32 imr;
+ bool imr_change_pending;
+ struct work_struct mask_work;
+
+ u32 edge_change;
+ struct work_struct edge_work;
+};
+
+static void twl4030_sih_do_mask(struct work_struct *work)
+{
+ struct sih_agent *agent;
+ const struct sih *sih;
+ union {
+ u8 bytes[4];
+ u32 word;
+ } imr;
+ int status;
+
+ agent = container_of(work, struct sih_agent, mask_work);
+
+ /* see what work we have */
+ spin_lock_irq(&sih_agent_lock);
+ if (agent->imr_change_pending) {
+ sih = agent->sih;
+ /* byte[0] gets overwritten as we write ... */
+ imr.word = cpu_to_le32(agent->imr << 8);
+ agent->imr_change_pending = false;
+ } else
+ sih = NULL;
+ spin_unlock_irq(&sih_agent_lock);
+ if (!sih)
+ return;
+
+ /* write the whole mask ... simpler than subsetting it */
+ status = twl4030_i2c_write(sih->module, imr.bytes,
+ sih->mask[irq_line].imr_offset, sih->bytes_ixr);
+ if (status)
+ pr_err("twl4030: %s, %s --> %d\n", __func__,
+ "write", status);
+}
+
+static void twl4030_sih_do_edge(struct work_struct *work)
+{
+ struct sih_agent *agent;
+ const struct sih *sih;
+ u8 bytes[6];
+ u32 edge_change;
+ int status;
+
+ agent = container_of(work, struct sih_agent, edge_work);
+
+ /* see what work we have */
+ spin_lock_irq(&sih_agent_lock);
+ edge_change = agent->edge_change;
+ agent->edge_change = 0;;
+ sih = edge_change ? agent->sih : NULL;
+ spin_unlock_irq(&sih_agent_lock);
+ if (!sih)
+ return;
+
+ /* Read, reserving first byte for write scratch. Yes, this
+ * could be cached for some speedup ... but be careful about
+ * any processor on the other IRQ line, EDR registers are
+ * shared.
+ */
+ status = twl4030_i2c_read(sih->module, bytes + 1,
+ sih->edr_offset, sih->bytes_edr);
+ if (status) {
+ pr_err("twl4030: %s, %s --> %d\n", __func__,
+ "read", status);
+ return;
+ }
+
+ /* Modify only the bits we know must change */
+ while (edge_change) {
+ int i = fls(edge_change) - 1;
+ struct irq_desc *d = irq_desc + i + agent->irq_base;
+ int byte = 1 + (i >> 2);
+ int off = (i & 0x3) * 2;
+
+ bytes[byte] &= ~(0x03 << off);
+
+ spin_lock_irq(&d->lock);
+ if (d->status & IRQ_TYPE_EDGE_RISING)
+ bytes[byte] |= BIT(off + 1);
+ if (d->status & IRQ_TYPE_EDGE_FALLING)
+ bytes[byte] |= BIT(off + 0);
+ spin_unlock_irq(&d->lock);
+
+ edge_change &= ~BIT(i);
+ }
+
+ /* Write */
+ status = twl4030_i2c_write(sih->module, bytes,
+ sih->edr_offset, sih->bytes_edr);
+ if (status)
+ pr_err("twl4030: %s, %s --> %d\n", __func__,
+ "write", status);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * All irq_chip methods get issued from code holding irq_desc[irq].lock,
+ * which can't perform the underlying I2C operations (because they sleep).
+ * So we must hand them off to a thread (workqueue) and cope with asynch
+ * completion, potentially including some re-ordering, of these requests.
+ */
+
+static void twl4030_sih_mask(unsigned irq)
+{
+ struct sih_agent *sih = get_irq_chip_data(irq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sih_agent_lock, flags);
+ sih->imr |= BIT(irq - sih->irq_base);
+ sih->imr_change_pending = true;
+ queue_work(wq, &sih->mask_work);
+ spin_unlock_irqrestore(&sih_agent_lock, flags);
+}
+
+static void twl4030_sih_unmask(unsigned irq)
+{
+ struct sih_agent *sih = get_irq_chip_data(irq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sih_agent_lock, flags);
+ sih->imr &= ~BIT(irq - sih->irq_base);
+ sih->imr_change_pending = true;
+ queue_work(wq, &sih->mask_work);
+ spin_unlock_irqrestore(&sih_agent_lock, flags);
+}
+
+static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
+{
+ struct sih_agent *sih = get_irq_chip_data(irq);
+ struct irq_desc *desc = irq_desc + irq;
+ unsigned long flags;
+
+ if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ return -EINVAL;
+
+ spin_lock_irqsave(&sih_agent_lock, flags);
+ if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
+ desc->status &= ~IRQ_TYPE_SENSE_MASK;
+ desc->status |= trigger;
+ sih->edge_change |= BIT(irq - sih->irq_base);
+ queue_work(wq, &sih->edge_work);
+ }
+ spin_unlock_irqrestore(&sih_agent_lock, flags);
+ return 0;
+}
+
+static struct irq_chip twl4030_sih_irq_chip = {
+ .name = "twl4030",
+ .mask = twl4030_sih_mask,
+ .unmask = twl4030_sih_unmask,
+ .set_type = twl4030_sih_set_type,
+};
+
+/*----------------------------------------------------------------------*/
+
+static inline int sih_read_isr(const struct sih *sih)
+{
+ int status;
+ union {
+ u8 bytes[4];
+ u32 word;
+ } isr;
+
+ /* FIXME need retry-on-error ... */
+
+ isr.word = 0;
+ status = twl4030_i2c_read(sih->module, isr.bytes,
+ sih->mask[irq_line].isr_offset, sih->bytes_ixr);
+
+ return (status < 0) ? status : le32_to_cpu(isr.word);
+}
+
+/*
+ * Generic handler for SIH interrupts ... we "know" this is called
+ * in task context, with IRQs enabled.
+ */
+static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
+{
+ struct sih_agent *agent = get_irq_data(irq);
+ const struct sih *sih = agent->sih;
+ int isr;
+
+ /* reading ISR acks the IRQs, using clear-on-read mode */
+ local_irq_enable();
+ isr = sih_read_isr(sih);
+ local_irq_disable();
+
+ if (isr < 0) {
+ pr_err("twl4030: %s SIH, read ISR error %d\n",
+ sih->name, isr);
+ /* REVISIT: recover; eventually mask it all, etc */
+ return;
+ }
+
+ while (isr) {
+ irq = fls(isr);
+ irq--;
+ isr &= ~BIT(irq);
+
+ if (irq < sih->bits)
+ generic_handle_irq(agent->irq_base + irq);
+ else
+ pr_err("twl4030: %s SIH, invalid ISR bit %d\n",
+ sih->name, irq);
+ }
+}
+
+static unsigned twl4030_irq_next;
+
+/* returns the first IRQ used by this SIH bank,
+ * or negative errno
+ */
+int twl4030_sih_setup(int module)
+{
+ int sih_mod;
+ const struct sih *sih = NULL;
+ struct sih_agent *agent;
+ int i, irq;
+ int status = -EINVAL;
+ unsigned irq_base = twl4030_irq_next;
+
+ /* only support modules with standard clear-on-read for now */
+ for (sih_mod = 0, sih = sih_modules;
+ sih_mod < ARRAY_SIZE(sih_modules);
+ sih_mod++, sih++) {
+ if (sih->module == module && sih->set_cor) {
+ if (!WARN((irq_base + sih->bits) > NR_IRQS,
+ "irq %d for %s too big\n",
+ irq_base + sih->bits,
+ sih->name))
+ status = 0;
+ break;
+ }
+ }
+ if (status < 0)
+ return status;
+
+ agent = kzalloc(sizeof *agent, GFP_KERNEL);
+ if (!agent)
+ return -ENOMEM;
+
+ status = 0;
+
+ agent->irq_base = irq_base;
+ agent->sih = sih;
+ agent->imr = ~0;
+ INIT_WORK(&agent->mask_work, twl4030_sih_do_mask);
+ INIT_WORK(&agent->edge_work, twl4030_sih_do_edge);
+
+ for (i = 0; i < sih->bits; i++) {
+ irq = irq_base + i;
+
+ set_irq_chip_and_handler(irq, &twl4030_sih_irq_chip,
+ handle_edge_irq);
+ set_irq_chip_data(irq, agent);
+ activate_irq(irq);
+ }
+
+ status = irq_base;
+ twl4030_irq_next += i;
+
+ /* replace generic PIH handler (handle_simple_irq) */
+ irq = sih_mod + twl4030_irq_base;
+ set_irq_data(irq, agent);
+ set_irq_chained_handler(irq, handle_twl4030_sih);
+
+ pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
+ irq, irq_base, twl4030_irq_next - 1);
+
+ return status;
+}
+
+/* FIXME need a call to reverse twl4030_sih_setup() ... */
+
+
+/*----------------------------------------------------------------------*/
+
+/* FIXME pass in which interrupt line we'll use ... */
+#define twl_irq_line 0
+
+int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
+{
+ static struct irq_chip twl4030_irq_chip;
+
+ int status;
+ int i;
+ struct task_struct *task;
+
+ /*
+ * Mask and clear all TWL4030 interrupts since initially we do
+ * not have any TWL4030 module interrupt handlers present
+ */
+ status = twl4030_init_sih_modules(twl_irq_line);
+ if (status < 0)
+ return status;
+
+ wq = create_singlethread_workqueue("twl4030-irqchip");
+ if (!wq) {
+ pr_err("twl4030: workqueue FAIL\n");
+ return -ESRCH;
+ }
+
+ twl4030_irq_base = irq_base;
+
+ /* install an irq handler for each of the SIH modules;
+ * clone dummy irq_chip since PIH can't *do* anything
+ */
+ twl4030_irq_chip = dummy_irq_chip;
+ twl4030_irq_chip.name = "twl4030";
+
+ twl4030_sih_irq_chip.ack = dummy_irq_chip.ack;
+
+ for (i = irq_base; i < irq_end; i++) {
+ set_irq_chip_and_handler(i, &twl4030_irq_chip,
+ handle_simple_irq);
+ activate_irq(i);
+ }
+ twl4030_irq_next = i;
+ pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
+ irq_num, irq_base, twl4030_irq_next - 1);
+
+ /* ... and the PWR_INT module ... */
+ status = twl4030_sih_setup(TWL4030_MODULE_INT);
+ if (status < 0) {
+ pr_err("twl4030: sih_setup PWR INT --> %d\n", status);
+ goto fail;
+ }
+
+ /* install an irq handler to demultiplex the TWL4030 interrupt */
+ task = start_twl4030_irq_thread(irq_num);
+ if (!task) {
+ pr_err("twl4030: irq thread FAIL\n");
+ status = -ESRCH;
+ goto fail;
+ }
+
+ set_irq_data(irq_num, task);
+ set_irq_chained_handler(irq_num, handle_twl4030_pih);
+
+ return status;
+
+fail:
+ for (i = irq_base; i < irq_end; i++)
+ set_irq_chip_and_handler(i, NULL, NULL);
+ destroy_workqueue(wq);
+ wq = NULL;
+ return status;
+}
+
+int twl_exit_irq(void)
+{
+ /* FIXME undo twl_init_irq() */
+ if (twl4030_irq_base) {
+ pr_err("twl4030: can't yet clean up IRQs?\n");
+ return -ENOSYS;
+ }
+ return 0;
+}
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 25a7a5d08bc..0d47fb9e4b3 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -183,6 +183,9 @@ static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
(wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
| src[i - reg];
+ /* Don't store volatile bits */
+ wm8350->reg_cache[i] &= ~wm8350_reg_io_map[i].vol;
+
src[i - reg] = cpu_to_be16(src[i - reg]);
}
@@ -1120,6 +1123,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
}
value = be16_to_cpu(value);
value &= wm8350_reg_io_map[i].readable;
+ value &= ~wm8350_reg_io_map[i].vol;
wm8350->reg_cache[i] = value;
} else
wm8350->reg_cache[i] = reg_map[i];
@@ -1128,7 +1132,6 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
out:
return ret;
}
-EXPORT_SYMBOL_GPL(wm8350_create_cache);
/*
* Register a client device. This is non-fatal since there is no need to
@@ -1217,7 +1220,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
mutex_init(&wm8350->irq_mutex);
INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
- if (irq != NO_IRQ) {
+ if (irq) {
ret = request_irq(irq, wm8350_irq, 0,
"wm8350", wm8350);
if (ret != 0) {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index efd3aa08b88..9494400e8fd 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -145,6 +145,7 @@ config ACER_WMI
depends on NEW_LEDS
depends on BACKLIGHT_CLASS_DEVICE
depends on SERIO_I8042
+ depends on RFKILL
select ACPI_WMI
---help---
This is a driver for newer Acer (and Wistron) laptops. It adds
@@ -245,6 +246,17 @@ config MSI_LAPTOP
If you have an MSI S270 laptop, say Y or M here.
+config PANASONIC_LAPTOP
+ tristate "Panasonic Laptop Extras"
+ depends on X86 && INPUT && ACPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This driver adds support for access to backlight control and hotkeys
+ on Panasonic Let's Note laptops.
+
+ If you have a Panasonic Let's note laptop (such as the R1(N variant),
+ R2, R3, R5, T2, W2 and Y2 series), say Y.
+
config COMPAL_LAPTOP
tristate "Compal Laptop Extras"
depends on X86
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c6c13f60b45..909e2468cdc 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
+obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index d8b0d326e45..0532a2de2ce 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -33,6 +33,8 @@
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/i8042.h>
+#include <linux/rfkill.h>
+#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <acpi/acpi_drivers.h>
@@ -123,21 +125,15 @@ enum interface_flags {
static int max_brightness = 0xF;
-static int wireless = -1;
-static int bluetooth = -1;
static int mailled = -1;
static int brightness = -1;
static int threeg = -1;
static int force_series;
module_param(mailled, int, 0444);
-module_param(wireless, int, 0444);
-module_param(bluetooth, int, 0444);
module_param(brightness, int, 0444);
module_param(threeg, int, 0444);
module_param(force_series, int, 0444);
-MODULE_PARM_DESC(wireless, "Set initial state of Wireless hardware");
-MODULE_PARM_DESC(bluetooth, "Set initial state of Bluetooth hardware");
MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
@@ -145,8 +141,6 @@ MODULE_PARM_DESC(force_series, "Force a different laptop series");
struct acer_data {
int mailled;
- int wireless;
- int bluetooth;
int threeg;
int brightness;
};
@@ -157,6 +151,9 @@ struct acer_debug {
u32 wmid_devices;
};
+static struct rfkill *wireless_rfkill;
+static struct rfkill *bluetooth_rfkill;
+
/* Each low-level interface must define at least some of the following */
struct wmi_interface {
/* The WMI device type */
@@ -476,7 +473,7 @@ struct wmi_interface *iface)
}
break;
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
return AE_OK;
}
@@ -514,7 +511,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
break;
}
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
/* Actually do the set */
@@ -689,7 +686,7 @@ struct wmi_interface *iface)
return 0;
}
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
status = WMI_execute_u32(method_id, 0, &result);
@@ -735,7 +732,7 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
}
break;
default:
- return AE_BAD_ADDRESS;
+ return AE_ERROR;
}
return WMI_execute_u32(method_id, (u32)value, NULL);
}
@@ -785,7 +782,7 @@ static struct wmi_interface wmid_interface = {
static acpi_status get_u32(u32 *value, u32 cap)
{
- acpi_status status = AE_BAD_ADDRESS;
+ acpi_status status = AE_ERROR;
switch (interface->type) {
case ACER_AMW0:
@@ -846,8 +843,6 @@ static void __init acer_commandline_init(void)
* capability isn't available on the given interface
*/
set_u32(mailled, ACER_CAP_MAILLED);
- set_u32(wireless, ACER_CAP_WIRELESS);
- set_u32(bluetooth, ACER_CAP_BLUETOOTH);
set_u32(threeg, ACER_CAP_THREEG);
set_u32(brightness, ACER_CAP_BRIGHTNESS);
}
@@ -933,40 +928,135 @@ static void acer_backlight_exit(void)
}
/*
- * Read/ write bool sysfs macro
+ * Rfkill devices
*/
-#define show_set_bool(value, cap) \
-static ssize_t \
-show_bool_##value(struct device *dev, struct device_attribute *attr, \
- char *buf) \
-{ \
- u32 result; \
- acpi_status status = get_u32(&result, cap); \
- if (ACPI_SUCCESS(status)) \
- return sprintf(buf, "%u\n", result); \
- return sprintf(buf, "Read error\n"); \
-} \
-\
-static ssize_t \
-set_bool_##value(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- u32 tmp = simple_strtoul(buf, NULL, 10); \
- acpi_status status = set_u32(tmp, cap); \
- if (ACPI_FAILURE(status)) \
- return -EINVAL; \
- return count; \
-} \
-static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \
- show_bool_##value, set_bool_##value);
-
-show_set_bool(wireless, ACER_CAP_WIRELESS);
-show_set_bool(bluetooth, ACER_CAP_BLUETOOTH);
-show_set_bool(threeg, ACER_CAP_THREEG);
+static void acer_rfkill_update(struct work_struct *ignored);
+static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
+static void acer_rfkill_update(struct work_struct *ignored)
+{
+ u32 state;
+ acpi_status status;
+
+ status = get_u32(&state, ACER_CAP_WIRELESS);
+ if (ACPI_SUCCESS(status))
+ rfkill_force_state(wireless_rfkill, state ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED);
+
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ status = get_u32(&state, ACER_CAP_BLUETOOTH);
+ if (ACPI_SUCCESS(status))
+ rfkill_force_state(bluetooth_rfkill, state ?
+ RFKILL_STATE_UNBLOCKED :
+ RFKILL_STATE_SOFT_BLOCKED);
+ }
+
+ schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
+}
+
+static int acer_rfkill_set(void *data, enum rfkill_state state)
+{
+ acpi_status status;
+ u32 *cap = data;
+ status = set_u32((u32) (state == RFKILL_STATE_UNBLOCKED), *cap);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+ return 0;
+}
+
+static struct rfkill * acer_rfkill_register(struct device *dev,
+enum rfkill_type type, char *name, u32 cap)
+{
+ int err;
+ u32 state;
+ u32 *data;
+ struct rfkill *rfkill_dev;
+
+ rfkill_dev = rfkill_allocate(dev, type);
+ if (!rfkill_dev)
+ return ERR_PTR(-ENOMEM);
+ rfkill_dev->name = name;
+ get_u32(&state, cap);
+ rfkill_dev->state = state ? RFKILL_STATE_UNBLOCKED :
+ RFKILL_STATE_SOFT_BLOCKED;
+ data = kzalloc(sizeof(u32), GFP_KERNEL);
+ if (!data) {
+ rfkill_free(rfkill_dev);
+ return ERR_PTR(-ENOMEM);
+ }
+ *data = cap;
+ rfkill_dev->data = data;
+ rfkill_dev->toggle_radio = acer_rfkill_set;
+ rfkill_dev->user_claim_unsupported = 1;
+
+ err = rfkill_register(rfkill_dev);
+ if (err) {
+ kfree(rfkill_dev->data);
+ rfkill_free(rfkill_dev);
+ return ERR_PTR(err);
+ }
+ return rfkill_dev;
+}
+
+static int acer_rfkill_init(struct device *dev)
+{
+ wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
+ "acer-wireless", ACER_CAP_WIRELESS);
+ if (IS_ERR(wireless_rfkill))
+ return PTR_ERR(wireless_rfkill);
+
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ bluetooth_rfkill = acer_rfkill_register(dev,
+ RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
+ ACER_CAP_BLUETOOTH);
+ if (IS_ERR(bluetooth_rfkill)) {
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(wireless_rfkill);
+ return PTR_ERR(bluetooth_rfkill);
+ }
+ }
+
+ schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
+
+ return 0;
+}
+
+static void acer_rfkill_exit(void)
+{
+ cancel_delayed_work_sync(&acer_rfkill_work);
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(wireless_rfkill);
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ kfree(wireless_rfkill->data);
+ rfkill_unregister(bluetooth_rfkill);
+ }
+ return;
+}
/*
- * Read interface sysfs macro
+ * sysfs interface
*/
+static ssize_t show_bool_threeg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u32 result; \
+ acpi_status status = get_u32(&result, ACER_CAP_THREEG);
+ if (ACPI_SUCCESS(status))
+ return sprintf(buf, "%u\n", result);
+ return sprintf(buf, "Read error\n");
+}
+
+static ssize_t set_bool_threeg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ u32 tmp = simple_strtoul(buf, NULL, 10);
+ acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+ return count;
+}
+static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg,
+ set_bool_threeg);
+
static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -1026,7 +1116,9 @@ static int __devinit acer_platform_probe(struct platform_device *device)
goto error_brightness;
}
- return 0;
+ err = acer_rfkill_init(&device->dev);
+
+ return err;
error_brightness:
acer_led_exit();
@@ -1040,6 +1132,8 @@ static int acer_platform_remove(struct platform_device *device)
acer_led_exit();
if (has_cap(ACER_CAP_BRIGHTNESS))
acer_backlight_exit();
+
+ acer_rfkill_exit();
return 0;
}
@@ -1052,16 +1146,6 @@ pm_message_t state)
if (!data)
return -ENOMEM;
- if (has_cap(ACER_CAP_WIRELESS)) {
- get_u32(&value, ACER_CAP_WIRELESS);
- data->wireless = value;
- }
-
- if (has_cap(ACER_CAP_BLUETOOTH)) {
- get_u32(&value, ACER_CAP_BLUETOOTH);
- data->bluetooth = value;
- }
-
if (has_cap(ACER_CAP_MAILLED)) {
get_u32(&value, ACER_CAP_MAILLED);
data->mailled = value;
@@ -1082,15 +1166,6 @@ static int acer_platform_resume(struct platform_device *device)
if (!data)
return -ENOMEM;
- if (has_cap(ACER_CAP_WIRELESS))
- set_u32(data->wireless, ACER_CAP_WIRELESS);
-
- if (has_cap(ACER_CAP_BLUETOOTH))
- set_u32(data->bluetooth, ACER_CAP_BLUETOOTH);
-
- if (has_cap(ACER_CAP_THREEG))
- set_u32(data->threeg, ACER_CAP_THREEG);
-
if (has_cap(ACER_CAP_MAILLED))
set_u32(data->mailled, ACER_CAP_MAILLED);
@@ -1115,12 +1190,6 @@ static struct platform_device *acer_platform_device;
static int remove_sysfs(struct platform_device *device)
{
- if (has_cap(ACER_CAP_WIRELESS))
- device_remove_file(&device->dev, &dev_attr_wireless);
-
- if (has_cap(ACER_CAP_BLUETOOTH))
- device_remove_file(&device->dev, &dev_attr_bluetooth);
-
if (has_cap(ACER_CAP_THREEG))
device_remove_file(&device->dev, &dev_attr_threeg);
@@ -1133,20 +1202,6 @@ static int create_sysfs(void)
{
int retval = -ENOMEM;
- if (has_cap(ACER_CAP_WIRELESS)) {
- retval = device_create_file(&acer_platform_device->dev,
- &dev_attr_wireless);
- if (retval)
- goto error_sysfs;
- }
-
- if (has_cap(ACER_CAP_BLUETOOTH)) {
- retval = device_create_file(&acer_platform_device->dev,
- &dev_attr_bluetooth);
- if (retval)
- goto error_sysfs;
- }
-
if (has_cap(ACER_CAP_THREEG)) {
retval = device_create_file(&acer_platform_device->dev,
&dev_attr_threeg);
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 7c6dfd03de9..a9d5228724a 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -139,6 +139,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
"\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
"\\_SB.PCI0.PX40.EC0.Q10", /* M1A */
"\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */
+ "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
"\\_SB.PCI0.PX40.Q10", /* S1x */
"\\Q10"); /* A2x, L2D, L3D, M2E */
@@ -280,7 +281,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
static int read_wireless_status(int mask)
{
- ulong status;
+ unsigned long long status;
acpi_status rv = AE_OK;
if (!wireless_status_handle)
@@ -297,7 +298,7 @@ static int read_wireless_status(int mask)
static int read_gps_status(void)
{
- ulong status;
+ unsigned long long status;
acpi_status rv = AE_OK;
rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
@@ -350,7 +351,7 @@ static void write_status(acpi_handle handle, int out, int mask)
static void object##_led_set(struct led_classdev *led_cdev, \
enum led_brightness value) \
{ \
- object##_led_wk = value; \
+ object##_led_wk = (value > 0) ? 1 : 0; \
queue_work(led_workqueue, &object##_led_work); \
} \
static void object##_led_update(struct work_struct *ignored) \
@@ -404,7 +405,7 @@ static void lcd_blank(int blank)
static int read_brightness(struct backlight_device *bd)
{
- ulong value;
+ unsigned long long value;
acpi_status rv = AE_OK;
rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value);
@@ -455,7 +456,7 @@ static ssize_t show_infos(struct device *dev,
struct device_attribute *attr, char *page)
{
int len = 0;
- ulong temp;
+ unsigned long long temp;
char buf[16]; //enough for all info
acpi_status rv = AE_OK;
@@ -603,7 +604,7 @@ static void set_display(int value)
static int read_display(void)
{
- ulong value = 0;
+ unsigned long long value = 0;
acpi_status rv = AE_OK;
/* In most of the case, we know how to set the display, but sometime
@@ -849,7 +850,7 @@ static int asus_hotk_get_info(void)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *model = NULL;
- ulong bsts_result, hwrs_result;
+ unsigned long long bsts_result, hwrs_result;
char *string = NULL;
acpi_status status;
@@ -996,7 +997,7 @@ static int asus_hotk_add(struct acpi_device *device)
hotk->handle = device->handle;
strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
- acpi_driver_data(device) = hotk;
+ device->driver_data = hotk;
hotk->device = device;
result = asus_hotk_check();
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index 1ee8501e90f..9ef98b2d503 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -28,6 +28,8 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#include <linux/uaccess.h>
+#include <linux/input.h>
+#include <linux/rfkill.h>
#define EEEPC_LAPTOP_VERSION "0.1"
@@ -125,6 +127,10 @@ struct eeepc_hotk {
by this BIOS */
uint init_flag; /* Init flags */
u16 event_count[128]; /* count for each event */
+ struct input_dev *inputdev;
+ u16 *keycode_map;
+ struct rfkill *eeepc_wlan_rfkill;
+ struct rfkill *eeepc_bluetooth_rfkill;
};
/* The actual device the driver binds to */
@@ -140,6 +146,27 @@ static struct platform_driver platform_driver = {
static struct platform_device *platform_device;
+struct key_entry {
+ char type;
+ u8 code;
+ u16 keycode;
+};
+
+enum { KE_KEY, KE_END };
+
+static struct key_entry eeepc_keymap[] = {
+ /* Sleep already handled via generic ACPI code */
+ {KE_KEY, 0x10, KEY_WLAN },
+ {KE_KEY, 0x12, KEY_PROG1 },
+ {KE_KEY, 0x13, KEY_MUTE },
+ {KE_KEY, 0x14, KEY_VOLUMEDOWN },
+ {KE_KEY, 0x15, KEY_VOLUMEUP },
+ {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
+ {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
+ {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
+ {KE_END, 0},
+};
+
/*
* The hotkey driver declaration
*/
@@ -204,7 +231,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
static int read_acpi_int(acpi_handle handle, const char *method, int *val)
{
acpi_status status;
- ulong result;
+ unsigned long long result;
status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
if (ACPI_FAILURE(status)) {
@@ -261,6 +288,44 @@ static int update_bl_status(struct backlight_device *bd)
}
/*
+ * Rfkill helpers
+ */
+
+static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state)
+{
+ if (state == RFKILL_STATE_SOFT_BLOCKED)
+ return set_acpi(CM_ASL_WLAN, 0);
+ else
+ return set_acpi(CM_ASL_WLAN, 1);
+}
+
+static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state)
+{
+ if (get_acpi(CM_ASL_WLAN) == 1)
+ *state = RFKILL_STATE_UNBLOCKED;
+ else
+ *state = RFKILL_STATE_SOFT_BLOCKED;
+ return 0;
+}
+
+static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state)
+{
+ if (state == RFKILL_STATE_SOFT_BLOCKED)
+ return set_acpi(CM_ASL_BLUETOOTH, 0);
+ else
+ return set_acpi(CM_ASL_BLUETOOTH, 1);
+}
+
+static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state)
+{
+ if (get_acpi(CM_ASL_BLUETOOTH) == 1)
+ *state = RFKILL_STATE_UNBLOCKED;
+ else
+ *state = RFKILL_STATE_SOFT_BLOCKED;
+ return 0;
+}
+
+/*
* Sys helpers
*/
static int parse_arg(const char *buf, unsigned long count, int *val)
@@ -311,13 +376,11 @@ static ssize_t show_sys_acpi(int cm, char *buf)
EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
-EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN);
static struct attribute *platform_attributes[] = {
&dev_attr_camera.attr,
&dev_attr_cardr.attr,
&dev_attr_disp.attr,
- &dev_attr_wlan.attr,
NULL
};
@@ -328,8 +391,64 @@ static struct attribute_group platform_attribute_group = {
/*
* Hotkey functions
*/
+static struct key_entry *eepc_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
+
+ for (key = eeepc_keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
+
+ return NULL;
+}
+
+static struct key_entry *eepc_get_entry_by_keycode(int code)
+{
+ struct key_entry *key;
+
+ for (key = eeepc_keymap; key->type != KE_END; key++)
+ if (code == key->keycode && key->type == KE_KEY)
+ return key;
+
+ return NULL;
+}
+
+static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ struct key_entry *key = eepc_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int eeepc_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 = eepc_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!eepc_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static int eeepc_hotk_check(void)
{
+ const struct key_entry *key;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
int result;
@@ -356,6 +475,31 @@ static int eeepc_hotk_check(void)
"Get control methods supported: 0x%x\n",
ehotk->cm_supported);
}
+ ehotk->inputdev = input_allocate_device();
+ if (!ehotk->inputdev) {
+ printk(EEEPC_INFO "Unable to allocate input device\n");
+ return 0;
+ }
+ ehotk->inputdev->name = "Asus EeePC extra buttons";
+ ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
+ ehotk->inputdev->id.bustype = BUS_HOST;
+ ehotk->inputdev->getkeycode = eeepc_getkeycode;
+ ehotk->inputdev->setkeycode = eeepc_setkeycode;
+
+ for (key = eeepc_keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, ehotk->inputdev->evbit);
+ set_bit(key->keycode, ehotk->inputdev->keybit);
+ break;
+ }
+ }
+ result = input_register_device(ehotk->inputdev);
+ if (result) {
+ printk(EEEPC_INFO "Unable to register input device\n");
+ input_free_device(ehotk->inputdev);
+ return 0;
+ }
} else {
printk(EEEPC_ERR "Hotkey device not present, aborting\n");
return -EINVAL;
@@ -363,21 +507,6 @@ static int eeepc_hotk_check(void)
return 0;
}
-static void notify_wlan(u32 *event)
-{
- /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2
- will always be 0x10 */
- if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) {
- const char *method = cm_getv[CM_ASL_WLAN];
- int value;
- if (read_acpi_int(ehotk->handle, method, &value))
- printk(EEEPC_WARNING "Error reading %s\n",
- method);
- else if (value == 1)
- *event = 0x11;
- }
-}
-
static void notify_brn(void)
{
struct backlight_device *bd = eeepc_backlight_device;
@@ -386,14 +515,28 @@ static void notify_brn(void)
static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
{
+ static struct key_entry *key;
if (!ehotk)
return;
- if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag))
- notify_wlan(&event);
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
notify_brn();
acpi_bus_generate_proc_event(ehotk->device, event,
ehotk->event_count[event % 128]++);
+ if (ehotk->inputdev) {
+ key = eepc_get_entry_by_scancode(event);
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ input_report_key(ehotk->inputdev, key->keycode,
+ 1);
+ input_sync(ehotk->inputdev);
+ input_report_key(ehotk->inputdev, key->keycode,
+ 0);
+ input_sync(ehotk->inputdev);
+ break;
+ }
+ }
+ }
}
static int eeepc_hotk_add(struct acpi_device *device)
@@ -411,7 +554,7 @@ static int eeepc_hotk_add(struct acpi_device *device)
ehotk->handle = device->handle;
strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
- acpi_driver_data(device) = ehotk;
+ device->driver_data = ehotk;
ehotk->device = device;
result = eeepc_hotk_check();
if (result)
@@ -420,6 +563,47 @@ static int eeepc_hotk_add(struct acpi_device *device)
eeepc_hotk_notify, ehotk);
if (ACPI_FAILURE(status))
printk(EEEPC_ERR "Error installing notify handler\n");
+
+ if (get_acpi(CM_ASL_WLAN) != -1) {
+ ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev,
+ RFKILL_TYPE_WLAN);
+
+ if (!ehotk->eeepc_wlan_rfkill)
+ goto end;
+
+ ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
+ ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
+ ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
+ if (get_acpi(CM_ASL_WLAN) == 1)
+ ehotk->eeepc_wlan_rfkill->state =
+ RFKILL_STATE_UNBLOCKED;
+ else
+ ehotk->eeepc_wlan_rfkill->state =
+ RFKILL_STATE_SOFT_BLOCKED;
+ rfkill_register(ehotk->eeepc_wlan_rfkill);
+ }
+
+ if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
+ ehotk->eeepc_bluetooth_rfkill =
+ rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
+
+ if (!ehotk->eeepc_bluetooth_rfkill)
+ goto end;
+
+ ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
+ ehotk->eeepc_bluetooth_rfkill->toggle_radio =
+ eeepc_bluetooth_rfkill_set;
+ ehotk->eeepc_bluetooth_rfkill->get_state =
+ eeepc_bluetooth_rfkill_state;
+ if (get_acpi(CM_ASL_BLUETOOTH) == 1)
+ ehotk->eeepc_bluetooth_rfkill->state =
+ RFKILL_STATE_UNBLOCKED;
+ else
+ ehotk->eeepc_bluetooth_rfkill->state =
+ RFKILL_STATE_SOFT_BLOCKED;
+ rfkill_register(ehotk->eeepc_bluetooth_rfkill);
+ }
+
end:
if (result) {
kfree(ehotk);
@@ -553,6 +737,12 @@ static void eeepc_backlight_exit(void)
{
if (eeepc_backlight_device)
backlight_device_unregister(eeepc_backlight_device);
+ if (ehotk->inputdev)
+ input_unregister_device(ehotk->inputdev);
+ if (ehotk->eeepc_wlan_rfkill)
+ rfkill_unregister(ehotk->eeepc_wlan_rfkill);
+ if (ehotk->eeepc_bluetooth_rfkill)
+ rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
eeepc_backlight_device = NULL;
}
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index 3e56203e494..d2cf0bfe316 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -44,8 +44,9 @@
* Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
* also supported by this driver.
*
- * This driver has been tested on a Fujitsu Lifebook S6410 and S7020. It
- * should work on most P-series and S-series Lifebooks, but YMMV.
+ * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
+ * P8010. It should work on most P-series and S-series Lifebooks, but
+ * YMMV.
*
* The module parameter use_alt_lcd_levels switches between different ACPI
* brightness controls which are used by different Fujitsu laptops. In most
@@ -65,7 +66,7 @@
#include <linux/video_output.h>
#include <linux/platform_device.h>
-#define FUJITSU_DRIVER_VERSION "0.4.2"
+#define FUJITSU_DRIVER_VERSION "0.4.3"
#define FUJITSU_LCD_N_LEVELS 8
@@ -83,10 +84,10 @@
#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
/* Hotkey details */
-#define LOCK_KEY 0x410 /* codes for the keys in the GIRB register */
-#define DISPLAY_KEY 0x411 /* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */
-#define ENERGY_KEY 0x412 /* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */
-#define REST_KEY 0x413 /* KEY_SUSPEND (R key) */
+#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
+#define KEY2_CODE 0x411
+#define KEY3_CODE 0x412
+#define KEY4_CODE 0x413
#define MAX_HOTKEY_RINGBUFFER_SIZE 100
#define RINGBUFFERSIZE 40
@@ -123,6 +124,7 @@ struct fujitsu_t {
char phys[32];
struct backlight_device *bl_device;
struct platform_device *pf_device;
+ int keycode1, keycode2, keycode3, keycode4;
unsigned int max_brightness;
unsigned int brightness_changed;
@@ -224,7 +226,7 @@ static int set_lcd_level_alt(int level)
static int get_lcd_level(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n");
@@ -246,7 +248,7 @@ static int get_lcd_level(void)
static int get_max_brightness(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n");
@@ -263,7 +265,7 @@ static int get_max_brightness(void)
static int get_lcd_level_alt(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n");
@@ -384,7 +386,7 @@ static ssize_t store_lcd_level(struct device *dev,
static int get_irb(void)
{
- unsigned long state = 0;
+ unsigned long long state = 0;
acpi_status status = AE_OK;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n");
@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = {
}
};
-static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+static void dmi_check_cb_common(const struct dmi_system_id *id)
{
acpi_handle handle;
int have_blnf;
@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
"auto-detecting disable_adjust\n");
disable_brightness_adjust = have_blnf ? 0 : 1;
}
+}
+
+static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+{
+ dmi_check_cb_common(id);
+ fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
+ fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
+ return 0;
+}
+
+static int dmi_check_cb_p8010(const struct dmi_system_id *id)
+{
+ dmi_check_cb_common(id);
+ fujitsu->keycode1 = KEY_HELP; /* "Support" */
+ fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */
+ fujitsu->keycode4 = KEY_WWW; /* "Internet" */
return 0;
}
static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
{
- .ident = "Fujitsu Siemens",
+ .ident = "Fujitsu Siemens S6410",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
},
.callback = dmi_check_cb_s6410},
{
- .ident = "FUJITSU LifeBook P8010",
+ .ident = "Fujitsu LifeBook P8010",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
- },
- .callback = dmi_check_cb_s6410},
+ },
+ .callback = dmi_check_cb_p8010},
{}
};
@@ -490,7 +508,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
fujitsu->acpi_handle = device->handle;
sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
- acpi_driver_data(device) = fujitsu;
+ device->driver_data = fujitsu;
status = acpi_install_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY,
@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device)
}
/* do config (detect defaults) */
- dmi_check_system(fujitsu_dmi_table);
use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
keycode = 0;
if (disable_brightness_keys != 1) {
if (oldb == 0) {
- acpi_bus_generate_proc_event(fujitsu->
- dev,
- ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
- 0);
+ acpi_bus_generate_proc_event
+ (fujitsu->dev,
+ ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
+ 0);
keycode = KEY_BRIGHTNESSDOWN;
} else if (oldb ==
(fujitsu->max_brightness) - 1) {
- acpi_bus_generate_proc_event(fujitsu->
- dev,
- ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
- 0);
+ acpi_bus_generate_proc_event
+ (fujitsu->dev,
+ ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
+ 0);
keycode = KEY_BRIGHTNESSUP;
}
}
@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
}
if (disable_brightness_keys != 1) {
acpi_bus_generate_proc_event(fujitsu->dev,
- ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
- 0);
+ ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
keycode = KEY_BRIGHTNESSUP;
}
} else if (oldb > newb) {
@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
}
if (disable_brightness_keys != 1) {
acpi_bus_generate_proc_event(fujitsu->dev,
- ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
- 0);
+ ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
keycode = KEY_BRIGHTNESSDOWN;
}
} else {
@@ -703,7 +718,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
sprintf(acpi_device_name(device), "%s",
ACPI_FUJITSU_HOTKEY_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
- acpi_driver_data(device) = fujitsu_hotkey;
+ device->driver_data = fujitsu_hotkey;
status = acpi_install_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY,
@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
input->id.product = 0x06;
input->dev.parent = &device->dev;
input->evbit[0] = BIT(EV_KEY);
- set_bit(KEY_SCREENLOCK, input->keybit);
- set_bit(KEY_MEDIA, input->keybit);
- set_bit(KEY_EMAIL, input->keybit);
- set_bit(KEY_SUSPEND, input->keybit);
+ set_bit(fujitsu->keycode1, input->keybit);
+ set_bit(fujitsu->keycode2, input->keybit);
+ set_bit(fujitsu->keycode3, input->keybit);
+ set_bit(fujitsu->keycode4, input->keybit);
set_bit(KEY_UNKNOWN, input->keybit);
error = input_register_device(input);
@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
irb);
switch (irb & 0x4ff) {
- case LOCK_KEY:
- keycode = KEY_SCREENLOCK;
+ case KEY1_CODE:
+ keycode = fujitsu->keycode1;
break;
- case DISPLAY_KEY:
- keycode = KEY_MEDIA;
+ case KEY2_CODE:
+ keycode = fujitsu->keycode2;
break;
- case ENERGY_KEY:
- keycode = KEY_EMAIL;
+ case KEY3_CODE:
+ keycode = fujitsu->keycode3;
break;
- case REST_KEY:
- keycode = KEY_SUSPEND;
+ case KEY4_CODE:
+ keycode = fujitsu->keycode4;
break;
case 0:
keycode = 0;
break;
default:
vdbg_printk(FUJLAPTOP_DBG_WARN,
- "Unknown GIRB result [%x]\n", irb);
+ "Unknown GIRB result [%x]\n", irb);
keycode = -1;
break;
}
@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
"Push keycode into ringbuffer [%d]\n",
keycode);
status = kfifo_put(fujitsu_hotkey->fifo,
- (unsigned char *)&keycode,
- sizeof(keycode));
+ (unsigned char *)&keycode,
+ sizeof(keycode));
if (status != sizeof(keycode)) {
vdbg_printk(FUJLAPTOP_DBG_WARN,
- "Could not push keycode [0x%x]\n",
- keycode);
+ "Could not push keycode [0x%x]\n",
+ keycode);
} else {
input_report_key(input, keycode, 1);
input_sync(input);
@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
input_report_key(input, keycode_r, 0);
input_sync(input);
vdbg_printk(FUJLAPTOP_DBG_TRACE,
- "Pop keycode from ringbuffer [%d]\n",
- keycode_r);
+ "Pop keycode from ringbuffer [%d]\n",
+ keycode_r);
}
}
}
@@ -943,6 +958,11 @@ static int __init fujitsu_init(void)
if (!fujitsu)
return -ENOMEM;
memset(fujitsu, 0, sizeof(struct fujitsu_t));
+ fujitsu->keycode1 = KEY_PROG1;
+ fujitsu->keycode2 = KEY_PROG2;
+ fujitsu->keycode3 = KEY_PROG3;
+ fujitsu->keycode4 = KEY_PROG4;
+ dmi_check_system(fujitsu_dmi_table);
result = acpi_bus_register_driver(&acpi_fujitsu_driver);
if (result < 0) {
@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support");
MODULE_VERSION(FUJITSU_DRIVER_VERSION);
MODULE_LICENSE("GPL");
-MODULE_ALIAS
- ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
-MODULE_ALIAS
- ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
+MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
+MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
static struct pnp_device_id pnp_ids[] = {
- { .id = "FUJ02bf" },
- { .id = "FUJ02B1" },
- { .id = "FUJ02E3" },
- { .id = "" }
+ {.id = "FUJ02bf"},
+ {.id = "FUJ02B1"},
+ {.id = "FUJ02E3"},
+ {.id = ""}
};
+
MODULE_DEVICE_TABLE(pnp, pnp_ids);
diff --git a/drivers/misc/hp-wmi.c b/drivers/misc/hp-wmi.c
index 5dabfb69ee5..4b7c24c519c 100644
--- a/drivers/misc/hp-wmi.c
+++ b/drivers/misc/hp-wmi.c
@@ -82,6 +82,7 @@ static struct key_entry hp_wmi_keymap[] = {
{KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
{KE_KEY, 0x20e6, KEY_PROG1},
{KE_KEY, 0x2142, KEY_MEDIA},
+ {KE_KEY, 0x213b, KEY_INFO},
{KE_KEY, 0x231b, KEY_HELP},
{KE_END, 0}
};
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
index 80a13635240..e00a2756e97 100644
--- a/drivers/misc/intel_menlow.c
+++ b/drivers/misc/intel_menlow.c
@@ -57,7 +57,7 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
{
struct acpi_device *device = cdev->devdata;
acpi_handle handle = device->handle;
- unsigned long value;
+ unsigned long long value;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
@@ -90,7 +90,7 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
{
struct acpi_device *device = cdev->devdata;
acpi_handle handle = device->handle;
- unsigned long value;
+ unsigned long long value;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
@@ -104,7 +104,7 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
if (ACPI_FAILURE(status))
return -EFAULT;
- return sprintf(buf, "%ld\n", value);
+ return sprintf(buf, "%llu\n", value);
}
static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
@@ -115,7 +115,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status;
- int temp;
+ unsigned long long temp;
unsigned long max_state;
if (memory_get_int_max_bandwidth(cdev, &max_state))
@@ -131,7 +131,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
status =
acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list,
- (unsigned long *)&temp);
+ &temp);
printk(KERN_INFO
"Bandwidth value was %d: status is %d\n", state, status);
@@ -175,7 +175,7 @@ static int intel_menlow_memory_add(struct acpi_device *device)
goto end;
}
- acpi_driver_data(device) = cdev;
+ device->driver_data = cdev;
result = sysfs_create_link(&device->dev.kobj,
&cdev->device.kobj, "thermal_cooling");
if (result)
@@ -252,7 +252,8 @@ static DEFINE_MUTEX(intel_menlow_attr_lock);
* @auxtype : AUX0/AUX1
* @buf: syfs buffer
*/
-static int sensor_get_auxtrip(acpi_handle handle, int index, int *value)
+static int sensor_get_auxtrip(acpi_handle handle, int index,
+ unsigned long long *value)
{
acpi_status status;
@@ -260,7 +261,7 @@ static int sensor_get_auxtrip(acpi_handle handle, int index, int *value)
return -EINVAL;
status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0,
- NULL, (unsigned long *)value);
+ NULL, value);
if (ACPI_FAILURE(status))
return -EIO;
@@ -282,13 +283,13 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
struct acpi_object_list args = {
1, &arg
};
- int temp;
+ unsigned long long temp;
if (index != 0 && index != 1)
return -EINVAL;
status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1,
- NULL, (unsigned long *)&temp);
+ NULL, &temp);
if (ACPI_FAILURE(status))
return -EIO;
if ((index && value < temp) || (!index && value > temp))
@@ -296,7 +297,7 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
arg.integer.value = value;
status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0,
- &args, (unsigned long *)&temp);
+ &args, &temp);
if (ACPI_FAILURE(status))
return -EIO;
@@ -312,7 +313,7 @@ static ssize_t aux0_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr);
- int value;
+ unsigned long long value;
int result;
result = sensor_get_auxtrip(attr->handle, 0, &value);
@@ -324,7 +325,7 @@ static ssize_t aux1_show(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr);
- int value;
+ unsigned long long value;
int result;
result = sensor_get_auxtrip(attr->handle, 1, &value);
@@ -376,7 +377,7 @@ static ssize_t bios_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
acpi_status status;
- unsigned long bios_enabled;
+ unsigned long long bios_enabled;
status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled);
if (ACPI_FAILURE(status))
@@ -492,7 +493,7 @@ static int __init intel_menlow_module_init(void)
{
int result = -ENODEV;
acpi_status status;
- unsigned long enable;
+ unsigned long long enable;
if (acpi_disabled)
return result;
diff --git a/drivers/misc/panasonic-laptop.c b/drivers/misc/panasonic-laptop.c
new file mode 100644
index 00000000000..a2cb598d8ab
--- /dev/null
+++ b/drivers/misc/panasonic-laptop.c
@@ -0,0 +1,767 @@
+/*
+ * Panasonic HotKey and LCD brightness control driver
+ * (C) 2004 Hiroshi Miura <miura@da-cha.org>
+ * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
+ * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp>
+ * (C) 2004 David Bronaugh <dbronaugh>
+ * (C) 2006-2008 Harald Welte <laforge@gnumonks.org>
+ *
+ * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte
+ *
+ * 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
+ * publicshed by the Free Software Foundation.
+ *
+ * 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
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ChangeLog:
+ * Sep.23, 2008 Harald Welte <laforge@gnumonks.org>
+ * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to
+ * drivers/misc/panasonic-laptop.c
+ *
+ * Jul.04, 2008 Harald Welte <laforge@gnumonks.org>
+ * -v0.94 replace /proc interface with device attributes
+ * support {set,get}keycode on th input device
+ *
+ * Jun.27, 2008 Harald Welte <laforge@gnumonks.org>
+ * -v0.92 merge with 2.6.26-rc6 input API changes
+ * remove broken <= 2.6.15 kernel support
+ * resolve all compiler warnings
+ * various coding style fixes (checkpatch.pl)
+ * add support for backlight api
+ * major code restructuring
+ *
+ * Dac.28, 2007 Harald Welte <laforge@gnumonks.org>
+ * -v0.91 merge with 2.6.24-rc6 ACPI changes
+ *
+ * Nov.04, 2006 Hiroshi Miura <miura@da-cha.org>
+ * -v0.9 remove warning about section reference.
+ * remove acpi_os_free
+ * add /proc/acpi/pcc/brightness interface for HAL access
+ * merge dbronaugh's enhancement
+ * Aug.17, 2004 David Bronaugh (dbronaugh)
+ * - Added screen brightness setting interface
+ * Thanks to FreeBSD crew (acpi_panasonic.c)
+ * for the ideas I needed to accomplish it
+ *
+ * May.29, 2006 Hiroshi Miura <miura@da-cha.org>
+ * -v0.8.4 follow to change keyinput structure
+ * thanks Fabian Yamaguchi <fabs@cs.tu-berlin.de>,
+ * Jacob Bower <jacob.bower@ic.ac.uk> and
+ * Hiroshi Yokota for providing solutions.
+ *
+ * Oct.02, 2004 Hiroshi Miura <miura@da-cha.org>
+ * -v0.8.2 merge code of YOKOTA Hiroshi
+ * <yokota@netlab.is.tsukuba.ac.jp>.
+ * Add sticky key mode interface.
+ * Refactoring acpi_pcc_generate_keyinput().
+ *
+ * Sep.15, 2004 Hiroshi Miura <miura@da-cha.org>
+ * -v0.8 Generate key input event on input subsystem.
+ * This is based on yet another driver written by
+ * Ryuta Nakanishi.
+ *
+ * Sep.10, 2004 Hiroshi Miura <miura@da-cha.org>
+ * -v0.7 Change proc interface functions using seq_file
+ * facility as same as other ACPI drivers.
+ *
+ * Aug.28, 2004 Hiroshi Miura <miura@da-cha.org>
+ * -v0.6.4 Fix a silly error with status checking
+ *
+ * Aug.25, 2004 Hiroshi Miura <miura@da-cha.org>
+ * -v0.6.3 replace read_acpi_int by standard function
+ * acpi_evaluate_integer
+ * some clean up and make smart copyright notice.
+ * fix return value of pcc_acpi_get_key()
+ * fix checking return value of acpi_bus_register_driver()
+ *
+ * Aug.22, 2004 David Bronaugh <dbronaugh@linuxboxen.org>
+ * -v0.6.2 Add check on ACPI data (num_sifr)
+ * Coding style cleanups, better error messages/handling
+ * Fixed an off-by-one error in memory allocation
+ *
+ * Aug.21, 2004 David Bronaugh <dbronaugh@linuxboxen.org>
+ * -v0.6.1 Fix a silly error with status checking
+ *
+ * Aug.20, 2004 David Bronaugh <dbronaugh@linuxboxen.org>
+ * - v0.6 Correct brightness controls to reflect reality
+ * based on information gleaned by Hiroshi Miura
+ * and discussions with Hiroshi Miura
+ *
+ * Aug.10, 2004 Hiroshi Miura <miura@da-cha.org>
+ * - v0.5 support LCD brightness control
+ * based on the disclosed information by MEI.
+ *
+ * Jul.25, 2004 Hiroshi Miura <miura@da-cha.org>
+ * - v0.4 first post version
+ * add function to retrive SIFR
+ *
+ * Jul.24, 2004 Hiroshi Miura <miura@da-cha.org>
+ * - v0.3 get proper status of hotkey
+ *
+ * Jul.22, 2004 Hiroshi Miura <miura@da-cha.org>
+ * - v0.2 add HotKey handler
+ *
+ * Jul.17, 2004 Hiroshi Miura <miura@da-cha.org>
+ * - v0.1 start from toshiba_acpi driver written by John Belmonte
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/backlight.h>
+#include <linux/ctype.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/input.h>
+
+
+#ifndef ACPI_HOTKEY_COMPONENT
+#define ACPI_HOTKEY_COMPONENT 0x10000000
+#endif
+
+#define _COMPONENT ACPI_HOTKEY_COMPONENT
+
+MODULE_AUTHOR("Hiroshi Miura, David Bronaugh and Harald Welte");
+MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops");
+MODULE_LICENSE("GPL");
+
+#define LOGPREFIX "pcc_acpi: "
+
+/* Define ACPI PATHs */
+/* Lets note hotkeys */
+#define METHOD_HKEY_QUERY "HINF"
+#define METHOD_HKEY_SQTY "SQTY"
+#define METHOD_HKEY_SINF "SINF"
+#define METHOD_HKEY_SSET "SSET"
+#define HKEY_NOTIFY 0x80
+
+#define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support"
+#define ACPI_PCC_DEVICE_NAME "Hotkey"
+#define ACPI_PCC_CLASS "pcc"
+
+#define ACPI_PCC_INPUT_PHYS "panasonic/hkey0"
+
+/* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent
+ ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00
+*/
+enum SINF_BITS { SINF_NUM_BATTERIES = 0,
+ SINF_LCD_TYPE,
+ SINF_AC_MAX_BRIGHT,
+ SINF_AC_MIN_BRIGHT,
+ SINF_AC_CUR_BRIGHT,
+ SINF_DC_MAX_BRIGHT,
+ SINF_DC_MIN_BRIGHT,
+ SINF_DC_CUR_BRIGHT,
+ SINF_MUTE,
+ SINF_RESERVED,
+ SINF_ENV_STATE,
+ SINF_STICKY_KEY = 0x80,
+ };
+/* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */
+
+static int acpi_pcc_hotkey_add(struct acpi_device *device);
+static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
+static int acpi_pcc_hotkey_resume(struct acpi_device *device);
+
+static const struct acpi_device_id pcc_device_ids[] = {
+ { "MAT0012", 0},
+ { "MAT0013", 0},
+ { "MAT0018", 0},
+ { "MAT0019", 0},
+ { "", 0},
+};
+
+static struct acpi_driver acpi_pcc_driver = {
+ .name = ACPI_PCC_DRIVER_NAME,
+ .class = ACPI_PCC_CLASS,
+ .ids = pcc_device_ids,
+ .ops = {
+ .add = acpi_pcc_hotkey_add,
+ .remove = acpi_pcc_hotkey_remove,
+ .resume = acpi_pcc_hotkey_resume,
+ },
+};
+
+#define KEYMAP_SIZE 11
+static const int initial_keymap[KEYMAP_SIZE] = {
+ /* 0 */ KEY_RESERVED,
+ /* 1 */ KEY_BRIGHTNESSDOWN,
+ /* 2 */ KEY_BRIGHTNESSUP,
+ /* 3 */ KEY_DISPLAYTOGGLE,
+ /* 4 */ KEY_MUTE,
+ /* 5 */ KEY_VOLUMEDOWN,
+ /* 6 */ KEY_VOLUMEUP,
+ /* 7 */ KEY_SLEEP,
+ /* 8 */ KEY_PROG1, /* Change CPU boost */
+ /* 9 */ KEY_BATTERY,
+ /* 10 */ KEY_SUSPEND,
+};
+
+struct pcc_acpi {
+ acpi_handle handle;
+ unsigned long num_sifr;
+ int sticky_mode;
+ u32 *sinf;
+ struct acpi_device *device;
+ struct input_dev *input_dev;
+ struct backlight_device *backlight;
+ int keymap[KEYMAP_SIZE];
+};
+
+struct pcc_keyinput {
+ struct acpi_hotkey *hotkey;
+};
+
+/* method access functions */
+static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
+{
+ union acpi_object in_objs[] = {
+ { .integer.type = ACPI_TYPE_INTEGER,
+ .integer.value = func, },
+ { .integer.type = ACPI_TYPE_INTEGER,
+ .integer.value = val, },
+ };
+ struct acpi_object_list params = {
+ .count = ARRAY_SIZE(in_objs),
+ .pointer = in_objs,
+ };
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_write_sset");
+
+ status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET,
+ &params, NULL);
+
+ return status == AE_OK;
+}
+
+static inline int acpi_pcc_get_sqty(struct acpi_device *device)
+{
+ unsigned long long s;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty");
+
+ status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY,
+ NULL, &s);
+ if (ACPI_SUCCESS(status))
+ return s;
+ else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "evaluation error HKEY.SQTY\n"));
+ return -EINVAL;
+ }
+}
+
+static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *hkey = NULL;
+ int i;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata");
+
+ status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, 0,
+ &buffer);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "evaluation error HKEY.SINF\n"));
+ return 0;
+ }
+
+ hkey = buffer.pointer;
+ if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n"));
+ goto end;
+ }
+
+ if (pcc->num_sifr < hkey->package.count) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "SQTY reports bad SINF length\n"));
+ status = AE_ERROR;
+ goto end;
+ }
+
+ for (i = 0; i < hkey->package.count; i++) {
+ union acpi_object *element = &(hkey->package.elements[i]);
+ if (likely(element->type == ACPI_TYPE_INTEGER)) {
+ sinf[i] = element->integer.value;
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid HKEY.SINF data\n"));
+ }
+ sinf[hkey->package.count] = -1;
+
+end:
+ kfree(buffer.pointer);
+ return status == AE_OK;
+}
+
+/* backlight API interface functions */
+
+/* This driver currently treats AC and DC brightness identical,
+ * since we don't need to invent an interface to the core ACPI
+ * logic to receive events in case a power supply is plugged in
+ * or removed */
+
+static int bl_get(struct backlight_device *bd)
+{
+ struct pcc_acpi *pcc = bl_get_data(bd);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return pcc->sinf[SINF_AC_CUR_BRIGHT];
+}
+
+static int bl_set_status(struct backlight_device *bd)
+{
+ struct pcc_acpi *pcc = bl_get_data(bd);
+ int bright = bd->props.brightness;
+ int rc;
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
+ bright = pcc->sinf[SINF_AC_MIN_BRIGHT];
+
+ if (bright < pcc->sinf[SINF_DC_MIN_BRIGHT])
+ bright = pcc->sinf[SINF_DC_MIN_BRIGHT];
+
+ if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT] ||
+ bright > pcc->sinf[SINF_AC_MAX_BRIGHT])
+ return -EINVAL;
+
+ rc = acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, bright);
+ if (rc < 0)
+ return rc;
+
+ return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright);
+}
+
+static struct backlight_ops pcc_backlight_ops = {
+ .get_brightness = bl_get,
+ .update_status = bl_set_status,
+};
+
+
+/* sysfs user interface functions */
+
+static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
+}
+
+static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
+}
+
+static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_MUTE]);
+}
+
+static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+ return -EIO;
+
+ return sprintf(buf, "%u\n", pcc->sinf[SINF_STICKY_KEY]);
+}
+
+static ssize_t set_sticky(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct acpi_device *acpi = to_acpi_device(dev);
+ struct pcc_acpi *pcc = acpi_driver_data(acpi);
+ int val;
+
+ if (count && sscanf(buf, "%i", &val) == 1 &&
+ (val == 0 || val == 1)) {
+ acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, val);
+ pcc->sticky_mode = val;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL);
+static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL);
+static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL);
+static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky);
+
+static struct attribute *pcc_sysfs_entries[] = {
+ &dev_attr_numbatt.attr,
+ &dev_attr_lcdtype.attr,
+ &dev_attr_mute.attr,
+ &dev_attr_sticky_key.attr,
+ NULL,
+};
+
+static struct attribute_group pcc_attr_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = pcc_sysfs_entries,
+};
+
+
+/* hotkey input device driver */
+
+static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ struct pcc_acpi *pcc = input_get_drvdata(dev);
+
+ if (scancode >= ARRAY_SIZE(pcc->keymap))
+ return -EINVAL;
+
+ *keycode = pcc->keymap[scancode];
+
+ return 0;
+}
+
+static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
+ if (pcc->keymap[i] == keycode)
+ return i+1;
+ }
+
+ return 0;
+}
+
+static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct pcc_acpi *pcc = input_get_drvdata(dev);
+ int oldkeycode;
+
+ if (scancode >= ARRAY_SIZE(pcc->keymap))
+ return -EINVAL;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ oldkeycode = pcc->keymap[scancode];
+ pcc->keymap[scancode] = keycode;
+
+ set_bit(keycode, dev->keybit);
+
+ if (!keymap_get_by_keycode(pcc, oldkeycode))
+ clear_bit(oldkeycode, dev->keybit);
+
+ return 0;
+}
+
+static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
+{
+ struct input_dev *hotk_input_dev = pcc->input_dev;
+ int rc;
+ int key_code, hkey_num;
+ unsigned long long result;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_generate_keyinput");
+
+ rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
+ NULL, &result);
+ if (!ACPI_SUCCESS(rc)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "error getting hotkey status\n"));
+ return;
+ }
+
+ acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
+
+ hkey_num = result & 0xf;
+
+ if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "hotkey number out of range: %d\n",
+ hkey_num));
+ return;
+ }
+
+ key_code = pcc->keymap[hkey_num];
+
+ if (key_code != KEY_RESERVED) {
+ int pushed = (result & 0x80) ? TRUE : FALSE;
+
+ input_report_key(hotk_input_dev, key_code, pushed);
+ input_sync(hotk_input_dev);
+ }
+
+ return;
+}
+
+static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct pcc_acpi *pcc = (struct pcc_acpi *) data;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_notify");
+
+ switch (event) {
+ case HKEY_NOTIFY:
+ acpi_pcc_generate_keyinput(pcc);
+ break;
+ default:
+ /* nothing to do */
+ break;
+ }
+}
+
+static int acpi_pcc_init_input(struct pcc_acpi *pcc)
+{
+ int i, rc;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_init_input");
+
+ pcc->input_dev = input_allocate_device();
+ if (!pcc->input_dev) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Couldn't allocate input device for hotkey"));
+ return -ENOMEM;
+ }
+
+ pcc->input_dev->evbit[0] = BIT(EV_KEY);
+
+ pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
+ pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
+ pcc->input_dev->id.bustype = BUS_HOST;
+ pcc->input_dev->id.vendor = 0x0001;
+ pcc->input_dev->id.product = 0x0001;
+ pcc->input_dev->id.version = 0x0100;
+ pcc->input_dev->getkeycode = pcc_getkeycode;
+ pcc->input_dev->setkeycode = pcc_setkeycode;
+
+ /* load initial keymap */
+ memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
+
+ for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
+ __set_bit(pcc->keymap[i], pcc->input_dev->keybit);
+ __clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
+
+ input_set_drvdata(pcc->input_dev, pcc);
+
+ rc = input_register_device(pcc->input_dev);
+ if (rc < 0)
+ input_free_device(pcc->input_dev);
+
+ return rc;
+}
+
+/* kernel module interface */
+
+static int acpi_pcc_hotkey_resume(struct acpi_device *device)
+{
+ struct pcc_acpi *pcc = acpi_driver_data(device);
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume");
+
+ if (device == NULL || pcc == NULL)
+ return -EINVAL;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n",
+ pcc->sticky_mode));
+
+ status = acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode);
+
+ return status == AE_OK ? 0 : -EINVAL;
+}
+
+static int acpi_pcc_hotkey_add(struct acpi_device *device)
+{
+ acpi_status status;
+ struct pcc_acpi *pcc;
+ int num_sifr, result;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add");
+
+ if (!device)
+ return -EINVAL;
+
+ num_sifr = acpi_pcc_get_sqty(device);
+
+ if (num_sifr > 255) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large"));
+ return -ENODEV;
+ }
+
+ pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL);
+ if (!pcc) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Couldn't allocate mem for pcc"));
+ return -ENOMEM;
+ }
+
+ pcc->sinf = kzalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
+ if (!pcc->sinf) {
+ result = -ENOMEM;
+ goto out_hotkey;
+ }
+
+ pcc->device = device;
+ pcc->handle = device->handle;
+ pcc->num_sifr = num_sifr;
+ device->driver_data = pcc;
+ strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_PCC_CLASS);
+
+ result = acpi_pcc_init_input(pcc);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error installing keyinput handler\n"));
+ goto out_sinf;
+ }
+
+ /* initialize hotkey input device */
+ status = acpi_install_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify, pcc);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error installing notify handler\n"));
+ result = -ENODEV;
+ goto out_input;
+ }
+
+ /* initialize backlight */
+ pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
+ &pcc_backlight_ops);
+ if (IS_ERR(pcc->backlight))
+ goto out_notify;
+
+ if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Couldn't retrieve BIOS data\n"));
+ goto out_backlight;
+ }
+
+ /* read the initial brightness setting from the hardware */
+ pcc->backlight->props.max_brightness =
+ pcc->sinf[SINF_AC_MAX_BRIGHT];
+ pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
+
+ /* read the initial sticky key mode from the hardware */
+ pcc->sticky_mode = pcc->sinf[SINF_STICKY_KEY];
+
+ /* add sysfs attributes */
+ result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group);
+ if (result)
+ goto out_backlight;
+
+ return 0;
+
+out_backlight:
+ backlight_device_unregister(pcc->backlight);
+out_notify:
+ acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify);
+out_input:
+ input_unregister_device(pcc->input_dev);
+ /* no need to input_free_device() since core input API refcount and
+ * free()s the device */
+out_sinf:
+ kfree(pcc->sinf);
+out_hotkey:
+ kfree(pcc);
+
+ return result;
+}
+
+static int __init acpi_pcc_init(void)
+{
+ int result = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_init");
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ result = acpi_bus_register_driver(&acpi_pcc_driver);
+ if (result < 0) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error registering hotkey driver\n"));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
+{
+ struct pcc_acpi *pcc = acpi_driver_data(device);
+
+ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove");
+
+ if (!device || !pcc)
+ return -EINVAL;
+
+ sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
+
+ backlight_device_unregister(pcc->backlight);
+
+ acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_pcc_hotkey_notify);
+
+ input_unregister_device(pcc->input_dev);
+ /* no need to input_free_device() since core input API refcount and
+ * free()s the device */
+
+ kfree(pcc->sinf);
+ kfree(pcc);
+
+ return 0;
+}
+
+static void __exit acpi_pcc_exit(void)
+{
+ ACPI_FUNCTION_TRACE("acpi_pcc_exit");
+
+ acpi_bus_unregister_driver(&acpi_pcc_driver);
+}
+
+module_init(acpi_pcc_init);
+module_exit(acpi_pcc_exit);
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 60775be2282..5a97d3a9d74 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -970,7 +970,7 @@ static int sony_nc_resume(struct acpi_device *device)
/* set the last requested brightness level */
if (sony_backlight_device &&
!sony_backlight_update_status(sony_backlight_device))
- printk(KERN_WARNING DRV_PFX "unable to restore brightness level");
+ printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
/* re-initialize models with specific requirements */
dmi_check_system(sony_nc_ids);
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 6b9300779a4..4db1cf9078d 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -159,7 +159,6 @@ enum {
#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
#define TPACPI_DBG_ALL 0xffff
-#define TPACPI_DBG_ALL 0xffff
#define TPACPI_DBG_INIT 0x0001
#define TPACPI_DBG_EXIT 0x0002
#define dbg_printk(a_dbg_level, format, arg...) \
@@ -543,7 +542,7 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
return -ENODEV;
}
- acpi_driver_data(ibm->acpi->device) = ibm;
+ ibm->acpi->device->driver_data = ibm;
sprintf(acpi_device_class(ibm->acpi->device), "%s/%s",
TPACPI_ACPI_EVENT_PREFIX,
ibm->name);
@@ -582,7 +581,8 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
if (!ibm->acpi->driver) {
- printk(TPACPI_ERR "kzalloc(ibm->driver) failed\n");
+ printk(TPACPI_ERR
+ "failed to allocate memory for ibm->acpi->driver\n");
return -ENOMEM;
}
@@ -838,6 +838,13 @@ static int parse_strtoul(const char *buf,
return 0;
}
+static void tpacpi_disable_brightness_delay(void)
+{
+ if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0))
+ printk(TPACPI_NOTICE
+ "ACPI backlight control delay disabled\n");
+}
+
static int __init tpacpi_query_bcl_levels(acpi_handle handle)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -2139,6 +2146,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
if (!tp_features.hotkey)
return 1;
+ tpacpi_disable_brightness_delay();
+
hotkey_dev_attributes = create_attr_set(13, NULL);
if (!hotkey_dev_attributes)
return -ENOMEM;
@@ -2512,6 +2521,8 @@ static void hotkey_suspend(pm_message_t state)
static void hotkey_resume(void)
{
+ tpacpi_disable_brightness_delay();
+
if (hotkey_mask_get())
printk(TPACPI_ERR
"error while trying to read hot key mask "
@@ -5983,6 +5994,52 @@ static void fan_exit(void)
flush_workqueue(tpacpi_wq);
}
+static void fan_suspend(pm_message_t state)
+{
+ if (!fan_control_allowed)
+ return;
+
+ /* Store fan status in cache */
+ fan_get_status_safe(NULL);
+ if (tp_features.fan_ctrl_status_undef)
+ fan_control_desired_level = TP_EC_FAN_AUTO;
+}
+
+static void fan_resume(void)
+{
+ u8 saved_fan_level;
+ u8 current_level = 7;
+ bool do_set = false;
+
+ /* DSDT *always* updates status on resume */
+ tp_features.fan_ctrl_status_undef = 0;
+
+ saved_fan_level = fan_control_desired_level;
+ if (!fan_control_allowed ||
+ (fan_get_status_safe(&current_level) < 0))
+ return;
+
+ switch (fan_control_access_mode) {
+ case TPACPI_FAN_WR_ACPI_SFAN:
+ do_set = (saved_fan_level > current_level);
+ break;
+ case TPACPI_FAN_WR_ACPI_FANS:
+ case TPACPI_FAN_WR_TPEC:
+ do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) ||
+ (saved_fan_level == 7 &&
+ !(current_level & TP_EC_FAN_FULLSPEED)));
+ break;
+ default:
+ return;
+ }
+ if (do_set) {
+ printk(TPACPI_NOTICE
+ "restoring fan level to 0x%02x\n",
+ saved_fan_level);
+ fan_set_level_safe(saved_fan_level);
+ }
+}
+
static int fan_read(char *p)
{
int len = 0;
@@ -6174,6 +6231,8 @@ static struct ibm_struct fan_driver_data = {
.read = fan_read,
.write = fan_write,
.exit = fan_exit,
+ .suspend = fan_suspend,
+ .resume = fan_resume,
};
/****************************************************************************
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 24c97d3d16b..3d067c35185 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -92,18 +92,17 @@ static void mmc_blk_put(struct mmc_blk_data *md)
mutex_unlock(&open_lock);
}
-static int mmc_blk_open(struct inode *inode, struct file *filp)
+static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
{
- struct mmc_blk_data *md;
+ struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
int ret = -ENXIO;
- md = mmc_blk_get(inode->i_bdev->bd_disk);
if (md) {
if (md->usage == 2)
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
ret = 0;
- if ((filp->f_mode & FMODE_WRITE) && md->read_only) {
+ if ((mode & FMODE_WRITE) && md->read_only) {
mmc_blk_put(md);
ret = -EROFS;
}
@@ -112,9 +111,9 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
return ret;
}
-static int mmc_blk_release(struct inode *inode, struct file *filp)
+static int mmc_blk_release(struct gendisk *disk, fmode_t mode)
{
- struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data;
+ struct mmc_blk_data *md = disk->private_data;
mmc_blk_put(md);
return 0;
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 406989e992b..7a72e75d5c6 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -132,6 +132,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
blk_queue_prep_rq(mq->queue, mmc_prep_request);
blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL);
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
#ifdef CONFIG_MMC_BLOCK_BOUNCE
if (host->max_hw_segs == 1) {
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index ae16d845d74..3b2085b5776 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -3,6 +3,9 @@
*
* Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
*
+ * Current driver maintained by Ben Dooks and Simtec Electronics
+ * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.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.
@@ -13,6 +16,7 @@
#include <linux/clk.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
+#include <linux/cpufreq.h>
#include <linux/irq.h>
#include <linux/io.h>
@@ -39,9 +43,9 @@ enum dbg_channels {
dbg_conf = (1 << 8),
};
-static const int dbgmap_err = dbg_err | dbg_fail;
+static const int dbgmap_err = dbg_fail;
static const int dbgmap_info = dbg_info | dbg_conf;
-static const int dbgmap_debug = dbg_debug;
+static const int dbgmap_debug = dbg_err | dbg_debug;
#define dbg(host, channels, args...) \
do { \
@@ -189,7 +193,7 @@ static inline void clear_imask(struct s3cmci_host *host)
}
static inline int get_data_buffer(struct s3cmci_host *host,
- u32 *words, u32 **pointer)
+ u32 *bytes, u32 **pointer)
{
struct scatterlist *sg;
@@ -206,7 +210,7 @@ static inline int get_data_buffer(struct s3cmci_host *host,
}
sg = &host->mrq->data->sg[host->pio_sgptr];
- *words = sg->length >> 2;
+ *bytes = sg->length;
*pointer = sg_virt(sg);
host->pio_sgptr++;
@@ -222,7 +226,7 @@ static inline u32 fifo_count(struct s3cmci_host *host)
u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
fifostat &= S3C2410_SDIFSTA_COUNTMASK;
- return fifostat >> 2;
+ return fifostat;
}
static inline u32 fifo_free(struct s3cmci_host *host)
@@ -230,13 +234,15 @@ static inline u32 fifo_free(struct s3cmci_host *host)
u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
fifostat &= S3C2410_SDIFSTA_COUNTMASK;
- return (63 - fifostat) >> 2;
+ return 63 - fifostat;
}
static void do_pio_read(struct s3cmci_host *host)
{
int res;
u32 fifo;
+ u32 *ptr;
+ u32 fifo_words;
void __iomem *from_ptr;
/* write real prescaler to host, it might be set slow to fix */
@@ -245,8 +251,8 @@ static void do_pio_read(struct s3cmci_host *host)
from_ptr = host->base + host->sdidata;
while ((fifo = fifo_count(host))) {
- if (!host->pio_words) {
- res = get_data_buffer(host, &host->pio_words,
+ if (!host->pio_bytes) {
+ res = get_data_buffer(host, &host->pio_bytes,
&host->pio_ptr);
if (res) {
host->pio_active = XFER_NONE;
@@ -259,26 +265,47 @@ static void do_pio_read(struct s3cmci_host *host)
dbg(host, dbg_pio,
"pio_read(): new target: [%i]@[%p]\n",
- host->pio_words, host->pio_ptr);
+ host->pio_bytes, host->pio_ptr);
}
dbg(host, dbg_pio,
"pio_read(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
- fifo, host->pio_words,
+ fifo, host->pio_bytes,
readl(host->base + S3C2410_SDIDCNT));
- if (fifo > host->pio_words)
- fifo = host->pio_words;
+ /* If we have reached the end of the block, we can
+ * read a word and get 1 to 3 bytes. If we in the
+ * middle of the block, we have to read full words,
+ * otherwise we will write garbage, so round down to
+ * an even multiple of 4. */
+ if (fifo >= host->pio_bytes)
+ fifo = host->pio_bytes;
+ else
+ fifo -= fifo & 3;
- host->pio_words -= fifo;
+ host->pio_bytes -= fifo;
host->pio_count += fifo;
- while (fifo--)
- *(host->pio_ptr++) = readl(from_ptr);
+ fifo_words = fifo >> 2;
+ ptr = host->pio_ptr;
+ while (fifo_words--)
+ *ptr++ = readl(from_ptr);
+ host->pio_ptr = ptr;
+
+ if (fifo & 3) {
+ u32 n = fifo & 3;
+ u32 data = readl(from_ptr);
+ u8 *p = (u8 *)host->pio_ptr;
+
+ while (n--) {
+ *p++ = data;
+ data >>= 8;
+ }
+ }
}
- if (!host->pio_words) {
- res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
+ if (!host->pio_bytes) {
+ res = get_data_buffer(host, &host->pio_bytes, &host->pio_ptr);
if (res) {
dbg(host, dbg_pio,
"pio_read(): complete (no more buffers).\n");
@@ -298,12 +325,13 @@ static void do_pio_write(struct s3cmci_host *host)
void __iomem *to_ptr;
int res;
u32 fifo;
+ u32 *ptr;
to_ptr = host->base + host->sdidata;
while ((fifo = fifo_free(host))) {
- if (!host->pio_words) {
- res = get_data_buffer(host, &host->pio_words,
+ if (!host->pio_bytes) {
+ res = get_data_buffer(host, &host->pio_bytes,
&host->pio_ptr);
if (res) {
dbg(host, dbg_pio,
@@ -315,18 +343,27 @@ static void do_pio_write(struct s3cmci_host *host)
dbg(host, dbg_pio,
"pio_write(): new source: [%i]@[%p]\n",
- host->pio_words, host->pio_ptr);
+ host->pio_bytes, host->pio_ptr);
}
- if (fifo > host->pio_words)
- fifo = host->pio_words;
+ /* If we have reached the end of the block, we have to
+ * write exactly the remaining number of bytes. If we
+ * in the middle of the block, we have to write full
+ * words, so round down to an even multiple of 4. */
+ if (fifo >= host->pio_bytes)
+ fifo = host->pio_bytes;
+ else
+ fifo -= fifo & 3;
- host->pio_words -= fifo;
+ host->pio_bytes -= fifo;
host->pio_count += fifo;
+ fifo = (fifo + 3) >> 2;
+ ptr = host->pio_ptr;
while (fifo--)
- writel(*(host->pio_ptr++), to_ptr);
+ writel(*ptr++, to_ptr);
+ host->pio_ptr = ptr;
}
enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
@@ -349,9 +386,9 @@ static void pio_tasklet(unsigned long data)
clear_imask(host);
if (host->pio_active != XFER_NONE) {
dbg(host, dbg_err, "unfinished %s "
- "- pio_count:[%u] pio_words:[%u]\n",
+ "- pio_count:[%u] pio_bytes:[%u]\n",
(host->pio_active == XFER_READ) ? "read" : "write",
- host->pio_count, host->pio_words);
+ host->pio_count, host->pio_bytes);
if (host->mrq->data)
host->mrq->data->error = -EINVAL;
@@ -812,11 +849,10 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
/* We cannot deal with unaligned blocks with more than
* one block being transfered. */
- if (data->blocks > 1)
+ if (data->blocks > 1) {
+ pr_warning("%s: can't do non-word sized block transfers (blksz %d)\n", __func__, data->blksz);
return -EINVAL;
-
- /* No support yet for non-word block transfers. */
- return -EINVAL;
+ }
}
while (readl(host->base + S3C2410_SDIDSTA) &
@@ -896,7 +932,7 @@ static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
host->pio_sgptr = 0;
- host->pio_words = 0;
+ host->pio_bytes = 0;
host->pio_count = 0;
host->pio_active = rw ? XFER_WRITE : XFER_READ;
@@ -1033,10 +1069,33 @@ static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
s3cmci_send_request(mmc);
}
+static void s3cmci_set_clk(struct s3cmci_host *host, struct mmc_ios *ios)
+{
+ u32 mci_psc;
+
+ /* Set clock */
+ for (mci_psc = 0; mci_psc < 255; mci_psc++) {
+ host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
+
+ if (host->real_rate <= ios->clock)
+ break;
+ }
+
+ if (mci_psc > 255)
+ mci_psc = 255;
+
+ host->prescaler = mci_psc;
+ writel(host->prescaler, host->base + S3C2410_SDIPRE);
+
+ /* If requested clock is 0, real_rate will be 0, too */
+ if (ios->clock == 0)
+ host->real_rate = 0;
+}
+
static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct s3cmci_host *host = mmc_priv(mmc);
- u32 mci_psc, mci_con;
+ u32 mci_con;
/* Set the power state */
@@ -1074,23 +1133,7 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
}
- /* Set clock */
- for (mci_psc = 0; mci_psc < 255; mci_psc++) {
- host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
-
- if (host->real_rate <= ios->clock)
- break;
- }
-
- if (mci_psc > 255)
- mci_psc = 255;
-
- host->prescaler = mci_psc;
- writel(host->prescaler, host->base + S3C2410_SDIPRE);
-
- /* If requested clock is 0, real_rate will be 0, too */
- if (ios->clock == 0)
- host->real_rate = 0;
+ s3cmci_set_clk(host, ios);
/* Set CLOCK_ENABLE */
if (ios->clock)
@@ -1148,6 +1191,61 @@ static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
* checks. Any zero fields to ensure reaonable defaults are picked. */
};
+#ifdef CONFIG_CPU_FREQ
+
+static int s3cmci_cpufreq_transition(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct s3cmci_host *host;
+ struct mmc_host *mmc;
+ unsigned long newclk;
+ unsigned long flags;
+
+ host = container_of(nb, struct s3cmci_host, freq_transition);
+ newclk = clk_get_rate(host->clk);
+ mmc = host->mmc;
+
+ if ((val == CPUFREQ_PRECHANGE && newclk > host->clk_rate) ||
+ (val == CPUFREQ_POSTCHANGE && newclk < host->clk_rate)) {
+ spin_lock_irqsave(&mmc->lock, flags);
+
+ host->clk_rate = newclk;
+
+ if (mmc->ios.power_mode != MMC_POWER_OFF &&
+ mmc->ios.clock != 0)
+ s3cmci_set_clk(host, &mmc->ios);
+
+ spin_unlock_irqrestore(&mmc->lock, flags);
+ }
+
+ return 0;
+}
+
+static inline int s3cmci_cpufreq_register(struct s3cmci_host *host)
+{
+ host->freq_transition.notifier_call = s3cmci_cpufreq_transition;
+
+ return cpufreq_register_notifier(&host->freq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void s3cmci_cpufreq_deregister(struct s3cmci_host *host)
+{
+ cpufreq_unregister_notifier(&host->freq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+static inline int s3cmci_cpufreq_register(struct s3cmci_host *host)
+{
+ return 0;
+}
+
+static inline void s3cmci_cpufreq_deregister(struct s3cmci_host *host)
+{
+}
+#endif
+
static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
{
struct s3cmci_host *host;
@@ -1298,10 +1396,16 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
(host->is2440?"2440":""),
host->base, host->irq, host->irq_cd, host->dma);
+ ret = s3cmci_cpufreq_register(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register cpufreq\n");
+ goto free_dmabuf;
+ }
+
ret = mmc_add_host(mmc);
if (ret) {
dev_err(&pdev->dev, "failed to add mmc host.\n");
- goto free_dmabuf;
+ goto free_cpufreq;
}
platform_set_drvdata(pdev, mmc);
@@ -1309,6 +1413,9 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
return 0;
+ free_cpufreq:
+ s3cmci_cpufreq_deregister(host);
+
free_dmabuf:
clk_disable(host->clk);
@@ -1342,6 +1449,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
+ s3cmci_cpufreq_deregister(host);
mmc_remove_host(mmc);
clk_disable(host->clk);
}
@@ -1455,7 +1563,7 @@ module_exit(s3cmci_exit);
MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>");
+MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
MODULE_ALIAS("platform:s3c2410-sdi");
MODULE_ALIAS("platform:s3c2412-sdi");
MODULE_ALIAS("platform:s3c2440-sdi");
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index 37d9c60010c..ca1ba3d58cf 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -51,7 +51,7 @@ struct s3cmci_host {
int dma_complete;
u32 pio_sgptr;
- u32 pio_words;
+ u32 pio_bytes;
u32 pio_count;
u32 *pio_ptr;
#define XFER_NONE 0
@@ -67,4 +67,8 @@ struct s3cmci_host {
unsigned int ccnt, dcnt;
struct tasklet_struct pio_tasklet;
+
+#ifdef CONFIG_CPU_FREQ
+ struct notifier_block freq_transition;
+#endif
};
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 14f11f8b9e5..a90d50c2c3e 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -172,6 +172,11 @@ config MTD_CHAR
memory chips, and also use ioctl() to obtain information about
the device, or to erase parts of it.
+config HAVE_MTD_OTP
+ bool
+ help
+ Enable access to OTP regions using MTD_CHAR.
+
config MTD_BLKDEVS
tristate "Common interface to block layer for MTD 'translation layers'"
depends on BLOCK
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 479d32b57a1..9408099eec4 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -6,6 +6,7 @@ menu "RAM/ROM/Flash chip drivers"
config MTD_CFI
tristate "Detect flash chips by Common Flash Interface (CFI) probe"
select MTD_GEN_PROBE
+ select MTD_CFI_UTIL
help
The Common Flash Interface specification was developed by Intel,
AMD and other flash manufactures that provides a universal method
@@ -154,6 +155,7 @@ config MTD_CFI_I8
config MTD_OTP
bool "Protection Registers aka one-time programmable (OTP) bits"
depends on MTD_CFI_ADV_OPTIONS
+ select HAVE_MTD_OTP
default n
help
This enables support for reading, writing and locking so called
@@ -187,7 +189,7 @@ config MTD_CFI_INTELEXT
StrataFlash and other parts.
config MTD_CFI_AMDSTD
- tristate "Support for AMD/Fujitsu flash chips"
+ tristate "Support for AMD/Fujitsu/Spansion flash chips"
depends on MTD_GEN_PROBE
select MTD_CFI_UTIL
help
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 5f1b472137a..c93a8be5d5f 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -478,6 +478,28 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
else
cfi->chips[i].erase_time = 2000000;
+ if (cfi->cfiq->WordWriteTimeoutTyp &&
+ cfi->cfiq->WordWriteTimeoutMax)
+ cfi->chips[i].word_write_time_max =
+ 1<<(cfi->cfiq->WordWriteTimeoutTyp +
+ cfi->cfiq->WordWriteTimeoutMax);
+ else
+ cfi->chips[i].word_write_time_max = 50000 * 8;
+
+ if (cfi->cfiq->BufWriteTimeoutTyp &&
+ cfi->cfiq->BufWriteTimeoutMax)
+ cfi->chips[i].buffer_write_time_max =
+ 1<<(cfi->cfiq->BufWriteTimeoutTyp +
+ cfi->cfiq->BufWriteTimeoutMax);
+
+ if (cfi->cfiq->BlockEraseTimeoutTyp &&
+ cfi->cfiq->BlockEraseTimeoutMax)
+ cfi->chips[i].erase_time_max =
+ 1000<<(cfi->cfiq->BlockEraseTimeoutTyp +
+ cfi->cfiq->BlockEraseTimeoutMax);
+ else
+ cfi->chips[i].erase_time_max = 2000000 * 8;
+
cfi->chips[i].ref_point_counter = 0;
init_waitqueue_head(&(cfi->chips[i].wq));
}
@@ -703,6 +725,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
unsigned long timeo = jiffies + HZ;
+ /* Prevent setting state FL_SYNCING for chip in suspended state. */
+ if (mode == FL_SYNCING && chip->oldstate != FL_READY)
+ goto sleep;
+
switch (chip->state) {
case FL_STATUS:
@@ -808,8 +834,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
DECLARE_WAITQUEUE(wait, current);
retry:
- if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
- || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
+ if (chip->priv &&
+ (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE
+ || mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) {
/*
* OK. We have possibility for contention on the write/erase
* operations which are global to the real chip and not per
@@ -859,6 +886,14 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
return ret;
}
spin_lock(&shared->lock);
+
+ /* We should not own chip if it is already
+ * in FL_SYNCING state. Put contender and retry. */
+ if (chip->state == FL_SYNCING) {
+ put_chip(map, contender, contender->start);
+ spin_unlock(contender->mutex);
+ goto retry;
+ }
spin_unlock(contender->mutex);
}
@@ -1012,7 +1047,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
static int __xipram xip_wait_for_operation(
struct map_info *map, struct flchip *chip,
- unsigned long adr, unsigned int chip_op_time )
+ unsigned long adr, unsigned int chip_op_time_max)
{
struct cfi_private *cfi = map->fldrv_priv;
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
@@ -1021,7 +1056,7 @@ static int __xipram xip_wait_for_operation(
flstate_t oldstate, newstate;
start = xip_currtime();
- usec = chip_op_time * 8;
+ usec = chip_op_time_max;
if (usec == 0)
usec = 500000;
done = 0;
@@ -1131,8 +1166,8 @@ static int __xipram xip_wait_for_operation(
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
INVALIDATE_CACHED_RANGE(map, from, size)
-#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
- xip_wait_for_operation(map, chip, cmd_adr, usec)
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec, usec_max) \
+ xip_wait_for_operation(map, chip, cmd_adr, usec_max)
#else
@@ -1144,7 +1179,7 @@ static int __xipram xip_wait_for_operation(
static int inval_cache_and_wait_for_operation(
struct map_info *map, struct flchip *chip,
unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
- unsigned int chip_op_time)
+ unsigned int chip_op_time, unsigned int chip_op_time_max)
{
struct cfi_private *cfi = map->fldrv_priv;
map_word status, status_OK = CMD(0x80);
@@ -1156,8 +1191,7 @@ static int inval_cache_and_wait_for_operation(
INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
spin_lock(chip->mutex);
- /* set our timeout to 8 times the expected delay */
- timeo = chip_op_time * 8;
+ timeo = chip_op_time_max;
if (!timeo)
timeo = 500000;
reset_timeo = timeo;
@@ -1217,8 +1251,8 @@ static int inval_cache_and_wait_for_operation(
#endif
-#define WAIT_TIMEOUT(map, chip, adr, udelay) \
- INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
+#define WAIT_TIMEOUT(map, chip, adr, udelay, udelay_max) \
+ INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay, udelay_max);
static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
@@ -1452,7 +1486,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
adr, map_bankwidth(map),
- chip->word_write_time);
+ chip->word_write_time,
+ chip->word_write_time_max);
if (ret) {
xip_enable(map, chip, adr);
printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
@@ -1623,7 +1658,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
chip->state = FL_WRITING_TO_BUFFER;
map_write(map, write_cmd, cmd_adr);
- ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0);
+ ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0, 0);
if (ret) {
/* Argh. Not ready for write to buffer */
map_word Xstatus = map_read(map, cmd_adr);
@@ -1640,7 +1675,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
/* Figure out the number of words to write */
word_gap = (-adr & (map_bankwidth(map)-1));
- words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);
+ words = DIV_ROUND_UP(len - word_gap, map_bankwidth(map));
if (!word_gap) {
words--;
} else {
@@ -1692,7 +1727,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
initial_adr, initial_len,
- chip->buffer_write_time);
+ chip->buffer_write_time,
+ chip->buffer_write_time_max);
if (ret) {
map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS;
@@ -1827,7 +1863,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
adr, len,
- chip->erase_time);
+ chip->erase_time,
+ chip->erase_time_max);
if (ret) {
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
@@ -2006,7 +2043,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
*/
udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0;
- ret = WAIT_TIMEOUT(map, chip, adr, udelay);
+ ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100);
if (ret) {
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index a972cc6be43..3e6f5d8609e 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -13,6 +13,8 @@
* XIP support hooks by Vitaly Wool (based on code for Intel flash
* by Nicolas Pitre)
*
+ * 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0
+ *
* Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
*
* This code is GPL
@@ -43,6 +45,7 @@
#define MANUFACTURER_AMD 0x0001
#define MANUFACTURER_ATMEL 0x001F
+#define MANUFACTURER_MACRONIX 0x00C2
#define MANUFACTURER_SST 0x00BF
#define SST49LF004B 0x0060
#define SST49LF040B 0x0050
@@ -144,12 +147,44 @@ static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
if (((major << 8) | minor) < 0x3131) {
/* CFI version 1.0 => don't trust bootloc */
+
+ DEBUG(MTD_DEBUG_LEVEL1,
+ "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
+ map->name, cfi->mfr, cfi->id);
+
+ /* AFAICS all 29LV400 with a bottom boot block have a device ID
+ * of 0x22BA in 16-bit mode and 0xBA in 8-bit mode.
+ * These were badly detected as they have the 0x80 bit set
+ * so treat them as a special case.
+ */
+ if (((cfi->id == 0xBA) || (cfi->id == 0x22BA)) &&
+
+ /* Macronix added CFI to their 2nd generation
+ * MX29LV400C B/T but AFAICS no other 29LV400 (AMD,
+ * Fujitsu, Spansion, EON, ESI and older Macronix)
+ * has CFI.
+ *
+ * Therefore also check the manufacturer.
+ * This reduces the risk of false detection due to
+ * the 8-bit device ID.
+ */
+ (cfi->mfr == MANUFACTURER_MACRONIX)) {
+ DEBUG(MTD_DEBUG_LEVEL1,
+ "%s: Macronix MX29LV400C with bottom boot block"
+ " detected\n", map->name);
+ extp->TopBottom = 2; /* bottom boot */
+ } else
if (cfi->id & 0x80) {
printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
extp->TopBottom = 3; /* top boot */
} else {
extp->TopBottom = 2; /* bottom boot */
}
+
+ DEBUG(MTD_DEBUG_LEVEL1,
+ "%s: AMD CFI PRI V%c.%c has no boot block field;"
+ " deduced %s from Device ID\n", map->name, major, minor,
+ extp->TopBottom == 2 ? "bottom" : "top");
}
}
#endif
@@ -178,10 +213,18 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
if (atmel_pri.Features & 0x02)
extp->EraseSuspend = 2;
- if (atmel_pri.BottomBoot)
- extp->TopBottom = 2;
- else
- extp->TopBottom = 3;
+ /* Some chips got it backwards... */
+ if (cfi->id == AT49BV6416) {
+ if (atmel_pri.BottomBoot)
+ extp->TopBottom = 3;
+ else
+ extp->TopBottom = 2;
+ } else {
+ if (atmel_pri.BottomBoot)
+ extp->TopBottom = 2;
+ else
+ extp->TopBottom = 3;
+ }
/* burst write mode not supported */
cfi->cfiq->BufWriteTimeoutTyp = 0;
@@ -243,6 +286,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
#ifdef AMD_BOOTLOC_BUG
{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
+ { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL },
#endif
{ CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
{ CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index c418e92e1d9..e63e6749429 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -44,17 +44,14 @@ do { \
#define xip_enable(base, map, cfi) \
do { \
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
- cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
+ cfi_qry_mode_off(base, map, cfi); \
xip_allowed(base, map); \
} while (0)
#define xip_disable_qry(base, map, cfi) \
do { \
xip_disable(); \
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
- cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); \
+ cfi_qry_mode_on(base, map, cfi); \
} while (0)
#else
@@ -70,32 +67,6 @@ do { \
in: interleave,type,mode
ret: table index, <0 for error
*/
-static int __xipram qry_present(struct map_info *map, __u32 base,
- struct cfi_private *cfi)
-{
- int osf = cfi->interleave * cfi->device_type; // scale factor
- map_word val[3];
- map_word qry[3];
-
- qry[0] = cfi_build_cmd('Q', map, cfi);
- qry[1] = cfi_build_cmd('R', map, cfi);
- qry[2] = cfi_build_cmd('Y', map, cfi);
-
- val[0] = map_read(map, base + osf*0x10);
- val[1] = map_read(map, base + osf*0x11);
- val[2] = map_read(map, base + osf*0x12);
-
- if (!map_word_equal(map, qry[0], val[0]))
- return 0;
-
- if (!map_word_equal(map, qry[1], val[1]))
- return 0;
-
- if (!map_word_equal(map, qry[2], val[2]))
- return 0;
-
- return 1; // "QRY" found
-}
static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
unsigned long *chip_map, struct cfi_private *cfi)
@@ -116,11 +87,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
}
xip_disable();
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
- if (!qry_present(map,base,cfi)) {
+ if (!cfi_qry_mode_on(base, map, cfi)) {
xip_enable(base, map, cfi);
return 0;
}
@@ -141,14 +108,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
start = i << cfi->chipshift;
/* This chip should be in read mode if it's one
we've already touched. */
- if (qry_present(map, start, cfi)) {
+ if (cfi_qry_present(map, start, cfi)) {
/* Eep. This chip also had the QRY marker.
* Is it an alias for the new one? */
- cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
+ cfi_qry_mode_off(start, map, cfi);
/* If the QRY marker goes away, it's an alias */
- if (!qry_present(map, start, cfi)) {
+ if (!cfi_qry_present(map, start, cfi)) {
xip_allowed(base, map);
printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
map->name, base, start);
@@ -158,10 +124,9 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
* unfortunate. Stick the new chip in read mode
* too and if it's the same, assume it's an alias. */
/* FIXME: Use other modes to do a proper check */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
+ cfi_qry_mode_off(base, map, cfi);
- if (qry_present(map, base, cfi)) {
+ if (cfi_qry_present(map, base, cfi)) {
xip_allowed(base, map);
printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
map->name, base, start);
@@ -176,8 +141,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
cfi->numchips++;
/* Put it back into Read Mode */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
@@ -237,9 +201,7 @@ static int __xipram cfi_chip_setup(struct map_info *map,
cfi_read_query(map, base + 0xf * ofs_factor);
/* Put it back into Read Mode */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
- /* ... even if it's an Intel chip */
- cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
/* Do any necessary byteswapping */
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index 0ee45701801..34d40e25d31 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -24,6 +24,66 @@
#include <linux/mtd/cfi.h>
#include <linux/mtd/compatmac.h>
+int __xipram cfi_qry_present(struct map_info *map, __u32 base,
+ struct cfi_private *cfi)
+{
+ int osf = cfi->interleave * cfi->device_type; /* scale factor */
+ map_word val[3];
+ map_word qry[3];
+
+ qry[0] = cfi_build_cmd('Q', map, cfi);
+ qry[1] = cfi_build_cmd('R', map, cfi);
+ qry[2] = cfi_build_cmd('Y', map, cfi);
+
+ val[0] = map_read(map, base + osf*0x10);
+ val[1] = map_read(map, base + osf*0x11);
+ val[2] = map_read(map, base + osf*0x12);
+
+ if (!map_word_equal(map, qry[0], val[0]))
+ return 0;
+
+ if (!map_word_equal(map, qry[1], val[1]))
+ return 0;
+
+ if (!map_word_equal(map, qry[2], val[2]))
+ return 0;
+
+ return 1; /* "QRY" found */
+}
+EXPORT_SYMBOL_GPL(cfi_qry_present);
+
+int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
+ struct cfi_private *cfi)
+{
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+ if (cfi_qry_present(map, base, cfi))
+ return 1;
+ /* QRY not found probably we deal with some odd CFI chips */
+ /* Some revisions of some old Intel chips? */
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+ if (cfi_qry_present(map, base, cfi))
+ return 1;
+ /* ST M29DW chips */
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
+ if (cfi_qry_present(map, base, cfi))
+ return 1;
+ /* QRY not found */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
+
+void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
+ struct cfi_private *cfi)
+{
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+}
+EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
+
struct cfi_extquery *
__xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
{
@@ -48,8 +108,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
#endif
/* Switch it into Query Mode */
- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
+ cfi_qry_mode_on(base, map, cfi);
/* Read in the Extended Query Table */
for (i=0; i<size; i++) {
((unsigned char *)extp)[i] =
@@ -57,8 +116,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
}
/* Make sure it returns to read mode */
- cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL);
+ cfi_qry_mode_off(base, map, cfi);
#ifdef CONFIG_MTD_XIP
(void) map_read(map, base);
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index f061885b281..e2dc96441e0 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -111,7 +111,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
max_chips = 1;
}
- mapsize = sizeof(long) * ( (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG );
+ mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG);
chip_map = kzalloc(mapsize, GFP_KERNEL);
if (!chip_map) {
printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index 71bc07f149b..50a340388e7 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -7,6 +7,7 @@
*
* mtdparts=<mtddef>[;<mtddef]
* <mtddef> := <mtd-id>:<partdef>[,<partdef>]
+ * where <mtd-id> is the name from the "cat /proc/mtd" command
* <partdef> := <size>[@offset][<name>][ro][lk]
* <mtd-id> := unique name used in mapping driver/device (mtd->name)
* <size> := standard linux memsize OR "-" to denote all remaining space
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 9c613f06623..6fde0a2e356 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -59,6 +59,27 @@ config MTD_DATAFLASH
Sometimes DataFlash chips are packaged inside MMC-format
cards; at this writing, the MMC stack won't handle those.
+config MTD_DATAFLASH_WRITE_VERIFY
+ bool "Verify DataFlash page writes"
+ depends on MTD_DATAFLASH
+ help
+ This adds an extra check when data is written to the flash.
+ It may help if you are verifying chip setup (timings etc) on
+ your board. There is a rare possibility that even though the
+ device thinks the write was successful, a bit could have been
+ flipped accidentally due to device wear or something else.
+
+config MTD_DATAFLASH_OTP
+ bool "DataFlash OTP support (Security Register)"
+ depends on MTD_DATAFLASH
+ select HAVE_MTD_OTP
+ help
+ Newer DataFlash chips (revisions C and D) support 128 bytes of
+ one-time-programmable (OTP) data. The first half may be written
+ (once) with up to 64 bytes of data, such as a serial number or
+ other key product data. The second half is programmed with a
+ unique-to-each-chip bit pattern at the factory.
+
config MTD_M25P80
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
depends on SPI_MASTER && EXPERIMENTAL
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 91fbba76763..8c295f40d2a 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -224,7 +224,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
if (dev->blkdev) {
invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
0, -1);
- close_bdev_excl(dev->blkdev);
+ close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
}
kfree(dev);
@@ -246,7 +246,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
return NULL;
/* Get a handle on the device */
- bdev = open_bdev_excl(devname, O_RDWR, NULL);
+ bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
#ifndef MODULE
if (IS_ERR(bdev)) {
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index b35c3333e21..76a76751da3 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -39,6 +39,7 @@
#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
+#define OPCODE_BE 0xc7 /* Erase whole flash block */
#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
#define OPCODE_RDID 0x9f /* Read JEDEC ID */
@@ -161,6 +162,31 @@ static int wait_till_ready(struct m25p *flash)
return 1;
}
+/*
+ * Erase the whole flash memory
+ *
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int erase_block(struct m25p *flash)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
+ flash->spi->dev.bus_id, __func__,
+ flash->mtd.size / 1024);
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash))
+ return 1;
+
+ /* Send write enable, then erase commands. */
+ write_enable(flash);
+
+ /* Set up command buffer. */
+ flash->command[0] = OPCODE_BE;
+
+ spi_write(flash->spi, flash->command, 1);
+
+ return 0;
+}
/*
* Erase one sector of flash memory at offset ``offset'' which is any
@@ -229,15 +255,21 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
*/
/* now erase those sectors */
- while (len) {
- if (erase_sector(flash, addr)) {
- instr->state = MTD_ERASE_FAILED;
- mutex_unlock(&flash->lock);
- return -EIO;
- }
+ if (len == flash->mtd.size && erase_block(flash)) {
+ instr->state = MTD_ERASE_FAILED;
+ mutex_unlock(&flash->lock);
+ return -EIO;
+ } else {
+ while (len) {
+ if (erase_sector(flash, addr)) {
+ instr->state = MTD_ERASE_FAILED;
+ mutex_unlock(&flash->lock);
+ return -EIO;
+ }
- addr += mtd->erasesize;
- len -= mtd->erasesize;
+ addr += mtd->erasesize;
+ len -= mtd->erasesize;
+ }
}
mutex_unlock(&flash->lock);
@@ -437,6 +469,7 @@ struct flash_info {
* then a two byte device id.
*/
u32 jedec_id;
+ u16 ext_id;
/* The size listed here is what works with OPCODE_SE, which isn't
* necessarily called a "sector" by the vendor.
@@ -456,72 +489,75 @@ struct flash_info {
static struct flash_info __devinitdata m25p_data [] = {
/* Atmel -- some are (confusingly) marketed as "DataFlash" */
- { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
- { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
+ { "at25fs010", 0x1f6601, 0, 32 * 1024, 4, SECT_4K, },
+ { "at25fs040", 0x1f6604, 0, 64 * 1024, 8, SECT_4K, },
- { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
- { "at25df641", 0x1f4800, 64 * 1024, 128, SECT_4K, },
+ { "at25df041a", 0x1f4401, 0, 64 * 1024, 8, SECT_4K, },
+ { "at25df641", 0x1f4800, 0, 64 * 1024, 128, SECT_4K, },
- { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
- { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
- { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
- { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
+ { "at26f004", 0x1f0400, 0, 64 * 1024, 8, SECT_4K, },
+ { "at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K, },
+ { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
+ { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
- { "s25sl004a", 0x010212, 64 * 1024, 8, },
- { "s25sl008a", 0x010213, 64 * 1024, 16, },
- { "s25sl016a", 0x010214, 64 * 1024, 32, },
- { "s25sl032a", 0x010215, 64 * 1024, 64, },
- { "s25sl064a", 0x010216, 64 * 1024, 128, },
+ { "s25sl004a", 0x010212, 0, 64 * 1024, 8, },
+ { "s25sl008a", 0x010213, 0, 64 * 1024, 16, },
+ { "s25sl016a", 0x010214, 0, 64 * 1024, 32, },
+ { "s25sl032a", 0x010215, 0, 64 * 1024, 64, },
+ { "s25sl064a", 0x010216, 0, 64 * 1024, 128, },
+ { "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, },
+ { "s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, },
/* SST -- large erase sizes are "overlays", "sectors" are 4K */
- { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
- { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
- { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
- { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
+ { "sst25vf040b", 0xbf258d, 0, 64 * 1024, 8, SECT_4K, },
+ { "sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K, },
+ { "sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K, },
+ { "sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K, },
/* ST Microelectronics -- newer production may have feature updates */
- { "m25p05", 0x202010, 32 * 1024, 2, },
- { "m25p10", 0x202011, 32 * 1024, 4, },
- { "m25p20", 0x202012, 64 * 1024, 4, },
- { "m25p40", 0x202013, 64 * 1024, 8, },
- { "m25p80", 0, 64 * 1024, 16, },
- { "m25p16", 0x202015, 64 * 1024, 32, },
- { "m25p32", 0x202016, 64 * 1024, 64, },
- { "m25p64", 0x202017, 64 * 1024, 128, },
- { "m25p128", 0x202018, 256 * 1024, 64, },
-
- { "m45pe80", 0x204014, 64 * 1024, 16, },
- { "m45pe16", 0x204015, 64 * 1024, 32, },
-
- { "m25pe80", 0x208014, 64 * 1024, 16, },
- { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
+ { "m25p05", 0x202010, 0, 32 * 1024, 2, },
+ { "m25p10", 0x202011, 0, 32 * 1024, 4, },
+ { "m25p20", 0x202012, 0, 64 * 1024, 4, },
+ { "m25p40", 0x202013, 0, 64 * 1024, 8, },
+ { "m25p80", 0, 0, 64 * 1024, 16, },
+ { "m25p16", 0x202015, 0, 64 * 1024, 32, },
+ { "m25p32", 0x202016, 0, 64 * 1024, 64, },
+ { "m25p64", 0x202017, 0, 64 * 1024, 128, },
+ { "m25p128", 0x202018, 0, 256 * 1024, 64, },
+
+ { "m45pe80", 0x204014, 0, 64 * 1024, 16, },
+ { "m45pe16", 0x204015, 0, 64 * 1024, 32, },
+
+ { "m25pe80", 0x208014, 0, 64 * 1024, 16, },
+ { "m25pe16", 0x208015, 0, 64 * 1024, 32, SECT_4K, },
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
- { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
- { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
- { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
- { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
- { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
- { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
- { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
+ { "w25x10", 0xef3011, 0, 64 * 1024, 2, SECT_4K, },
+ { "w25x20", 0xef3012, 0, 64 * 1024, 4, SECT_4K, },
+ { "w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K, },
+ { "w25x80", 0xef3014, 0, 64 * 1024, 16, SECT_4K, },
+ { "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, },
+ { "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, },
+ { "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, },
};
static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
{
int tmp;
u8 code = OPCODE_RDID;
- u8 id[3];
+ u8 id[5];
u32 jedec;
+ u16 ext_jedec;
struct flash_info *info;
/* JEDEC also defines an optional "extended device information"
* string for after vendor-specific data, after the three bytes
* we use here. Supporting some chips might require using it.
*/
- tmp = spi_write_then_read(spi, &code, 1, id, 3);
+ tmp = spi_write_then_read(spi, &code, 1, id, 5);
if (tmp < 0) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
spi->dev.bus_id, tmp);
@@ -533,10 +569,14 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
jedec = jedec << 8;
jedec |= id[2];
+ ext_jedec = id[3] << 8 | id[4];
+
for (tmp = 0, info = m25p_data;
tmp < ARRAY_SIZE(m25p_data);
tmp++, info++) {
if (info->jedec_id == jedec)
+ if (ext_jedec != 0 && info->ext_id != ext_jedec)
+ continue;
return info;
}
dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 8bd0dea6885..6dd9aff8bb2 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -30,12 +30,10 @@
* doesn't (yet) use these for any kind of i/o overlap or prefetching.
*
* Sometimes DataFlash is packaged in MMC-format cards, although the
- * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash
+ * MMC stack can't (yet?) distinguish between MMC and DataFlash
* protocols during enumeration.
*/
-#define CONFIG_DATAFLASH_WRITE_VERIFY
-
/* reads can bypass the buffers */
#define OP_READ_CONTINUOUS 0xE8
#define OP_READ_PAGE 0xD2
@@ -80,7 +78,8 @@
*/
#define OP_READ_ID 0x9F
#define OP_READ_SECURITY 0x77
-#define OP_WRITE_SECURITY 0x9A /* OTP bits */
+#define OP_WRITE_SECURITY_REVC 0x9A
+#define OP_WRITE_SECURITY 0x9B /* revision D */
struct dataflash {
@@ -402,7 +401,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
(void) dataflash_waitready(priv->spi);
-#ifdef CONFIG_DATAFLASH_WRITE_VERIFY
+#ifdef CONFIG_MTD_DATAFLASH_VERIFY_WRITE
/* (3) Compare to Buffer1 */
addr = pageaddr << priv->page_offset;
@@ -431,7 +430,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
} else
status = 0;
-#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */
+#endif /* CONFIG_MTD_DATAFLASH_VERIFY_WRITE */
remaining = remaining - writelen;
pageaddr++;
@@ -451,16 +450,192 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
/* ......................................................................... */
+#ifdef CONFIG_MTD_DATAFLASH_OTP
+
+static int dataflash_get_otp_info(struct mtd_info *mtd,
+ struct otp_info *info, size_t len)
+{
+ /* Report both blocks as identical: bytes 0..64, locked.
+ * Unless the user block changed from all-ones, we can't
+ * tell whether it's still writable; so we assume it isn't.
+ */
+ info->start = 0;
+ info->length = 64;
+ info->locked = 1;
+ return sizeof(*info);
+}
+
+static ssize_t otp_read(struct spi_device *spi, unsigned base,
+ uint8_t *buf, loff_t off, size_t len)
+{
+ struct spi_message m;
+ size_t l;
+ uint8_t *scratch;
+ struct spi_transfer t;
+ int status;
+
+ if (off > 64)
+ return -EINVAL;
+
+ if ((off + len) > 64)
+ len = 64 - off;
+ if (len == 0)
+ return len;
+
+ spi_message_init(&m);
+
+ l = 4 + base + off + len;
+ scratch = kzalloc(l, GFP_KERNEL);
+ if (!scratch)
+ return -ENOMEM;
+
+ /* OUT: OP_READ_SECURITY, 3 don't-care bytes, zeroes
+ * IN: ignore 4 bytes, data bytes 0..N (max 127)
+ */
+ scratch[0] = OP_READ_SECURITY;
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = scratch;
+ t.rx_buf = scratch;
+ t.len = l;
+ spi_message_add_tail(&t, &m);
+
+ dataflash_waitready(spi);
+
+ status = spi_sync(spi, &m);
+ if (status >= 0) {
+ memcpy(buf, scratch + 4 + base + off, len);
+ status = len;
+ }
+
+ kfree(scratch);
+ return status;
+}
+
+static int dataflash_read_fact_otp(struct mtd_info *mtd,
+ loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ int status;
+
+ /* 64 bytes, from 0..63 ... start at 64 on-chip */
+ mutex_lock(&priv->lock);
+ status = otp_read(priv->spi, 64, buf, from, len);
+ mutex_unlock(&priv->lock);
+
+ if (status < 0)
+ return status;
+ *retlen = status;
+ return 0;
+}
+
+static int dataflash_read_user_otp(struct mtd_info *mtd,
+ loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ int status;
+
+ /* 64 bytes, from 0..63 ... start at 0 on-chip */
+ mutex_lock(&priv->lock);
+ status = otp_read(priv->spi, 0, buf, from, len);
+ mutex_unlock(&priv->lock);
+
+ if (status < 0)
+ return status;
+ *retlen = status;
+ return 0;
+}
+
+static int dataflash_write_user_otp(struct mtd_info *mtd,
+ loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ struct spi_message m;
+ const size_t l = 4 + 64;
+ uint8_t *scratch;
+ struct spi_transfer t;
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ int status;
+
+ if (len > 64)
+ return -EINVAL;
+
+ /* Strictly speaking, we *could* truncate the write ... but
+ * let's not do that for the only write that's ever possible.
+ */
+ if ((from + len) > 64)
+ return -EINVAL;
+
+ /* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes
+ * IN: ignore all
+ */
+ scratch = kzalloc(l, GFP_KERNEL);
+ if (!scratch)
+ return -ENOMEM;
+ scratch[0] = OP_WRITE_SECURITY;
+ memcpy(scratch + 4 + from, buf, len);
+
+ spi_message_init(&m);
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = scratch;
+ t.len = l;
+ spi_message_add_tail(&t, &m);
+
+ /* Write the OTP bits, if they've not yet been written.
+ * This modifies SRAM buffer1.
+ */
+ mutex_lock(&priv->lock);
+ dataflash_waitready(priv->spi);
+ status = spi_sync(priv->spi, &m);
+ mutex_unlock(&priv->lock);
+
+ kfree(scratch);
+
+ if (status >= 0) {
+ status = 0;
+ *retlen = len;
+ }
+ return status;
+}
+
+static char *otp_setup(struct mtd_info *device, char revision)
+{
+ device->get_fact_prot_info = dataflash_get_otp_info;
+ device->read_fact_prot_reg = dataflash_read_fact_otp;
+ device->get_user_prot_info = dataflash_get_otp_info;
+ device->read_user_prot_reg = dataflash_read_user_otp;
+
+ /* rev c parts (at45db321c and at45db1281 only!) use a
+ * different write procedure; not (yet?) implemented.
+ */
+ if (revision > 'c')
+ device->write_user_prot_reg = dataflash_write_user_otp;
+
+ return ", OTP";
+}
+
+#else
+
+static char *otp_setup(struct mtd_info *device, char revision)
+{
+ return " (OTP)";
+}
+
+#endif
+
+/* ......................................................................... */
+
/*
* Register DataFlash device with MTD subsystem.
*/
static int __devinit
-add_dataflash(struct spi_device *spi, char *name,
- int nr_pages, int pagesize, int pageoffset)
+add_dataflash_otp(struct spi_device *spi, char *name,
+ int nr_pages, int pagesize, int pageoffset, char revision)
{
struct dataflash *priv;
struct mtd_info *device;
struct flash_platform_data *pdata = spi->dev.platform_data;
+ char *otp_tag = "";
priv = kzalloc(sizeof *priv, GFP_KERNEL);
if (!priv)
@@ -489,8 +664,12 @@ add_dataflash(struct spi_device *spi, char *name,
device->write = dataflash_write;
device->priv = priv;
- dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes\n",
- name, DIV_ROUND_UP(device->size, 1024), pagesize);
+ if (revision >= 'c')
+ otp_tag = otp_setup(device, revision);
+
+ dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes%s\n",
+ name, DIV_ROUND_UP(device->size, 1024),
+ pagesize, otp_tag);
dev_set_drvdata(&spi->dev, priv);
if (mtd_has_partitions()) {
@@ -519,6 +698,14 @@ add_dataflash(struct spi_device *spi, char *name,
return add_mtd_device(device) == 1 ? -ENODEV : 0;
}
+static inline int __devinit
+add_dataflash(struct spi_device *spi, char *name,
+ int nr_pages, int pagesize, int pageoffset)
+{
+ return add_dataflash_otp(spi, name, nr_pages, pagesize,
+ pageoffset, 0);
+}
+
struct flash_info {
char *name;
@@ -664,13 +851,16 @@ static int __devinit dataflash_probe(struct spi_device *spi)
* Try to detect dataflash by JEDEC ID.
* If it succeeds we know we have either a C or D part.
* D will support power of 2 pagesize option.
+ * Both support the security register, though with different
+ * write procedures.
*/
info = jedec_probe(spi);
if (IS_ERR(info))
return PTR_ERR(info);
if (info != NULL)
- return add_dataflash(spi, info->name, info->nr_pages,
- info->pagesize, info->pageoffset);
+ return add_dataflash_otp(spi, info->name, info->nr_pages,
+ info->pagesize, info->pageoffset,
+ (info->flags & SUP_POW2PS) ? 'd' : 'c');
/*
* Older chips support only legacy commands, identifing
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index c4f9d3378b2..50ce13887f6 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -388,6 +388,10 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
if (thisEUN == targetEUN)
break;
+ /* Unlink the last block from the chain. */
+ inftl->PUtable[prevEUN] = BLOCK_NIL;
+
+ /* Now try to erase it. */
if (INFTL_formatblock(inftl, thisEUN) < 0) {
/*
* Could not erase : mark block as reserved.
@@ -396,7 +400,6 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
} else {
/* Correctly erased : mark it as free */
inftl->PUtable[thisEUN] = BLOCK_FREE;
- inftl->PUtable[prevEUN] = BLOCK_NIL;
inftl->numfreeEUNs++;
}
}
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index df8e00bba07..5ea16936216 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -332,30 +332,6 @@ config MTD_CFI_FLAGADM
Mapping for the Flaga digital module. If you don't have one, ignore
this setting.
-config MTD_WALNUT
- tristate "Flash device mapped on IBM 405GP Walnut"
- depends on MTD_JEDECPROBE && WALNUT && !PPC_MERGE
- help
- This enables access routines for the flash chips on the IBM 405GP
- Walnut board. If you have one of these boards and would like to
- use the flash chips on it, say 'Y'.
-
-config MTD_EBONY
- tristate "Flash devices mapped on IBM 440GP Ebony"
- depends on MTD_JEDECPROBE && EBONY && !PPC_MERGE
- help
- This enables access routines for the flash chips on the IBM 440GP
- Ebony board. If you have one of these boards and would like to
- use the flash chips on it, say 'Y'.
-
-config MTD_OCOTEA
- tristate "Flash devices mapped on IBM 440GX Ocotea"
- depends on MTD_CFI && OCOTEA && !PPC_MERGE
- help
- This enables access routines for the flash chips on the IBM 440GX
- Ocotea board. If you have one of these boards and would like to
- use the flash chips on it, say 'Y'.
-
config MTD_REDWOOD
tristate "CFI Flash devices mapped on IBM Redwood"
depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
@@ -458,13 +434,6 @@ config MTD_CEIVA
PhotoMax Digital Picture Frame.
If you have such a device, say 'Y'.
-config MTD_NOR_TOTO
- tristate "NOR Flash device on TOTO board"
- depends on ARCH_OMAP && OMAP_TOTO
- help
- This enables access to the NOR flash on the Texas Instruments
- TOTO board.
-
config MTD_H720X
tristate "Hynix evaluation board mappings"
depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
@@ -522,7 +491,7 @@ config MTD_BFIN_ASYNC
config MTD_UCLINUX
tristate "Generic uClinux RAM/ROM filesystem support"
- depends on MTD_PARTITIONS && !MMU
+ depends on MTD_PARTITIONS && MTD_RAM && !MMU
help
Map driver to support image based filesystems for uClinux.
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 6cda6df973e..6d9ba35caf1 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -50,12 +50,8 @@ obj-$(CONFIG_MTD_REDWOOD) += redwood.o
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
obj-$(CONFIG_MTD_NETtel) += nettel.o
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
-obj-$(CONFIG_MTD_EBONY) += ebony.o
-obj-$(CONFIG_MTD_OCOTEA) += ocotea.o
-obj-$(CONFIG_MTD_WALNUT) += walnut.o
obj-$(CONFIG_MTD_H720X) += h720x-flash.o
obj-$(CONFIG_MTD_SBC8240) += sbc8240.o
-obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o
obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o
obj-$(CONFIG_MTD_IXP2000) += ixp2000.o
obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o
diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c
deleted file mode 100644
index d92b7c70d3e..00000000000
--- a/drivers/mtd/maps/ebony.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Mapping for Ebony user flash
- *
- * Matt Porter <mporter@kernel.crashing.org>
- *
- * Copyright 2002-2004 MontaVista Software Inc.
- *
- * 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/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/ibm44x.h>
-#include <platforms/4xx/ebony.h>
-
-static struct mtd_info *flash;
-
-static struct map_info ebony_small_map = {
- .name = "Ebony small flash",
- .size = EBONY_SMALL_FLASH_SIZE,
- .bankwidth = 1,
-};
-
-static struct map_info ebony_large_map = {
- .name = "Ebony large flash",
- .size = EBONY_LARGE_FLASH_SIZE,
- .bankwidth = 1,
-};
-
-static struct mtd_partition ebony_small_partitions[] = {
- {
- .name = "OpenBIOS",
- .offset = 0x0,
- .size = 0x80000,
- }
-};
-
-static struct mtd_partition ebony_large_partitions[] = {
- {
- .name = "fs",
- .offset = 0,
- .size = 0x380000,
- },
- {
- .name = "firmware",
- .offset = 0x380000,
- .size = 0x80000,
- }
-};
-
-int __init init_ebony(void)
-{
- u8 fpga0_reg;
- u8 __iomem *fpga0_adr;
- unsigned long long small_flash_base, large_flash_base;
-
- fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16);
- if (!fpga0_adr)
- return -ENOMEM;
-
- fpga0_reg = readb(fpga0_adr);
- iounmap(fpga0_adr);
-
- if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
- !EBONY_FLASH_SEL(fpga0_reg))
- small_flash_base = EBONY_SMALL_FLASH_HIGH2;
- else if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
- EBONY_FLASH_SEL(fpga0_reg))
- small_flash_base = EBONY_SMALL_FLASH_HIGH1;
- else if (!EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
- !EBONY_FLASH_SEL(fpga0_reg))
- small_flash_base = EBONY_SMALL_FLASH_LOW2;
- else
- small_flash_base = EBONY_SMALL_FLASH_LOW1;
-
- if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
- !EBONY_ONBRD_FLASH_EN(fpga0_reg))
- large_flash_base = EBONY_LARGE_FLASH_LOW;
- else
- large_flash_base = EBONY_LARGE_FLASH_HIGH;
-
- ebony_small_map.phys = small_flash_base;
- ebony_small_map.virt = ioremap64(small_flash_base,
- ebony_small_map.size);
-
- if (!ebony_small_map.virt) {
- printk("Failed to ioremap flash\n");
- return -EIO;
- }
-
- simple_map_init(&ebony_small_map);
-
- flash = do_map_probe("jedec_probe", &ebony_small_map);
- if (flash) {
- flash->owner = THIS_MODULE;
- add_mtd_partitions(flash, ebony_small_partitions,
- ARRAY_SIZE(ebony_small_partitions));
- } else {
- printk("map probe failed for flash\n");
- iounmap(ebony_small_map.virt);
- return -ENXIO;
- }
-
- ebony_large_map.phys = large_flash_base;
- ebony_large_map.virt = ioremap64(large_flash_base,
- ebony_large_map.size);
-
- if (!ebony_large_map.virt) {
- printk("Failed to ioremap flash\n");
- iounmap(ebony_small_map.virt);
- return -EIO;
- }
-
- simple_map_init(&ebony_large_map);
-
- flash = do_map_probe("jedec_probe", &ebony_large_map);
- if (flash) {
- flash->owner = THIS_MODULE;
- add_mtd_partitions(flash, ebony_large_partitions,
- ARRAY_SIZE(ebony_large_partitions));
- } else {
- printk("map probe failed for flash\n");
- iounmap(ebony_small_map.virt);
- iounmap(ebony_large_map.virt);
- return -ENXIO;
- }
-
- return 0;
-}
-
-static void __exit cleanup_ebony(void)
-{
- if (flash) {
- del_mtd_partitions(flash);
- map_destroy(flash);
- }
-
- if (ebony_small_map.virt) {
- iounmap(ebony_small_map.virt);
- ebony_small_map.virt = NULL;
- }
-
- if (ebony_large_map.virt) {
- iounmap(ebony_large_map.virt);
- ebony_large_map.virt = NULL;
- }
-}
-
-module_init(init_ebony);
-module_exit(cleanup_ebony);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards");
diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c
deleted file mode 100644
index 5522eac8c98..00000000000
--- a/drivers/mtd/maps/ocotea.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Mapping for Ocotea user flash
- *
- * Matt Porter <mporter@kernel.crashing.org>
- *
- * Copyright 2002-2004 MontaVista Software Inc.
- *
- * 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/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/ibm44x.h>
-#include <platforms/4xx/ocotea.h>
-
-static struct mtd_info *flash;
-
-static struct map_info ocotea_small_map = {
- .name = "Ocotea small flash",
- .size = OCOTEA_SMALL_FLASH_SIZE,
- .buswidth = 1,
-};
-
-static struct map_info ocotea_large_map = {
- .name = "Ocotea large flash",
- .size = OCOTEA_LARGE_FLASH_SIZE,
- .buswidth = 1,
-};
-
-static struct mtd_partition ocotea_small_partitions[] = {
- {
- .name = "pibs",
- .offset = 0x0,
- .size = 0x100000,
- }
-};
-
-static struct mtd_partition ocotea_large_partitions[] = {
- {
- .name = "fs",
- .offset = 0,
- .size = 0x300000,
- },
- {
- .name = "firmware",
- .offset = 0x300000,
- .size = 0x100000,
- }
-};
-
-int __init init_ocotea(void)
-{
- u8 fpga0_reg;
- u8 *fpga0_adr;
- unsigned long long small_flash_base, large_flash_base;
-
- fpga0_adr = ioremap64(OCOTEA_FPGA_ADDR, 16);
- if (!fpga0_adr)
- return -ENOMEM;
-
- fpga0_reg = readb((unsigned long)fpga0_adr);
- iounmap(fpga0_adr);
-
- if (OCOTEA_BOOT_LARGE_FLASH(fpga0_reg)) {
- small_flash_base = OCOTEA_SMALL_FLASH_HIGH;
- large_flash_base = OCOTEA_LARGE_FLASH_LOW;
- }
- else {
- small_flash_base = OCOTEA_SMALL_FLASH_LOW;
- large_flash_base = OCOTEA_LARGE_FLASH_HIGH;
- }
-
- ocotea_small_map.phys = small_flash_base;
- ocotea_small_map.virt = ioremap64(small_flash_base,
- ocotea_small_map.size);
-
- if (!ocotea_small_map.virt) {
- printk("Failed to ioremap flash\n");
- return -EIO;
- }
-
- simple_map_init(&ocotea_small_map);
-
- flash = do_map_probe("map_rom", &ocotea_small_map);
- if (flash) {
- flash->owner = THIS_MODULE;
- add_mtd_partitions(flash, ocotea_small_partitions,
- ARRAY_SIZE(ocotea_small_partitions));
- } else {
- printk("map probe failed for flash\n");
- iounmap(ocotea_small_map.virt);
- return -ENXIO;
- }
-
- ocotea_large_map.phys = large_flash_base;
- ocotea_large_map.virt = ioremap64(large_flash_base,
- ocotea_large_map.size);
-
- if (!ocotea_large_map.virt) {
- printk("Failed to ioremap flash\n");
- iounmap(ocotea_small_map.virt);
- return -EIO;
- }
-
- simple_map_init(&ocotea_large_map);
-
- flash = do_map_probe("cfi_probe", &ocotea_large_map);
- if (flash) {
- flash->owner = THIS_MODULE;
- add_mtd_partitions(flash, ocotea_large_partitions,
- ARRAY_SIZE(ocotea_large_partitions));
- } else {
- printk("map probe failed for flash\n");
- iounmap(ocotea_small_map.virt);
- iounmap(ocotea_large_map.virt);
- return -ENXIO;
- }
-
- return 0;
-}
-
-static void __exit cleanup_ocotea(void)
-{
- if (flash) {
- del_mtd_partitions(flash);
- map_destroy(flash);
- }
-
- if (ocotea_small_map.virt) {
- iounmap((void *)ocotea_small_map.virt);
- ocotea_small_map.virt = 0;
- }
-
- if (ocotea_large_map.virt) {
- iounmap((void *)ocotea_large_map.virt);
- ocotea_large_map.virt = 0;
- }
-}
-
-module_init(init_ocotea);
-module_exit(cleanup_ocotea);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 440GX Ocotea boards");
diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c
deleted file mode 100644
index 0a60ebbc217..00000000000
--- a/drivers/mtd/maps/omap-toto-flash.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * NOR Flash memory access on TI Toto board
- *
- * jzhang@ti.com (C) 2003 Texas Instruments.
- *
- * (C) 2002 MontVista Software, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-
-#ifndef CONFIG_ARCH_OMAP
-#error This is for OMAP architecture only
-#endif
-
-//these lines need be moved to a hardware header file
-#define OMAP_TOTO_FLASH_BASE 0xd8000000
-#define OMAP_TOTO_FLASH_SIZE 0x80000
-
-static struct map_info omap_toto_map_flash = {
- .name = "OMAP Toto flash",
- .bankwidth = 2,
- .virt = (void __iomem *)OMAP_TOTO_FLASH_BASE,
-};
-
-
-static struct mtd_partition toto_flash_partitions[] = {
- {
- .name = "BootLoader",
- .size = 0x00040000, /* hopefully u-boot will stay 128k + 128*/
- .offset = 0,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- }, {
- .name = "ReservedSpace",
- .size = 0x00030000,
- .offset = MTDPART_OFS_APPEND,
- //mask_flags: MTD_WRITEABLE, /* force read-only */
- }, {
- .name = "EnvArea", /* bottom 64KiB for env vars */
- .size = MTDPART_SIZ_FULL,
- .offset = MTDPART_OFS_APPEND,
- }
-};
-
-static struct mtd_partition *parsed_parts;
-
-static struct mtd_info *flash_mtd;
-
-static int __init init_flash (void)
-{
-
- struct mtd_partition *parts;
- int nb_parts = 0;
- int parsed_nr_parts = 0;
- const char *part_type;
-
- /*
- * Static partition definition selection
- */
- part_type = "static";
-
- parts = toto_flash_partitions;
- nb_parts = ARRAY_SIZE(toto_flash_partitions);
- omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE;
- omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE);
-
- simple_map_init(&omap_toto_map_flash);
- /*
- * Now let's probe for the actual flash. Do it here since
- * specific machine settings might have been set above.
- */
- printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n",
- omap_toto_map_flash.bankwidth*8);
- flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash);
- if (!flash_mtd)
- return -ENXIO;
-
- if (parsed_nr_parts > 0) {
- parts = parsed_parts;
- nb_parts = parsed_nr_parts;
- }
-
- if (nb_parts == 0) {
- printk(KERN_NOTICE "OMAP toto flash: no partition info available,"
- "registering whole flash at once\n");
- if (add_mtd_device(flash_mtd)){
- return -ENXIO;
- }
- } else {
- printk(KERN_NOTICE "Using %s partition definition\n",
- part_type);
- return add_mtd_partitions(flash_mtd, parts, nb_parts);
- }
- return 0;
-}
-
-int __init omap_toto_mtd_init(void)
-{
- int status;
-
- if (status = init_flash()) {
- printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n");
- }
- return status;
-}
-
-static void __exit omap_toto_mtd_cleanup(void)
-{
- if (flash_mtd) {
- del_mtd_partitions(flash_mtd);
- map_destroy(flash_mtd);
- kfree(parsed_parts);
- }
-}
-
-module_init(omap_toto_mtd_init);
-module_exit(omap_toto_mtd_cleanup);
-
-MODULE_AUTHOR("Jian Zhang");
-MODULE_DESCRIPTION("OMAP Toto board map driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 5c6a25c9038..48f4cf5cb9d 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -203,15 +203,8 @@ intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
* not enabled, should we be allocating a new resource for it
* or simply enabling it?
*/
- if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
- IORESOURCE_ROM_ENABLE)) {
- u32 val;
- pci_resource_flags(dev, PCI_ROM_RESOURCE) |= IORESOURCE_ROM_ENABLE;
- pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
- val |= PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
- printk("%s: enabling expansion ROM\n", pci_name(dev));
- }
+ pci_enable_rom(dev);
+ printk("%s: enabling expansion ROM\n", pci_name(dev));
}
if (!len || !base)
@@ -232,18 +225,13 @@ intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
static void
intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
{
- u32 val;
-
if (map->base)
iounmap(map->base);
/*
* We need to undo the PCI BAR2/PCI ROM BAR address alteration.
*/
- pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~IORESOURCE_ROM_ENABLE;
- pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
- val &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
+ pci_disable_rom(dev);
}
static unsigned long
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 49acd417189..5fcfec034a9 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -230,8 +230,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
#ifdef CONFIG_MTD_OF_PARTS
if (err == 0) {
- err = of_mtd_parse_partitions(&dev->dev, info->mtd,
- dp, &info->parts);
+ err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
if (err < 0)
return err;
}
diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c
deleted file mode 100644
index e243476c817..00000000000
--- a/drivers/mtd/maps/walnut.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Mapping for Walnut flash
- * (used ebony.c as a "framework")
- *
- * Heikki Lindholm <holindho@infradead.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.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/ibm4xx.h>
-#include <platforms/4xx/walnut.h>
-
-/* these should be in platforms/4xx/walnut.h ? */
-#define WALNUT_FLASH_ONBD_N(x) (x & 0x02)
-#define WALNUT_FLASH_SRAM_SEL(x) (x & 0x01)
-#define WALNUT_FLASH_LOW 0xFFF00000
-#define WALNUT_FLASH_HIGH 0xFFF80000
-#define WALNUT_FLASH_SIZE 0x80000
-
-static struct mtd_info *flash;
-
-static struct map_info walnut_map = {
- .name = "Walnut flash",
- .size = WALNUT_FLASH_SIZE,
- .bankwidth = 1,
-};
-
-/* Actually, OpenBIOS is the last 128 KiB of the flash - better
- * partitioning could be made */
-static struct mtd_partition walnut_partitions[] = {
- {
- .name = "OpenBIOS",
- .offset = 0x0,
- .size = WALNUT_FLASH_SIZE,
- /*.mask_flags = MTD_WRITEABLE, */ /* force read-only */
- }
-};
-
-int __init init_walnut(void)
-{
- u8 fpga_brds1;
- void *fpga_brds1_adr;
- void *fpga_status_adr;
- unsigned long flash_base;
-
- /* this should already be mapped (platform/4xx/walnut.c) */
- fpga_status_adr = ioremap(WALNUT_FPGA_BASE, 8);
- if (!fpga_status_adr)
- return -ENOMEM;
-
- fpga_brds1_adr = fpga_status_adr+5;
- fpga_brds1 = readb(fpga_brds1_adr);
- /* iounmap(fpga_status_adr); */
-
- if (WALNUT_FLASH_ONBD_N(fpga_brds1)) {
- printk("The on-board flash is disabled (U79 sw 5)!");
- iounmap(fpga_status_adr);
- return -EIO;
- }
- if (WALNUT_FLASH_SRAM_SEL(fpga_brds1))
- flash_base = WALNUT_FLASH_LOW;
- else
- flash_base = WALNUT_FLASH_HIGH;
-
- walnut_map.phys = flash_base;
- walnut_map.virt =
- (void __iomem *)ioremap(flash_base, walnut_map.size);
-
- if (!walnut_map.virt) {
- printk("Failed to ioremap flash.\n");
- iounmap(fpga_status_adr);
- return -EIO;
- }
-
- simple_map_init(&walnut_map);
-
- flash = do_map_probe("jedec_probe", &walnut_map);
- if (flash) {
- flash->owner = THIS_MODULE;
- add_mtd_partitions(flash, walnut_partitions,
- ARRAY_SIZE(walnut_partitions));
- } else {
- printk("map probe failed for flash\n");
- iounmap(fpga_status_adr);
- return -ENXIO;
- }
-
- iounmap(fpga_status_adr);
- return 0;
-}
-
-static void __exit cleanup_walnut(void)
-{
- if (flash) {
- del_mtd_partitions(flash);
- map_destroy(flash);
- }
-
- if (walnut_map.virt) {
- iounmap((void *)walnut_map.virt);
- walnut_map.virt = 0;
- }
-}
-
-module_init(init_walnut);
-module_exit(cleanup_walnut);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Heikki Lindholm <holindho@infradead.org>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 405GP Walnut boards");
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 681d5aca2af..1409f01406f 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -133,15 +133,12 @@ static void mtd_blktrans_request(struct request_queue *rq)
}
-static int blktrans_open(struct inode *i, struct file *f)
+static int blktrans_open(struct block_device *bdev, fmode_t mode)
{
- struct mtd_blktrans_dev *dev;
- struct mtd_blktrans_ops *tr;
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+ struct mtd_blktrans_ops *tr = dev->tr;
int ret = -ENODEV;
- dev = i->i_bdev->bd_disk->private_data;
- tr = dev->tr;
-
if (!try_module_get(dev->mtd->owner))
goto out;
@@ -164,15 +161,12 @@ static int blktrans_open(struct inode *i, struct file *f)
return ret;
}
-static int blktrans_release(struct inode *i, struct file *f)
+static int blktrans_release(struct gendisk *disk, fmode_t mode)
{
- struct mtd_blktrans_dev *dev;
- struct mtd_blktrans_ops *tr;
+ struct mtd_blktrans_dev *dev = disk->private_data;
+ struct mtd_blktrans_ops *tr = dev->tr;
int ret = 0;
- dev = i->i_bdev->bd_disk->private_data;
- tr = dev->tr;
-
if (tr->release)
ret = tr->release(dev);
@@ -194,10 +188,10 @@ static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return -ENOTTY;
}
-static int blktrans_ioctl(struct inode *inode, struct file *file,
+static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
struct mtd_blktrans_ops *tr = dev->tr;
switch (cmd) {
@@ -215,7 +209,7 @@ static struct block_device_operations mtd_blktrans_ops = {
.owner = THIS_MODULE,
.open = blktrans_open,
.release = blktrans_release,
- .ioctl = blktrans_ioctl,
+ .locked_ioctl = blktrans_ioctl,
.getgeo = blktrans_getgeo,
};
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 1c74762dec8..bcffeda2df3 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -96,7 +96,7 @@ static int mtd_open(struct inode *inode, struct file *file)
return -ENODEV;
/* You can't open the RO devices RW */
- if ((file->f_mode & 2) && (minor & 1))
+ if ((file->f_mode & FMODE_WRITE) && (minor & 1))
return -EACCES;
lock_kernel();
@@ -114,7 +114,7 @@ static int mtd_open(struct inode *inode, struct file *file)
}
/* You can't open it RW if it's not a writeable device */
- if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
+ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
put_mtd_device(mtd);
ret = -EACCES;
goto out;
@@ -144,7 +144,7 @@ static int mtd_close(struct inode *inode, struct file *file)
DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
/* Only sync if opened RW */
- if ((file->f_mode & 2) && mtd->sync)
+ if ((file->f_mode & FMODE_WRITE) && mtd->sync)
mtd->sync(mtd);
put_mtd_device(mtd);
@@ -348,7 +348,7 @@ static void mtdchar_erase_callback (struct erase_info *instr)
wake_up((wait_queue_head_t *)instr->priv);
}
-#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+#ifdef CONFIG_HAVE_MTD_OTP
static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
{
struct mtd_info *mtd = mfi->mtd;
@@ -443,7 +443,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
{
struct erase_info *erase;
- if(!(file->f_mode & 2))
+ if(!(file->f_mode & FMODE_WRITE))
return -EPERM;
erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
@@ -497,7 +497,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
struct mtd_oob_buf __user *user_buf = argp;
uint32_t retlen;
- if(!(file->f_mode & 2))
+ if(!(file->f_mode & FMODE_WRITE))
return -EPERM;
if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
@@ -665,7 +665,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
break;
}
-#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+#ifdef CONFIG_HAVE_MTD_OTP
case OTPSELECT:
{
int mode;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 2972a5edb73..789842d0e6f 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -444,7 +444,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
return -EINVAL;
}
- instr->fail_addr = 0xffffffff;
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
/* make a local copy of instr to avoid modifying the caller's struct */
erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
@@ -493,7 +493,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
/* sanity check: should never happen since
* block alignment has been checked above */
BUG_ON(err == -EINVAL);
- if (erase->fail_addr != 0xffffffff)
+ if (erase->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr = erase->fail_addr + offset;
break;
}
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index 5a680e1e61f..aebb3b27edb 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -33,6 +33,7 @@
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
+#define MTDOOPS_KERNMSG_MAGIC 0x5d005d00
#define OOPS_PAGE_SIZE 4096
static struct mtdoops_context {
@@ -99,7 +100,7 @@ static void mtdoops_inc_counter(struct mtdoops_context *cxt)
int ret;
cxt->nextpage++;
- if (cxt->nextpage > cxt->oops_pages)
+ if (cxt->nextpage >= cxt->oops_pages)
cxt->nextpage = 0;
cxt->nextcount++;
if (cxt->nextcount == 0xffffffff)
@@ -141,7 +142,7 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
mod = (cxt->nextpage * OOPS_PAGE_SIZE) % mtd->erasesize;
if (mod != 0) {
cxt->nextpage = cxt->nextpage + ((mtd->erasesize - mod) / OOPS_PAGE_SIZE);
- if (cxt->nextpage > cxt->oops_pages)
+ if (cxt->nextpage >= cxt->oops_pages)
cxt->nextpage = 0;
}
@@ -158,7 +159,7 @@ badblock:
cxt->nextpage * OOPS_PAGE_SIZE);
i++;
cxt->nextpage = cxt->nextpage + (mtd->erasesize / OOPS_PAGE_SIZE);
- if (cxt->nextpage > cxt->oops_pages)
+ if (cxt->nextpage >= cxt->oops_pages)
cxt->nextpage = 0;
if (i == (cxt->oops_pages / (mtd->erasesize / OOPS_PAGE_SIZE))) {
printk(KERN_ERR "mtdoops: All blocks bad!\n");
@@ -224,40 +225,40 @@ static void find_next_position(struct mtdoops_context *cxt)
{
struct mtd_info *mtd = cxt->mtd;
int ret, page, maxpos = 0;
- u32 count, maxcount = 0xffffffff;
+ u32 count[2], maxcount = 0xffffffff;
size_t retlen;
for (page = 0; page < cxt->oops_pages; page++) {
- ret = mtd->read(mtd, page * OOPS_PAGE_SIZE, 4, &retlen, (u_char *) &count);
- if ((retlen != 4) || ((ret < 0) && (ret != -EUCLEAN))) {
- printk(KERN_ERR "mtdoops: Read failure at %d (%td of 4 read)"
+ ret = mtd->read(mtd, page * OOPS_PAGE_SIZE, 8, &retlen, (u_char *) &count[0]);
+ if ((retlen != 8) || ((ret < 0) && (ret != -EUCLEAN))) {
+ printk(KERN_ERR "mtdoops: Read failure at %d (%td of 8 read)"
", err %d.\n", page * OOPS_PAGE_SIZE, retlen, ret);
continue;
}
- if (count == 0xffffffff)
+ if (count[1] != MTDOOPS_KERNMSG_MAGIC)
+ continue;
+ if (count[0] == 0xffffffff)
continue;
if (maxcount == 0xffffffff) {
- maxcount = count;
+ maxcount = count[0];
maxpos = page;
- } else if ((count < 0x40000000) && (maxcount > 0xc0000000)) {
- maxcount = count;
+ } else if ((count[0] < 0x40000000) && (maxcount > 0xc0000000)) {
+ maxcount = count[0];
maxpos = page;
- } else if ((count > maxcount) && (count < 0xc0000000)) {
- maxcount = count;
+ } else if ((count[0] > maxcount) && (count[0] < 0xc0000000)) {
+ maxcount = count[0];
maxpos = page;
- } else if ((count > maxcount) && (count > 0xc0000000)
+ } else if ((count[0] > maxcount) && (count[0] > 0xc0000000)
&& (maxcount > 0x80000000)) {
- maxcount = count;
+ maxcount = count[0];
maxpos = page;
}
}
if (maxcount == 0xffffffff) {
cxt->nextpage = 0;
cxt->nextcount = 1;
- cxt->ready = 1;
- printk(KERN_DEBUG "mtdoops: Ready %d, %d (first init)\n",
- cxt->nextpage, cxt->nextcount);
+ schedule_work(&cxt->work_erase);
return;
}
@@ -358,8 +359,9 @@ mtdoops_console_write(struct console *co, const char *s, unsigned int count)
if (cxt->writecount == 0) {
u32 *stamp = cxt->oops_buf;
- *stamp = cxt->nextcount;
- cxt->writecount = 4;
+ *stamp++ = cxt->nextcount;
+ *stamp = MTDOOPS_KERNMSG_MAGIC;
+ cxt->writecount = 8;
}
if ((count + cxt->writecount) > OOPS_PAGE_SIZE)
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 9a06dc93ee0..3728913fa5f 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -214,7 +214,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->addr += part->offset;
ret = part->master->erase(part->master, instr);
if (ret) {
- if (instr->fail_addr != 0xffffffff)
+ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
}
@@ -226,7 +226,7 @@ void mtd_erase_callback(struct erase_info *instr)
if (instr->mtd->erase == part_erase) {
struct mtd_part *part = PART(instr->mtd);
- if (instr->fail_addr != 0xffffffff)
+ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
}
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 41f361c49b3..1c2e9450d66 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -56,6 +56,12 @@ config MTD_NAND_H1900
help
This enables the driver for the iPAQ h1900 flash.
+config MTD_NAND_GPIO
+ tristate "GPIO NAND Flash driver"
+ depends on GENERIC_GPIO && ARM
+ help
+ This enables a GPIO based NAND flash driver.
+
config MTD_NAND_SPIA
tristate "NAND Flash device on SPIA board"
depends on ARCH_P720T
@@ -68,12 +74,6 @@ config MTD_NAND_AMS_DELTA
help
Support for NAND flash on Amstrad E3 (Delta).
-config MTD_NAND_TOTO
- tristate "NAND Flash device on TOTO board"
- depends on ARCH_OMAP && BROKEN
- help
- Support for NAND flash on Texas Instruments Toto platform.
-
config MTD_NAND_TS7250
tristate "NAND Flash device on TS-7250 board"
depends on MACH_TS72XX
@@ -163,13 +163,6 @@ config MTD_NAND_S3C2410_HWECC
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
-config MTD_NAND_NDFC
- tristate "NDFC NanD Flash Controller"
- depends on 4xx && !PPC_MERGE
- select MTD_NAND_ECC_SMC
- help
- NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
-
config MTD_NAND_S3C2410_CLKSTOP
bool "S3C2410 NAND IDLE clock stop"
depends on MTD_NAND_S3C2410
@@ -340,6 +333,13 @@ config MTD_NAND_PXA3xx
This enables the driver for the NAND flash device found on
PXA3xx processors
+config MTD_NAND_PXA3xx_BUILTIN
+ bool "Use builtin definitions for some NAND chips (deprecated)"
+ depends on MTD_NAND_PXA3xx
+ help
+ This enables builtin definitions for some NAND chips. This
+ is deprecated in favor of platform specific data.
+
config MTD_NAND_CM_X270
tristate "Support for NAND Flash on CM-X270 modules"
depends on MTD_NAND && MACH_ARMCORE
@@ -400,10 +400,24 @@ config MTD_NAND_FSL_ELBC
config MTD_NAND_FSL_UPM
tristate "Support for NAND on Freescale UPM"
- depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx)
+ depends on MTD_NAND && (PPC_83xx || PPC_85xx)
select FSL_LBC
help
Enables support for NAND Flash chips wired onto Freescale PowerPC
processor localbus with User-Programmable Machine support.
+config MTD_NAND_MXC
+ tristate "MXC NAND support"
+ depends on ARCH_MX2
+ help
+ This enables the driver for the NAND flash controller on the
+ MXC processors.
+
+config MTD_NAND_SH_FLCTL
+ tristate "Support for NAND on Renesas SuperH FLCTL"
+ depends on MTD_NAND && SUPERH && CPU_SUBTYPE_SH7723
+ help
+ Several Renesas SuperH CPU has FLCTL. This option enables support
+ for NAND Flash using FLCTL. This driver support SH7723.
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b786c5da82d..b661586afbf 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
-obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
@@ -24,6 +23,7 @@ obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o
+obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o
obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
@@ -34,5 +34,7 @@ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
+obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o
+obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 3387e0d5076..c98c1570a40 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -174,48 +174,6 @@ static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
}
/*
- * write oob for small pages
- */
-static int atmel_nand_write_oob_512(struct mtd_info *mtd,
- struct nand_chip *chip, int page)
-{
- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsize = chip->ecc.size, length = mtd->oobsize;
- int len, pos, status = 0;
- const uint8_t *bufpoi = chip->oob_poi;
-
- pos = eccsize + chunk;
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
- len = min_t(int, length, chunk);
- chip->write_buf(mtd, bufpoi, len);
- bufpoi += len;
- length -= len;
- if (length > 0)
- chip->write_buf(mtd, bufpoi, length);
-
- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
- status = chip->waitfunc(mtd, chip);
-
- return status & NAND_STATUS_FAIL ? -EIO : 0;
-
-}
-
-/*
- * read oob for small pages
- */
-static int atmel_nand_read_oob_512(struct mtd_info *mtd,
- struct nand_chip *chip, int page, int sndcmd)
-{
- if (sndcmd) {
- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
- sndcmd = 0;
- }
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
- return sndcmd;
-}
-
-/*
* Calculate HW ECC
*
* function called after a write
@@ -235,14 +193,14 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
/* get the first 2 ECC bytes */
ecc_value = ecc_readl(host->ecc, PR);
- ecc_code[eccpos[0]] = ecc_value & 0xFF;
- ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
+ ecc_code[0] = ecc_value & 0xFF;
+ ecc_code[1] = (ecc_value >> 8) & 0xFF;
/* get the last 2 ECC bytes */
ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;
- ecc_code[eccpos[2]] = ecc_value & 0xFF;
- ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
+ ecc_code[2] = ecc_value & 0xFF;
+ ecc_code[3] = (ecc_value >> 8) & 0xFF;
return 0;
}
@@ -476,14 +434,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
res = -EIO;
goto err_ecc_ioremap;
}
- nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
+ nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.calculate = atmel_nand_calculate;
nand_chip->ecc.correct = atmel_nand_correct;
nand_chip->ecc.hwctl = atmel_nand_hwctl;
nand_chip->ecc.read_page = atmel_nand_read_page;
nand_chip->ecc.bytes = 4;
- nand_chip->ecc.prepad = 0;
- nand_chip->ecc.postpad = 0;
}
nand_chip->chip_delay = 20; /* 20us command delay time */
@@ -514,7 +470,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
goto err_scan_ident;
}
- if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
+ if (nand_chip->ecc.mode == NAND_ECC_HW) {
/* ECC is calculated for the whole page (1 step) */
nand_chip->ecc.size = mtd->writesize;
@@ -522,8 +478,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
switch (mtd->writesize) {
case 512:
nand_chip->ecc.layout = &atmel_oobinfo_small;
- nand_chip->ecc.read_oob = atmel_nand_read_oob_512;
- nand_chip->ecc.write_oob = atmel_nand_write_oob_512;
ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
break;
case 1024:
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 3370a800fd3..9f1b451005c 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -289,8 +289,10 @@ static int __init cs553x_init(void)
int i;
uint64_t val;
+#ifdef CONFIG_MTD_PARTITIONS
int mtd_parts_nb = 0;
struct mtd_partition *mtd_parts = NULL;
+#endif
/* If the CPU isn't a Geode GX or LX, abort */
if (!is_geode())
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 98ad3cefcaf..4aa5bd6158d 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -918,8 +918,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
#ifdef CONFIG_MTD_OF_PARTS
if (ret == 0) {
- ret = of_mtd_parse_partitions(priv->dev, &priv->mtd,
- node, &parts);
+ ret = of_mtd_parse_partitions(priv->dev, node, &parts);
if (ret < 0)
goto err;
}
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 1ebfd87f00b..024e3fffd4b 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
@@ -36,8 +37,6 @@ struct fsl_upm_nand {
uint8_t upm_cmd_offset;
void __iomem *io_base;
int rnb_gpio;
- const uint32_t *wait_pattern;
- const uint32_t *wait_write;
int chip_delay;
};
@@ -61,10 +60,11 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
if (fun->rnb_gpio >= 0) {
while (--cnt && !fun_chip_ready(&fun->mtd))
cpu_relax();
+ if (!cnt)
+ dev_err(fun->dev, "tired waiting for RNB\n");
+ } else {
+ ndelay(100);
}
-
- if (!cnt)
- dev_err(fun->dev, "tired waiting for RNB\n");
}
static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -89,8 +89,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
- if (fun->wait_pattern)
- fun_wait_rnb(fun);
+ fun_wait_rnb(fun);
}
static uint8_t fun_read_byte(struct mtd_info *mtd)
@@ -116,14 +115,16 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
for (i = 0; i < len; i++) {
out_8(fun->chip.IO_ADDR_W, buf[i]);
- if (fun->wait_write)
- fun_wait_rnb(fun);
+ fun_wait_rnb(fun);
}
}
-static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
+static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
+ const struct device_node *upm_np,
+ const struct resource *io_res)
{
int ret;
+ struct device_node *flash_np;
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_types[] = { "cmdlinepart", NULL, };
#endif
@@ -143,18 +144,37 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
fun->mtd.priv = &fun->chip;
fun->mtd.owner = THIS_MODULE;
+ flash_np = of_get_next_child(upm_np, NULL);
+ if (!flash_np)
+ return -ENODEV;
+
+ fun->mtd.name = kasprintf(GFP_KERNEL, "%x.%s", io_res->start,
+ flash_np->name);
+ if (!fun->mtd.name) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
ret = nand_scan(&fun->mtd, 1);
if (ret)
- return ret;
-
- fun->mtd.name = fun->dev->bus_id;
+ goto err;
#ifdef CONFIG_MTD_PARTITIONS
ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (ret == 0)
+ ret = of_mtd_parse_partitions(fun->dev, &fun->mtd,
+ flash_np, &fun->parts);
+#endif
if (ret > 0)
- return add_mtd_partitions(&fun->mtd, fun->parts, ret);
+ ret = add_mtd_partitions(&fun->mtd, fun->parts, ret);
+ else
#endif
- return add_mtd_device(&fun->mtd);
+ ret = add_mtd_device(&fun->mtd);
+err:
+ of_node_put(flash_np);
+ return ret;
}
static int __devinit fun_probe(struct of_device *ofdev,
@@ -211,6 +231,12 @@ static int __devinit fun_probe(struct of_device *ofdev,
goto err2;
}
+ prop = of_get_property(ofdev->node, "chip-delay", NULL);
+ if (prop)
+ fun->chip_delay = *prop;
+ else
+ fun->chip_delay = 50;
+
fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
io_res.end - io_res.start + 1);
if (!fun->io_base) {
@@ -220,17 +246,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
fun->dev = &ofdev->dev;
fun->last_ctrl = NAND_CLE;
- fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern",
- NULL);
- fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL);
-
- prop = of_get_property(ofdev->node, "chip-delay", NULL);
- if (prop)
- fun->chip_delay = *prop;
- else
- fun->chip_delay = 50;
- ret = fun_chip_init(fun);
+ ret = fun_chip_init(fun, ofdev->node, &io_res);
if (ret)
goto err2;
@@ -251,6 +268,7 @@ static int __devexit fun_remove(struct of_device *ofdev)
struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
nand_release(&fun->mtd);
+ kfree(fun->mtd.name);
if (fun->rnb_gpio >= 0)
gpio_free(fun->rnb_gpio);
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
new file mode 100644
index 00000000000..8f902e75aa8
--- /dev/null
+++ b/drivers/mtd/nand/gpio.c
@@ -0,0 +1,375 @@
+/*
+ * drivers/mtd/nand/gpio.c
+ *
+ * Updated, and converted to generic GPIO based driver by Russell King.
+ *
+ * Written by Ben Dooks <ben@simtec.co.uk>
+ * Based on 2.4 version by Mark Whittaker
+ *
+ * © 2004 Simtec Electronics
+ *
+ * Device driver for NAND connected via GPIO
+ *
+ * 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/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand-gpio.h>
+
+struct gpiomtd {
+ void __iomem *io_sync;
+ struct mtd_info mtd_info;
+ struct nand_chip nand_chip;
+ struct gpio_nand_platdata plat;
+};
+
+#define gpio_nand_getpriv(x) container_of(x, struct gpiomtd, mtd_info)
+
+
+#ifdef CONFIG_ARM
+/* gpio_nand_dosync()
+ *
+ * Make sure the GPIO state changes occur in-order with writes to NAND
+ * memory region.
+ * Needed on PXA due to bus-reordering within the SoC itself (see section on
+ * I/O ordering in PXA manual (section 2.3, p35)
+ */
+static void gpio_nand_dosync(struct gpiomtd *gpiomtd)
+{
+ unsigned long tmp;
+
+ if (gpiomtd->io_sync) {
+ /*
+ * Linux memory barriers don't cater for what's required here.
+ * What's required is what's here - a read from a separate
+ * region with a dependency on that read.
+ */
+ tmp = readl(gpiomtd->io_sync);
+ asm volatile("mov %1, %0\n" : "=r" (tmp) : "r" (tmp));
+ }
+}
+#else
+static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {}
+#endif
+
+static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
+
+ gpio_nand_dosync(gpiomtd);
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ gpio_set_value(gpiomtd->plat.gpio_nce, !(ctrl & NAND_NCE));
+ gpio_set_value(gpiomtd->plat.gpio_cle, !!(ctrl & NAND_CLE));
+ gpio_set_value(gpiomtd->plat.gpio_ale, !!(ctrl & NAND_ALE));
+ gpio_nand_dosync(gpiomtd);
+ }
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ writeb(cmd, gpiomtd->nand_chip.IO_ADDR_W);
+ gpio_nand_dosync(gpiomtd);
+}
+
+static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct nand_chip *this = mtd->priv;
+
+ writesb(this->IO_ADDR_W, buf, len);
+}
+
+static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *this = mtd->priv;
+
+ readsb(this->IO_ADDR_R, buf, len);
+}
+
+static int gpio_nand_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned char read, *p = (unsigned char *) buf;
+ int i, err = 0;
+
+ for (i = 0; i < len; i++) {
+ read = readb(this->IO_ADDR_R);
+ if (read != p[i]) {
+ pr_debug("%s: err at %d (read %04x vs %04x)\n",
+ __func__, i, read, p[i]);
+ err = -EFAULT;
+ }
+ }
+ return err;
+}
+
+static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf,
+ int len)
+{
+ struct nand_chip *this = mtd->priv;
+
+ if (IS_ALIGNED((unsigned long)buf, 2)) {
+ writesw(this->IO_ADDR_W, buf, len>>1);
+ } else {
+ int i;
+ unsigned short *ptr = (unsigned short *)buf;
+
+ for (i = 0; i < len; i += 2, ptr++)
+ writew(*ptr, this->IO_ADDR_W);
+ }
+}
+
+static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *this = mtd->priv;
+
+ if (IS_ALIGNED((unsigned long)buf, 2)) {
+ readsw(this->IO_ADDR_R, buf, len>>1);
+ } else {
+ int i;
+ unsigned short *ptr = (unsigned short *)buf;
+
+ for (i = 0; i < len; i += 2, ptr++)
+ *ptr = readw(this->IO_ADDR_R);
+ }
+}
+
+static int gpio_nand_verifybuf16(struct mtd_info *mtd, const u_char *buf,
+ int len)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned short read, *p = (unsigned short *) buf;
+ int i, err = 0;
+ len >>= 1;
+
+ for (i = 0; i < len; i++) {
+ read = readw(this->IO_ADDR_R);
+ if (read != p[i]) {
+ pr_debug("%s: err at %d (read %04x vs %04x)\n",
+ __func__, i, read, p[i]);
+ err = -EFAULT;
+ }
+ }
+ return err;
+}
+
+
+static int gpio_nand_devready(struct mtd_info *mtd)
+{
+ struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
+ return gpio_get_value(gpiomtd->plat.gpio_rdy);
+}
+
+static int __devexit gpio_nand_remove(struct platform_device *dev)
+{
+ struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
+ struct resource *res;
+
+ nand_release(&gpiomtd->mtd_info);
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ iounmap(gpiomtd->io_sync);
+ if (res)
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ iounmap(gpiomtd->nand_chip.IO_ADDR_R);
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+ gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
+ gpio_set_value(gpiomtd->plat.gpio_nce, 1);
+
+ gpio_free(gpiomtd->plat.gpio_cle);
+ gpio_free(gpiomtd->plat.gpio_ale);
+ gpio_free(gpiomtd->plat.gpio_nce);
+ if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+ gpio_free(gpiomtd->plat.gpio_nwp);
+ gpio_free(gpiomtd->plat.gpio_rdy);
+
+ kfree(gpiomtd);
+
+ return 0;
+}
+
+static void __iomem *request_and_remap(struct resource *res, size_t size,
+ const char *name, int *err)
+{
+ void __iomem *ptr;
+
+ if (!request_mem_region(res->start, res->end - res->start + 1, name)) {
+ *err = -EBUSY;
+ return NULL;
+ }
+
+ ptr = ioremap(res->start, size);
+ if (!ptr) {
+ release_mem_region(res->start, res->end - res->start + 1);
+ *err = -ENOMEM;
+ }
+ return ptr;
+}
+
+static int __devinit gpio_nand_probe(struct platform_device *dev)
+{
+ struct gpiomtd *gpiomtd;
+ struct nand_chip *this;
+ struct resource *res0, *res1;
+ int ret;
+
+ if (!dev->dev.platform_data)
+ return -EINVAL;
+
+ res0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res0)
+ return -EINVAL;
+
+ gpiomtd = kzalloc(sizeof(*gpiomtd), GFP_KERNEL);
+ if (gpiomtd == NULL) {
+ dev_err(&dev->dev, "failed to create NAND MTD\n");
+ return -ENOMEM;
+ }
+
+ this = &gpiomtd->nand_chip;
+ this->IO_ADDR_R = request_and_remap(res0, 2, "NAND", &ret);
+ if (!this->IO_ADDR_R) {
+ dev_err(&dev->dev, "unable to map NAND\n");
+ goto err_map;
+ }
+
+ res1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ if (res1) {
+ gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret);
+ if (!gpiomtd->io_sync) {
+ dev_err(&dev->dev, "unable to map sync NAND\n");
+ goto err_sync;
+ }
+ }
+
+ memcpy(&gpiomtd->plat, dev->dev.platform_data, sizeof(gpiomtd->plat));
+
+ ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE");
+ if (ret)
+ goto err_nce;
+ gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+ if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) {
+ ret = gpio_request(gpiomtd->plat.gpio_nwp, "NAND NWP");
+ if (ret)
+ goto err_nwp;
+ gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
+ }
+ ret = gpio_request(gpiomtd->plat.gpio_ale, "NAND ALE");
+ if (ret)
+ goto err_ale;
+ gpio_direction_output(gpiomtd->plat.gpio_ale, 0);
+ ret = gpio_request(gpiomtd->plat.gpio_cle, "NAND CLE");
+ if (ret)
+ goto err_cle;
+ gpio_direction_output(gpiomtd->plat.gpio_cle, 0);
+ ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY");
+ if (ret)
+ goto err_rdy;
+ gpio_direction_input(gpiomtd->plat.gpio_rdy);
+
+
+ this->IO_ADDR_W = this->IO_ADDR_R;
+ this->ecc.mode = NAND_ECC_SOFT;
+ this->options = gpiomtd->plat.options;
+ this->chip_delay = gpiomtd->plat.chip_delay;
+
+ /* install our routines */
+ this->cmd_ctrl = gpio_nand_cmd_ctrl;
+ this->dev_ready = gpio_nand_devready;
+
+ if (this->options & NAND_BUSWIDTH_16) {
+ this->read_buf = gpio_nand_readbuf16;
+ this->write_buf = gpio_nand_writebuf16;
+ this->verify_buf = gpio_nand_verifybuf16;
+ } else {
+ this->read_buf = gpio_nand_readbuf;
+ this->write_buf = gpio_nand_writebuf;
+ this->verify_buf = gpio_nand_verifybuf;
+ }
+
+ /* set the mtd private data for the nand driver */
+ gpiomtd->mtd_info.priv = this;
+ gpiomtd->mtd_info.owner = THIS_MODULE;
+
+ if (nand_scan(&gpiomtd->mtd_info, 1)) {
+ dev_err(&dev->dev, "no nand chips found?\n");
+ ret = -ENXIO;
+ goto err_wp;
+ }
+
+ if (gpiomtd->plat.adjust_parts)
+ gpiomtd->plat.adjust_parts(&gpiomtd->plat,
+ gpiomtd->mtd_info.size);
+
+ add_mtd_partitions(&gpiomtd->mtd_info, gpiomtd->plat.parts,
+ gpiomtd->plat.num_parts);
+ platform_set_drvdata(dev, gpiomtd);
+
+ return 0;
+
+err_wp:
+ if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+ gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
+ gpio_free(gpiomtd->plat.gpio_rdy);
+err_rdy:
+ gpio_free(gpiomtd->plat.gpio_cle);
+err_cle:
+ gpio_free(gpiomtd->plat.gpio_ale);
+err_ale:
+ if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+ gpio_free(gpiomtd->plat.gpio_nwp);
+err_nwp:
+ gpio_free(gpiomtd->plat.gpio_nce);
+err_nce:
+ iounmap(gpiomtd->io_sync);
+ if (res1)
+ release_mem_region(res1->start, res1->end - res1->start + 1);
+err_sync:
+ iounmap(gpiomtd->nand_chip.IO_ADDR_R);
+ release_mem_region(res0->start, res0->end - res0->start + 1);
+err_map:
+ kfree(gpiomtd);
+ return ret;
+}
+
+static struct platform_driver gpio_nand_driver = {
+ .probe = gpio_nand_probe,
+ .remove = gpio_nand_remove,
+ .driver = {
+ .name = "gpio-nand",
+ },
+};
+
+static int __init gpio_nand_init(void)
+{
+ printk(KERN_INFO "GPIO NAND driver, © 2004 Simtec Electronics\n");
+
+ return platform_driver_register(&gpio_nand_driver);
+}
+
+static void __exit gpio_nand_exit(void)
+{
+ platform_driver_unregister(&gpio_nand_driver);
+}
+
+module_init(gpio_nand_init);
+module_exit(gpio_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("GPIO NAND Driver");
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644
index 00000000000..21fd4f1c480
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,1077 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
+ *
+ * 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/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mach/flash.h>
+#include <mach/mxc_nand.h>
+
+#define DRIVER_NAME "mxc_nand"
+
+/* Addresses for NFC registers */
+#define NFC_BUF_SIZE 0xE00
+#define NFC_BUF_ADDR 0xE04
+#define NFC_FLASH_ADDR 0xE06
+#define NFC_FLASH_CMD 0xE08
+#define NFC_CONFIG 0xE0A
+#define NFC_ECC_STATUS_RESULT 0xE0C
+#define NFC_RSLTMAIN_AREA 0xE0E
+#define NFC_RSLTSPARE_AREA 0xE10
+#define NFC_WRPROT 0xE12
+#define NFC_UNLOCKSTART_BLKADDR 0xE14
+#define NFC_UNLOCKEND_BLKADDR 0xE16
+#define NFC_NF_WRPRST 0xE18
+#define NFC_CONFIG1 0xE1A
+#define NFC_CONFIG2 0xE1C
+
+/* Addresses for NFC RAM BUFFER Main area 0 */
+#define MAIN_AREA0 0x000
+#define MAIN_AREA1 0x200
+#define MAIN_AREA2 0x400
+#define MAIN_AREA3 0x600
+
+/* Addresses for NFC SPARE BUFFER Spare area 0 */
+#define SPARE_AREA0 0x800
+#define SPARE_AREA1 0x810
+#define SPARE_AREA2 0x820
+#define SPARE_AREA3 0x830
+
+/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation */
+#define NFC_CMD 0x1
+
+/* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation */
+#define NFC_ADDR 0x2
+
+/* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation */
+#define NFC_INPUT 0x4
+
+/* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation */
+#define NFC_OUTPUT 0x8
+
+/* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation */
+#define NFC_ID 0x10
+
+/* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation */
+#define NFC_STATUS 0x20
+
+/* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation */
+#define NFC_INT 0x8000
+
+#define NFC_SP_EN (1 << 2)
+#define NFC_ECC_EN (1 << 3)
+#define NFC_INT_MSK (1 << 4)
+#define NFC_BIG (1 << 5)
+#define NFC_RST (1 << 6)
+#define NFC_CE (1 << 7)
+#define NFC_ONE_CYCLE (1 << 8)
+
+struct mxc_nand_host {
+ struct mtd_info mtd;
+ struct nand_chip nand;
+ struct mtd_partition *parts;
+ struct device *dev;
+
+ void __iomem *regs;
+ int spare_only;
+ int status_request;
+ int pagesize_2k;
+ uint16_t col_addr;
+ struct clk *clk;
+ int clk_act;
+ int irq;
+
+ wait_queue_head_t irq_waitq;
+};
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY 2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x) ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+static struct nand_ecclayout nand_hw_eccoob_8 = {
+ .eccbytes = 5,
+ .eccpos = {6, 7, 8, 9, 10},
+ .oobfree = {{0, 5}, {11, 5}, }
+};
+
+static struct nand_ecclayout nand_hw_eccoob_16 = {
+ .eccbytes = 5,
+ .eccpos = {6, 7, 8, 9, 10},
+ .oobfree = {{0, 6}, {12, 4}, }
+};
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
+#endif
+
+static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
+{
+ struct mxc_nand_host *host = dev_id;
+
+ uint16_t tmp;
+
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp |= NFC_INT_MSK; /* Disable interrupt */
+ writew(tmp, host->regs + NFC_CONFIG1);
+
+ wake_up(&host->irq_waitq);
+
+ return IRQ_HANDLED;
+}
+
+/* This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+ uint16_t param, int useirq)
+{
+ uint32_t tmp;
+
+ if (useirq) {
+ if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
+
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp &= ~NFC_INT_MSK; /* Enable interrupt */
+ writew(tmp, host->regs + NFC_CONFIG1);
+
+ wait_event(host->irq_waitq,
+ readw(host->regs + NFC_CONFIG2) & NFC_INT);
+
+ tmp = readw(host->regs + NFC_CONFIG2);
+ tmp &= ~NFC_INT;
+ writew(tmp, host->regs + NFC_CONFIG2);
+ }
+ } else {
+ while (max_retries-- > 0) {
+ if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
+ tmp = readw(host->regs + NFC_CONFIG2);
+ tmp &= ~NFC_INT;
+ writew(tmp, host->regs + NFC_CONFIG2);
+ break;
+ }
+ udelay(1);
+ }
+ if (max_retries <= 0)
+ DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+ __func__, param);
+ }
+}
+
+/* This function issues the specified command to the NAND device and
+ * waits for completion. */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
+
+ writew(cmd, host->regs + NFC_FLASH_CMD);
+ writew(NFC_CMD, host->regs + NFC_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, cmd, useirq);
+}
+
+/* This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command. */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
+
+ writew(addr, host->regs + NFC_FLASH_ADDR);
+ writew(NFC_ADDR, host->regs + NFC_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, addr, islast);
+}
+
+/* This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device. */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+ int spare_only)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+ /* NANDFC buffer 0 is used for page read/write */
+ writew(buf_id, host->regs + NFC_BUF_ADDR);
+
+ /* Configure spare or page+spare access */
+ if (!host->pagesize_2k) {
+ uint16_t config1 = readw(host->regs + NFC_CONFIG1);
+ if (spare_only)
+ config1 |= NFC_SP_EN;
+ else
+ config1 &= ~(NFC_SP_EN);
+ writew(config1, host->regs + NFC_CONFIG1);
+ }
+
+ writew(NFC_INPUT, host->regs + NFC_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, spare_only, true);
+}
+
+/* Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer. */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+ int spare_only)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+ /* NANDFC buffer 0 is used for page read/write */
+ writew(buf_id, host->regs + NFC_BUF_ADDR);
+
+ /* Configure spare or page+spare access */
+ if (!host->pagesize_2k) {
+ uint32_t config1 = readw(host->regs + NFC_CONFIG1);
+ if (spare_only)
+ config1 |= NFC_SP_EN;
+ else
+ config1 &= ~NFC_SP_EN;
+ writew(config1, host->regs + NFC_CONFIG1);
+ }
+
+ writew(NFC_OUTPUT, host->regs + NFC_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, spare_only, true);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+ struct nand_chip *this = &host->nand;
+ uint16_t tmp;
+
+ /* NANDFC buffer 0 is used for device ID output */
+ writew(0x0, host->regs + NFC_BUF_ADDR);
+
+ /* Read ID into main buffer */
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp &= ~NFC_SP_EN;
+ writew(tmp, host->regs + NFC_CONFIG1);
+
+ writew(NFC_ID, host->regs + NFC_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, 0, true);
+
+ if (this->options & NAND_BUSWIDTH_16) {
+ void __iomem *main_buf = host->regs + MAIN_AREA0;
+ /* compress the ID info */
+ writeb(readb(main_buf + 2), main_buf + 1);
+ writeb(readb(main_buf + 4), main_buf + 2);
+ writeb(readb(main_buf + 6), main_buf + 3);
+ writeb(readb(main_buf + 8), main_buf + 4);
+ writeb(readb(main_buf + 10), main_buf + 5);
+ }
+}
+
+/* This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status. */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+ void __iomem *main_buf = host->regs + MAIN_AREA1;
+ uint32_t store;
+ uint16_t ret, tmp;
+ /* Issue status request to NAND device */
+
+ /* store the main area1 first word, later do recovery */
+ store = readl(main_buf);
+ /* NANDFC buffer 1 is used for device status to prevent
+ * corruption of read/write buffer on status requests. */
+ writew(1, host->regs + NFC_BUF_ADDR);
+
+ /* Read status into main buffer */
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp &= ~NFC_SP_EN;
+ writew(tmp, host->regs + NFC_CONFIG1);
+
+ writew(NFC_STATUS, host->regs + NFC_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, TROP_US_DELAY, 0, true);
+
+ /* Status is placed in first word of main buffer */
+ /* get status, then recovery area 1 data */
+ ret = readw(main_buf);
+ writel(store, main_buf);
+
+ return ret;
+}
+
+/* This functions is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+ /*
+ * NFC handles R/B internally. Therefore, this function
+ * always returns status as ready.
+ */
+ return 1;
+}
+
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+ /*
+ * If HW ECC is enabled, we turn it on during init. There is
+ * no need to enable again here.
+ */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+
+ /*
+ * 1-Bit errors are automatically corrected in HW. No need for
+ * additional correction. 2-Bit errors cannot be corrected by
+ * HW ECC, so we need to return failure
+ */
+ uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
+
+ if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+ u_char *ecc_code)
+{
+ return 0;
+}
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ uint8_t ret = 0;
+ uint16_t col, rd_word;
+ uint16_t __iomem *main_buf = host->regs + MAIN_AREA0;
+ uint16_t __iomem *spare_buf = host->regs + SPARE_AREA0;
+
+ /* Check for status request */
+ if (host->status_request)
+ return get_dev_status(host) & 0xFF;
+
+ /* Get column for 16-bit access */
+ col = host->col_addr >> 1;
+
+ /* If we are accessing the spare region */
+ if (host->spare_only)
+ rd_word = readw(&spare_buf[col]);
+ else
+ rd_word = readw(&main_buf[col]);
+
+ /* Pick upper/lower byte of word from RAM buffer */
+ if (host->col_addr & 0x1)
+ ret = (rd_word >> 8) & 0xFF;
+ else
+ ret = rd_word & 0xFF;
+
+ /* Update saved column address */
+ host->col_addr++;
+
+ return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ uint16_t col, rd_word, ret;
+ uint16_t __iomem *p;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+ col = host->col_addr;
+ /* Adjust saved column address */
+ if (col < mtd->writesize && host->spare_only)
+ col += mtd->writesize;
+
+ if (col < mtd->writesize)
+ p = (host->regs + MAIN_AREA0) + (col >> 1);
+ else
+ p = (host->regs + SPARE_AREA0) + ((col - mtd->writesize) >> 1);
+
+ if (col & 1) {
+ rd_word = readw(p);
+ ret = (rd_word >> 8) & 0xff;
+ rd_word = readw(&p[1]);
+ ret |= (rd_word << 8) & 0xff00;
+
+ } else
+ ret = readw(p);
+
+ /* Update saved column address */
+ host->col_addr = col + 2;
+
+ return ret;
+}
+
+/* Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ int n, col, i = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+ len);
+
+ col = host->col_addr;
+
+ /* Adjust saved column address */
+ if (col < mtd->writesize && host->spare_only)
+ col += mtd->writesize;
+
+ n = mtd->writesize + mtd->oobsize - col;
+ n = min(len, n);
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+ while (n) {
+ void __iomem *p;
+
+ if (col < mtd->writesize)
+ p = host->regs + MAIN_AREA0 + (col & ~3);
+ else
+ p = host->regs + SPARE_AREA0 -
+ mtd->writesize + (col & ~3);
+
+ DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+ __LINE__, p);
+
+ if (((col | (int)&buf[i]) & 3) || n < 16) {
+ uint32_t data = 0;
+
+ if (col & 3 || n < 4)
+ data = readl(p);
+
+ switch (col & 3) {
+ case 0:
+ if (n) {
+ data = (data & 0xffffff00) |
+ (buf[i++] << 0);
+ n--;
+ col++;
+ }
+ case 1:
+ if (n) {
+ data = (data & 0xffff00ff) |
+ (buf[i++] << 8);
+ n--;
+ col++;
+ }
+ case 2:
+ if (n) {
+ data = (data & 0xff00ffff) |
+ (buf[i++] << 16);
+ n--;
+ col++;
+ }
+ case 3:
+ if (n) {
+ data = (data & 0x00ffffff) |
+ (buf[i++] << 24);
+ n--;
+ col++;
+ }
+ }
+
+ writel(data, p);
+ } else {
+ int m = mtd->writesize - col;
+
+ if (col >= mtd->writesize)
+ m += mtd->oobsize;
+
+ m = min(n, m) & ~3;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+ __func__, __LINE__, n, m, i, col);
+
+ memcpy(p, &buf[i], m);
+ col += m;
+ i += m;
+ n -= m;
+ }
+ }
+ /* Update saved column address */
+ host->col_addr = col;
+}
+
+/* Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ int n, col, i = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+ col = host->col_addr;
+
+ /* Adjust saved column address */
+ if (col < mtd->writesize && host->spare_only)
+ col += mtd->writesize;
+
+ n = mtd->writesize + mtd->oobsize - col;
+ n = min(len, n);
+
+ while (n) {
+ void __iomem *p;
+
+ if (col < mtd->writesize)
+ p = host->regs + MAIN_AREA0 + (col & ~3);
+ else
+ p = host->regs + SPARE_AREA0 -
+ mtd->writesize + (col & ~3);
+
+ if (((col | (int)&buf[i]) & 3) || n < 16) {
+ uint32_t data;
+
+ data = readl(p);
+ switch (col & 3) {
+ case 0:
+ if (n) {
+ buf[i++] = (uint8_t) (data);
+ n--;
+ col++;
+ }
+ case 1:
+ if (n) {
+ buf[i++] = (uint8_t) (data >> 8);
+ n--;
+ col++;
+ }
+ case 2:
+ if (n) {
+ buf[i++] = (uint8_t) (data >> 16);
+ n--;
+ col++;
+ }
+ case 3:
+ if (n) {
+ buf[i++] = (uint8_t) (data >> 24);
+ n--;
+ col++;
+ }
+ }
+ } else {
+ int m = mtd->writesize - col;
+
+ if (col >= mtd->writesize)
+ m += mtd->oobsize;
+
+ m = min(n, m) & ~3;
+ memcpy(&buf[i], p, m);
+ col += m;
+ i += m;
+ n -= m;
+ }
+ }
+ /* Update saved column address */
+ host->col_addr = col;
+
+}
+
+/* Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf. */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ return -EFAULT;
+}
+
+/* This function is used by upper layer for select and
+ * deselect of the NAND chip */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+
+#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
+ if (chip > 0) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "ERROR: Illegal chip select (chip = %d)\n", chip);
+ return;
+ }
+
+ if (chip == -1) {
+ writew(readw(host->regs + NFC_CONFIG1) & ~NFC_CE,
+ host->regs + NFC_CONFIG1);
+ return;
+ }
+
+ writew(readw(host->regs + NFC_CONFIG1) | NFC_CE,
+ host->regs + NFC_CONFIG1);
+#endif
+
+ switch (chip) {
+ case -1:
+ /* Disable the NFC clock */
+ if (host->clk_act) {
+ clk_disable(host->clk);
+ host->clk_act = 0;
+ }
+ break;
+ case 0:
+ /* Enable the NFC clock */
+ if (!host->clk_act) {
+ clk_enable(host->clk);
+ host->clk_act = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+ int column, int page_addr)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct mxc_nand_host *host = nand_chip->priv;
+ int useirq = true;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+ command, column, page_addr);
+
+ /* Reset command state information */
+ host->status_request = false;
+
+ /* Command pre-processing step */
+ switch (command) {
+
+ case NAND_CMD_STATUS:
+ host->col_addr = 0;
+ host->status_request = true;
+ break;
+
+ case NAND_CMD_READ0:
+ host->col_addr = column;
+ host->spare_only = false;
+ useirq = false;
+ break;
+
+ case NAND_CMD_READOOB:
+ host->col_addr = column;
+ host->spare_only = true;
+ useirq = false;
+ if (host->pagesize_2k)
+ command = NAND_CMD_READ0; /* only READ0 is valid */
+ break;
+
+ case NAND_CMD_SEQIN:
+ if (column >= mtd->writesize) {
+ /*
+ * FIXME: before send SEQIN command for write OOB,
+ * We must read one page out.
+ * For K9F1GXX has no READ1 command to set current HW
+ * pointer to spare area, we must write the whole page
+ * including OOB together.
+ */
+ if (host->pagesize_2k)
+ /* call ourself to read a page */
+ mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+ page_addr);
+
+ host->col_addr = column - mtd->writesize;
+ host->spare_only = true;
+
+ /* Set program pointer to spare region */
+ if (!host->pagesize_2k)
+ send_cmd(host, NAND_CMD_READOOB, false);
+ } else {
+ host->spare_only = false;
+ host->col_addr = column;
+
+ /* Set program pointer to page start */
+ if (!host->pagesize_2k)
+ send_cmd(host, NAND_CMD_READ0, false);
+ }
+ useirq = false;
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ send_prog_page(host, 0, host->spare_only);
+
+ if (host->pagesize_2k) {
+ /* data in 4 areas datas */
+ send_prog_page(host, 1, host->spare_only);
+ send_prog_page(host, 2, host->spare_only);
+ send_prog_page(host, 3, host->spare_only);
+ }
+
+ break;
+
+ case NAND_CMD_ERASE1:
+ useirq = false;
+ break;
+ }
+
+ /* Write out the command to the device. */
+ send_cmd(host, command, useirq);
+
+ /* Write out column address, if necessary */
+ if (column != -1) {
+ /*
+ * MXC NANDFC can only perform full page+spare or
+ * spare-only read/write. When the upper layers
+ * layers perform a read/write buf operation,
+ * we will used the saved column adress to index into
+ * the full page.
+ */
+ send_addr(host, 0, page_addr == -1);
+ if (host->pagesize_2k)
+ /* another col addr cycle for 2k page */
+ send_addr(host, 0, false);
+ }
+
+ /* Write out page address, if necessary */
+ if (page_addr != -1) {
+ /* paddr_0 - p_addr_7 */
+ send_addr(host, (page_addr & 0xff), false);
+
+ if (host->pagesize_2k) {
+ send_addr(host, (page_addr >> 8) & 0xFF, false);
+ if (mtd->size >= 0x40000000)
+ send_addr(host, (page_addr >> 16) & 0xff, true);
+ } else {
+ /* One more address cycle for higher density devices */
+ if (mtd->size >= 0x4000000) {
+ /* paddr_8 - paddr_15 */
+ send_addr(host, (page_addr >> 8) & 0xff, false);
+ send_addr(host, (page_addr >> 16) & 0xff, true);
+ } else
+ /* paddr_8 - paddr_15 */
+ send_addr(host, (page_addr >> 8) & 0xff, true);
+ }
+ }
+
+ /* Command post-processing step */
+ switch (command) {
+
+ case NAND_CMD_RESET:
+ break;
+
+ case NAND_CMD_READOOB:
+ case NAND_CMD_READ0:
+ if (host->pagesize_2k) {
+ /* send read confirm command */
+ send_cmd(host, NAND_CMD_READSTART, true);
+ /* read for each AREA */
+ send_read_page(host, 0, host->spare_only);
+ send_read_page(host, 1, host->spare_only);
+ send_read_page(host, 2, host->spare_only);
+ send_read_page(host, 3, host->spare_only);
+ } else
+ send_read_page(host, 0, host->spare_only);
+ break;
+
+ case NAND_CMD_READID:
+ send_read_id(host);
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ break;
+
+ case NAND_CMD_STATUS:
+ break;
+
+ case NAND_CMD_ERASE2:
+ break;
+ }
+}
+
+static int __init mxcnd_probe(struct platform_device *pdev)
+{
+ struct nand_chip *this;
+ struct mtd_info *mtd;
+ struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct mxc_nand_host *host;
+ struct resource *res;
+ uint16_t tmp;
+ int err = 0, nr_parts = 0;
+
+ /* Allocate memory for MTD device structure and private data */
+ host = kzalloc(sizeof(struct mxc_nand_host), GFP_KERNEL);
+ if (!host)
+ return -ENOMEM;
+
+ host->dev = &pdev->dev;
+ /* structures must be linked */
+ this = &host->nand;
+ mtd = &host->mtd;
+ mtd->priv = this;
+ mtd->owner = THIS_MODULE;
+
+ /* 50 us command delay time */
+ this->chip_delay = 5;
+
+ this->priv = host;
+ this->dev_ready = mxc_nand_dev_ready;
+ this->cmdfunc = mxc_nand_command;
+ this->select_chip = mxc_nand_select_chip;
+ this->read_byte = mxc_nand_read_byte;
+ this->read_word = mxc_nand_read_word;
+ this->write_buf = mxc_nand_write_buf;
+ this->read_buf = mxc_nand_read_buf;
+ this->verify_buf = mxc_nand_verify_buf;
+
+ host->clk = clk_get(&pdev->dev, "nfc_clk");
+ if (IS_ERR(host->clk))
+ goto eclk;
+
+ clk_enable(host->clk);
+ host->clk_act = 1;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ err = -ENODEV;
+ goto eres;
+ }
+
+ host->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!host->regs) {
+ err = -EIO;
+ goto eres;
+ }
+
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp |= NFC_INT_MSK;
+ writew(tmp, host->regs + NFC_CONFIG1);
+
+ init_waitqueue_head(&host->irq_waitq);
+
+ host->irq = platform_get_irq(pdev, 0);
+
+ err = request_irq(host->irq, mxc_nfc_irq, 0, "mxc_nd", host);
+ if (err)
+ goto eirq;
+
+ if (pdata->hw_ecc) {
+ this->ecc.calculate = mxc_nand_calculate_ecc;
+ this->ecc.hwctl = mxc_nand_enable_hwecc;
+ this->ecc.correct = mxc_nand_correct_data;
+ this->ecc.mode = NAND_ECC_HW;
+ this->ecc.size = 512;
+ this->ecc.bytes = 3;
+ this->ecc.layout = &nand_hw_eccoob_8;
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp |= NFC_ECC_EN;
+ writew(tmp, host->regs + NFC_CONFIG1);
+ } else {
+ this->ecc.size = 512;
+ this->ecc.bytes = 3;
+ this->ecc.layout = &nand_hw_eccoob_8;
+ this->ecc.mode = NAND_ECC_SOFT;
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp &= ~NFC_ECC_EN;
+ writew(tmp, host->regs + NFC_CONFIG1);
+ }
+
+ /* Reset NAND */
+ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+ /* preset operation */
+ /* Unlock the internal RAM Buffer */
+ writew(0x2, host->regs + NFC_CONFIG);
+
+ /* Blocks to be unlocked */
+ writew(0x0, host->regs + NFC_UNLOCKSTART_BLKADDR);
+ writew(0x4000, host->regs + NFC_UNLOCKEND_BLKADDR);
+
+ /* Unlock Block Command for given address range */
+ writew(0x4, host->regs + NFC_WRPROT);
+
+ /* NAND bus width determines access funtions used by upper layer */
+ if (pdata->width == 2) {
+ this->options |= NAND_BUSWIDTH_16;
+ this->ecc.layout = &nand_hw_eccoob_16;
+ }
+
+ host->pagesize_2k = 0;
+
+ /* Scan to find existence of the device */
+ if (nand_scan(mtd, 1)) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "MXC_ND: Unable to find any NAND device.\n");
+ err = -ENXIO;
+ goto escan;
+ }
+
+ /* Register the partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+ nr_parts =
+ parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
+ if (nr_parts > 0)
+ add_mtd_partitions(mtd, host->parts, nr_parts);
+ else
+#endif
+ {
+ pr_info("Registering %s as whole device\n", mtd->name);
+ add_mtd_device(mtd);
+ }
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+
+escan:
+ free_irq(host->irq, NULL);
+eirq:
+ iounmap(host->regs);
+eres:
+ clk_put(host->clk);
+eclk:
+ kfree(host);
+
+ return err;
+}
+
+static int __devexit mxcnd_remove(struct platform_device *pdev)
+{
+ struct mxc_nand_host *host = platform_get_drvdata(pdev);
+
+ clk_put(host->clk);
+
+ platform_set_drvdata(pdev, NULL);
+
+ nand_release(&host->mtd);
+ free_irq(host->irq, NULL);
+ iounmap(host->regs);
+ kfree(host);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mtd_info *info = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
+ if (info)
+ ret = info->suspend(info);
+
+ /* Disable the NFC clock */
+ clk_disable(nfc_clk); /* FIXME */
+
+ return ret;
+}
+
+static int mxcnd_resume(struct platform_device *pdev)
+{
+ struct mtd_info *info = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
+ /* Enable the NFC clock */
+ clk_enable(nfc_clk); /* FIXME */
+
+ if (info)
+ info->resume(info);
+
+ return ret;
+}
+
+#else
+# define mxcnd_suspend NULL
+# define mxcnd_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver mxcnd_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+ .remove = __exit_p(mxcnd_remove),
+ .suspend = mxcnd_suspend,
+ .resume = mxcnd_resume,
+};
+
+static int __init mxc_nd_init(void)
+{
+ /* Register the device driver structure. */
+ pr_info("MXC MTD nand Driver\n");
+ if (platform_driver_probe(&mxcnd_driver, mxcnd_probe) != 0) {
+ printk(KERN_ERR "Driver register failed for mxcnd_driver\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit mxc_nd_cleanup(void)
+{
+ /* Unregister the device structure */
+ platform_driver_unregister(&mxcnd_driver);
+}
+
+module_init(mxc_nd_init);
+module_exit(mxc_nd_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC NAND MTD driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d1129bae6c2..0a9c9cd33f9 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -801,9 +801,9 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
* @mtd: mtd info structure
* @chip: nand chip info structure
- * @dataofs offset of requested data within the page
- * @readlen data length
- * @buf: buffer to store read data
+ * @data_offs: offset of requested data within the page
+ * @readlen: data length
+ * @bufpoi: buffer to store read data
*/
static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
{
@@ -2042,7 +2042,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
return -EINVAL;
}
- instr->fail_addr = 0xffffffff;
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
/* Grab the lock and see if the device is available */
nand_get_device(chip, mtd, FL_ERASING);
@@ -2318,6 +2318,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
/* Select the device */
chip->select_chip(mtd, 0);
+ /*
+ * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
+ * after power-up
+ */
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
@@ -2488,6 +2494,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
/* Check for a chip array */
for (i = 1; i < maxchips; i++) {
chip->select_chip(mtd, i);
+ /* See comment in nand_get_flash_type for reset */
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 918a806a847..868147acce2 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -1,13 +1,18 @@
/*
- * This file contains an ECC algorithm from Toshiba that detects and
- * corrects 1 bit errors in a 256 byte block of data.
+ * This file contains an ECC algorithm that detects and corrects 1 bit
+ * errors in a 256 byte block of data.
*
* drivers/mtd/nand/nand_ecc.c
*
- * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
- * Toshiba America Electronics Components, Inc.
+ * Copyright © 2008 Koninklijke Philips Electronics NV.
+ * Author: Frans Meulenbroeks
*
- * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ * Completely replaces the previous ECC implementation which was written by:
+ * Steven J. Hill (sjhill@realitydiluted.com)
+ * Thomas Gleixner (tglx@linutronix.de)
+ *
+ * Information on how this algorithm works and how it was developed
+ * can be found in Documentation/mtd/nand_ecc.txt
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -23,174 +28,475 @@
* with this file; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
- * As a special exception, if other files instantiate templates or use
- * macros or inline functions from these files, or you compile these
- * files and link them with other works to produce a work based on these
- * files, these files do not by themselves cause the resulting work to be
- * covered by the GNU General Public License. However the source code for
- * these files must still be made available in accordance with section (3)
- * of the GNU General Public License.
- *
- * This exception does not invalidate any other reasons why a work based on
- * this file might be covered by the GNU General Public License.
*/
+/*
+ * The STANDALONE macro is useful when running the code outside the kernel
+ * e.g. when running the code in a testbed or a benchmark program.
+ * When STANDALONE is used, the module related macros are commented out
+ * as well as the linux include files.
+ * Instead a private definition of mtd_info is given to satisfy the compiler
+ * (the code does not use mtd_info, so the code does not care)
+ */
+#ifndef STANDALONE
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
+#include <asm/byteorder.h>
+#else
+#include <stdint.h>
+struct mtd_info;
+#define EXPORT_SYMBOL(x) /* x */
+
+#define MODULE_LICENSE(x) /* x */
+#define MODULE_AUTHOR(x) /* x */
+#define MODULE_DESCRIPTION(x) /* x */
+
+#define printk printf
+#define KERN_ERR ""
+#endif
+
+/*
+ * invparity is a 256 byte table that contains the odd parity
+ * for each byte. So if the number of bits in a byte is even,
+ * the array element is 1, and when the number of bits is odd
+ * the array eleemnt is 0.
+ */
+static const char invparity[256] = {
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+/*
+ * bitsperbyte contains the number of bits per byte
+ * this is only used for testing and repairing parity
+ * (a precalculated value slightly improves performance)
+ */
+static const char bitsperbyte[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+};
/*
- * Pre-calculated 256-way 1 byte column parity
+ * addressbits is a lookup table to filter out the bits from the xor-ed
+ * ecc data that identify the faulty location.
+ * this is only used for repairing parity
+ * see the comments in nand_correct_data for more details
*/
-static const u_char nand_ecc_precalc_table[] = {
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+static const char addressbits[256] = {
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+ 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+ 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+ 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+ 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+ 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+ 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+ 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+ 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+ 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+ 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+ 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+ 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+ 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+ 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
+ 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+ 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
+ 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+ 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+ 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+ 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+ 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+ 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
+ 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+ 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f
};
/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
+ * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
+ * block
* @mtd: MTD block structure
- * @dat: raw data
- * @ecc_code: buffer for ECC
+ * @buf: input buffer with raw data
+ * @code: output buffer with ECC
*/
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
+int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+ unsigned char *code)
{
- uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
int i;
+ const uint32_t *bp = (uint32_t *)buf;
+ /* 256 or 512 bytes/ecc */
+ const uint32_t eccsize_mult =
+ (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
+ uint32_t cur; /* current value in buffer */
+ /* rp0..rp15..rp17 are the various accumulated parities (per byte) */
+ uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
+ uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
+ uint32_t uninitialized_var(rp17); /* to make compiler happy */
+ uint32_t par; /* the cumulative parity for all data */
+ uint32_t tmppar; /* the cumulative parity for this iteration;
+ for rp12, rp14 and rp16 at the end of the
+ loop */
+
+ par = 0;
+ rp4 = 0;
+ rp6 = 0;
+ rp8 = 0;
+ rp10 = 0;
+ rp12 = 0;
+ rp14 = 0;
+ rp16 = 0;
+
+ /*
+ * The loop is unrolled a number of times;
+ * This avoids if statements to decide on which rp value to update
+ * Also we process the data by longwords.
+ * Note: passing unaligned data might give a performance penalty.
+ * It is assumed that the buffers are aligned.
+ * tmppar is the cumulative sum of this iteration.
+ * needed for calculating rp12, rp14, rp16 and par
+ * also used as a performance improvement for rp6, rp8 and rp10
+ */
+ for (i = 0; i < eccsize_mult << 2; i++) {
+ cur = *bp++;
+ tmppar = cur;
+ rp4 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp6 ^= tmppar;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp8 ^= tmppar;
- /* Initialize variables */
- reg1 = reg2 = reg3 = 0;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ rp6 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp6 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp10 ^= tmppar;
- /* Build up column parity */
- for(i = 0; i < 256; i++) {
- /* Get CP0 - CP5 from table */
- idx = nand_ecc_precalc_table[*dat++];
- reg1 ^= (idx & 0x3f);
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ rp6 ^= cur;
+ rp8 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp6 ^= cur;
+ rp8 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ rp8 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp8 ^= cur;
- /* All bit XOR = 1 ? */
- if (idx & 0x40) {
- reg3 ^= (uint8_t) i;
- reg2 ^= ~((uint8_t) i);
- }
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ rp6 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp6 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+ rp4 ^= cur;
+ cur = *bp++;
+ tmppar ^= cur;
+
+ par ^= tmppar;
+ if ((i & 0x1) == 0)
+ rp12 ^= tmppar;
+ if ((i & 0x2) == 0)
+ rp14 ^= tmppar;
+ if (eccsize_mult == 2 && (i & 0x4) == 0)
+ rp16 ^= tmppar;
}
- /* Create non-inverted ECC code from line parity */
- tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
- tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
- tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
- tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
- tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
- tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
- tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
- tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
-
- tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
- tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
- tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
- tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
- tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
- tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
- tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
- tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
-
- /* Calculate final ECC code */
-#ifdef CONFIG_MTD_NAND_ECC_SMC
- ecc_code[0] = ~tmp2;
- ecc_code[1] = ~tmp1;
+ /*
+ * handle the fact that we use longword operations
+ * we'll bring rp4..rp14..rp16 back to single byte entities by
+ * shifting and xoring first fold the upper and lower 16 bits,
+ * then the upper and lower 8 bits.
+ */
+ rp4 ^= (rp4 >> 16);
+ rp4 ^= (rp4 >> 8);
+ rp4 &= 0xff;
+ rp6 ^= (rp6 >> 16);
+ rp6 ^= (rp6 >> 8);
+ rp6 &= 0xff;
+ rp8 ^= (rp8 >> 16);
+ rp8 ^= (rp8 >> 8);
+ rp8 &= 0xff;
+ rp10 ^= (rp10 >> 16);
+ rp10 ^= (rp10 >> 8);
+ rp10 &= 0xff;
+ rp12 ^= (rp12 >> 16);
+ rp12 ^= (rp12 >> 8);
+ rp12 &= 0xff;
+ rp14 ^= (rp14 >> 16);
+ rp14 ^= (rp14 >> 8);
+ rp14 &= 0xff;
+ if (eccsize_mult == 2) {
+ rp16 ^= (rp16 >> 16);
+ rp16 ^= (rp16 >> 8);
+ rp16 &= 0xff;
+ }
+
+ /*
+ * we also need to calculate the row parity for rp0..rp3
+ * This is present in par, because par is now
+ * rp3 rp3 rp2 rp2 in little endian and
+ * rp2 rp2 rp3 rp3 in big endian
+ * as well as
+ * rp1 rp0 rp1 rp0 in little endian and
+ * rp0 rp1 rp0 rp1 in big endian
+ * First calculate rp2 and rp3
+ */
+#ifdef __BIG_ENDIAN
+ rp2 = (par >> 16);
+ rp2 ^= (rp2 >> 8);
+ rp2 &= 0xff;
+ rp3 = par & 0xffff;
+ rp3 ^= (rp3 >> 8);
+ rp3 &= 0xff;
#else
- ecc_code[0] = ~tmp1;
- ecc_code[1] = ~tmp2;
+ rp3 = (par >> 16);
+ rp3 ^= (rp3 >> 8);
+ rp3 &= 0xff;
+ rp2 = par & 0xffff;
+ rp2 ^= (rp2 >> 8);
+ rp2 &= 0xff;
#endif
- ecc_code[2] = ((~reg1) << 2) | 0x03;
- return 0;
-}
-EXPORT_SYMBOL(nand_calculate_ecc);
+ /* reduce par to 16 bits then calculate rp1 and rp0 */
+ par ^= (par >> 16);
+#ifdef __BIG_ENDIAN
+ rp0 = (par >> 8) & 0xff;
+ rp1 = (par & 0xff);
+#else
+ rp1 = (par >> 8) & 0xff;
+ rp0 = (par & 0xff);
+#endif
-static inline int countbits(uint32_t byte)
-{
- int res = 0;
+ /* finally reduce par to 8 bits */
+ par ^= (par >> 8);
+ par &= 0xff;
- for (;byte; byte >>= 1)
- res += byte & 0x01;
- return res;
+ /*
+ * and calculate rp5..rp15..rp17
+ * note that par = rp4 ^ rp5 and due to the commutative property
+ * of the ^ operator we can say:
+ * rp5 = (par ^ rp4);
+ * The & 0xff seems superfluous, but benchmarking learned that
+ * leaving it out gives slightly worse results. No idea why, probably
+ * it has to do with the way the pipeline in pentium is organized.
+ */
+ rp5 = (par ^ rp4) & 0xff;
+ rp7 = (par ^ rp6) & 0xff;
+ rp9 = (par ^ rp8) & 0xff;
+ rp11 = (par ^ rp10) & 0xff;
+ rp13 = (par ^ rp12) & 0xff;
+ rp15 = (par ^ rp14) & 0xff;
+ if (eccsize_mult == 2)
+ rp17 = (par ^ rp16) & 0xff;
+
+ /*
+ * Finally calculate the ecc bits.
+ * Again here it might seem that there are performance optimisations
+ * possible, but benchmarks showed that on the system this is developed
+ * the code below is the fastest
+ */
+#ifdef CONFIG_MTD_NAND_ECC_SMC
+ code[0] =
+ (invparity[rp7] << 7) |
+ (invparity[rp6] << 6) |
+ (invparity[rp5] << 5) |
+ (invparity[rp4] << 4) |
+ (invparity[rp3] << 3) |
+ (invparity[rp2] << 2) |
+ (invparity[rp1] << 1) |
+ (invparity[rp0]);
+ code[1] =
+ (invparity[rp15] << 7) |
+ (invparity[rp14] << 6) |
+ (invparity[rp13] << 5) |
+ (invparity[rp12] << 4) |
+ (invparity[rp11] << 3) |
+ (invparity[rp10] << 2) |
+ (invparity[rp9] << 1) |
+ (invparity[rp8]);
+#else
+ code[1] =
+ (invparity[rp7] << 7) |
+ (invparity[rp6] << 6) |
+ (invparity[rp5] << 5) |
+ (invparity[rp4] << 4) |
+ (invparity[rp3] << 3) |
+ (invparity[rp2] << 2) |
+ (invparity[rp1] << 1) |
+ (invparity[rp0]);
+ code[0] =
+ (invparity[rp15] << 7) |
+ (invparity[rp14] << 6) |
+ (invparity[rp13] << 5) |
+ (invparity[rp12] << 4) |
+ (invparity[rp11] << 3) |
+ (invparity[rp10] << 2) |
+ (invparity[rp9] << 1) |
+ (invparity[rp8]);
+#endif
+ if (eccsize_mult == 1)
+ code[2] =
+ (invparity[par & 0xf0] << 7) |
+ (invparity[par & 0x0f] << 6) |
+ (invparity[par & 0xcc] << 5) |
+ (invparity[par & 0x33] << 4) |
+ (invparity[par & 0xaa] << 3) |
+ (invparity[par & 0x55] << 2) |
+ 3;
+ else
+ code[2] =
+ (invparity[par & 0xf0] << 7) |
+ (invparity[par & 0x0f] << 6) |
+ (invparity[par & 0xcc] << 5) |
+ (invparity[par & 0x33] << 4) |
+ (invparity[par & 0xaa] << 3) |
+ (invparity[par & 0x55] << 2) |
+ (invparity[rp17] << 1) |
+ (invparity[rp16] << 0);
+ return 0;
}
+EXPORT_SYMBOL(nand_calculate_ecc);
/**
* nand_correct_data - [NAND Interface] Detect and correct bit error(s)
* @mtd: MTD block structure
- * @dat: raw data read from the chip
+ * @buf: raw data read from the chip
* @read_ecc: ECC from the chip
* @calc_ecc: the ECC calculated from raw data
*
- * Detect and correct a 1 bit error for 256 byte block
+ * Detect and correct a 1 bit error for 256/512 byte block
*/
-int nand_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
+int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
+ unsigned char *read_ecc, unsigned char *calc_ecc)
{
- uint8_t s0, s1, s2;
+ unsigned char b0, b1, b2;
+ unsigned char byte_addr, bit_addr;
+ /* 256 or 512 bytes/ecc */
+ const uint32_t eccsize_mult =
+ (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
+ /*
+ * b0 to b2 indicate which bit is faulty (if any)
+ * we might need the xor result more than once,
+ * so keep them in a local var
+ */
#ifdef CONFIG_MTD_NAND_ECC_SMC
- s0 = calc_ecc[0] ^ read_ecc[0];
- s1 = calc_ecc[1] ^ read_ecc[1];
- s2 = calc_ecc[2] ^ read_ecc[2];
+ b0 = read_ecc[0] ^ calc_ecc[0];
+ b1 = read_ecc[1] ^ calc_ecc[1];
#else
- s1 = calc_ecc[0] ^ read_ecc[0];
- s0 = calc_ecc[1] ^ read_ecc[1];
- s2 = calc_ecc[2] ^ read_ecc[2];
+ b0 = read_ecc[1] ^ calc_ecc[1];
+ b1 = read_ecc[0] ^ calc_ecc[0];
#endif
- if ((s0 | s1 | s2) == 0)
- return 0;
-
- /* Check for a single bit error */
- if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
- ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
- ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
+ b2 = read_ecc[2] ^ calc_ecc[2];
- uint32_t byteoffs, bitnum;
+ /* check if there are any bitfaults */
- byteoffs = (s1 << 0) & 0x80;
- byteoffs |= (s1 << 1) & 0x40;
- byteoffs |= (s1 << 2) & 0x20;
- byteoffs |= (s1 << 3) & 0x10;
+ /* repeated if statements are slightly more efficient than switch ... */
+ /* ordered in order of likelihood */
- byteoffs |= (s0 >> 4) & 0x08;
- byteoffs |= (s0 >> 3) & 0x04;
- byteoffs |= (s0 >> 2) & 0x02;
- byteoffs |= (s0 >> 1) & 0x01;
-
- bitnum = (s2 >> 5) & 0x04;
- bitnum |= (s2 >> 4) & 0x02;
- bitnum |= (s2 >> 3) & 0x01;
-
- dat[byteoffs] ^= (1 << bitnum);
+ if ((b0 | b1 | b2) == 0)
+ return 0; /* no error */
+ if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) &&
+ (((b1 ^ (b1 >> 1)) & 0x55) == 0x55) &&
+ ((eccsize_mult == 1 && ((b2 ^ (b2 >> 1)) & 0x54) == 0x54) ||
+ (eccsize_mult == 2 && ((b2 ^ (b2 >> 1)) & 0x55) == 0x55))) {
+ /* single bit error */
+ /*
+ * rp17/rp15/13/11/9/7/5/3/1 indicate which byte is the faulty
+ * byte, cp 5/3/1 indicate the faulty bit.
+ * A lookup table (called addressbits) is used to filter
+ * the bits from the byte they are in.
+ * A marginal optimisation is possible by having three
+ * different lookup tables.
+ * One as we have now (for b0), one for b2
+ * (that would avoid the >> 1), and one for b1 (with all values
+ * << 4). However it was felt that introducing two more tables
+ * hardly justify the gain.
+ *
+ * The b2 shift is there to get rid of the lowest two bits.
+ * We could also do addressbits[b2] >> 1 but for the
+ * performace it does not make any difference
+ */
+ if (eccsize_mult == 1)
+ byte_addr = (addressbits[b1] << 4) + addressbits[b0];
+ else
+ byte_addr = (addressbits[b2 & 0x3] << 8) +
+ (addressbits[b1] << 4) + addressbits[b0];
+ bit_addr = addressbits[b2 >> 2];
+ /* flip the bit */
+ buf[byte_addr] ^= (1 << bit_addr);
return 1;
- }
- if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
- return 1;
+ }
+ /* count nr of bits; use table lookup, faster than calculating it */
+ if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
+ return 1; /* error in ecc data; no action needed */
- return -EBADMSG;
+ printk(KERN_ERR "uncorrectable error : ");
+ return -1;
}
EXPORT_SYMBOL(nand_correct_data);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>");
MODULE_DESCRIPTION("Generic NAND ECC support");
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 556e8131ecd..ae7c57781a6 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -38,7 +38,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/random.h>
-#include <asm/div64.h>
/* Default simulator parameters values */
#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index a64ad15b8fd..c0fa9c9edf0 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -115,55 +115,11 @@ enum {
STATE_PIO_WRITING,
};
-struct pxa3xx_nand_timing {
- unsigned int tCH; /* Enable signal hold time */
- unsigned int tCS; /* Enable signal setup time */
- unsigned int tWH; /* ND_nWE high duration */
- unsigned int tWP; /* ND_nWE pulse time */
- unsigned int tRH; /* ND_nRE high duration */
- unsigned int tRP; /* ND_nRE pulse width */
- unsigned int tR; /* ND_nWE high to ND_nRE low for read */
- unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */
- unsigned int tAR; /* ND_ALE low to ND_nRE low delay */
-};
-
-struct pxa3xx_nand_cmdset {
- uint16_t read1;
- uint16_t read2;
- uint16_t program;
- uint16_t read_status;
- uint16_t read_id;
- uint16_t erase;
- uint16_t reset;
- uint16_t lock;
- uint16_t unlock;
- uint16_t lock_status;
-};
-
-struct pxa3xx_nand_flash {
- struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
- struct pxa3xx_nand_cmdset *cmdset;
-
- uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
- uint32_t page_size; /* Page size in bytes (PAGE_SZ) */
- uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */
- uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */
- uint32_t num_blocks; /* Number of physical blocks in Flash */
- uint32_t chip_id;
-
- /* NOTE: these are automatically calculated, do not define */
- size_t oob_size;
- size_t read_id_bytes;
-
- unsigned int col_addr_cycles;
- unsigned int row_addr_cycles;
-};
-
struct pxa3xx_nand_info {
struct nand_chip nand_chip;
struct platform_device *pdev;
- struct pxa3xx_nand_flash *flash_info;
+ const struct pxa3xx_nand_flash *flash_info;
struct clk *clk;
void __iomem *mmio_base;
@@ -202,12 +158,20 @@ struct pxa3xx_nand_info {
uint32_t ndcb0;
uint32_t ndcb1;
uint32_t ndcb2;
+
+ /* calculated from pxa3xx_nand_flash data */
+ size_t oob_size;
+ size_t read_id_bytes;
+
+ unsigned int col_addr_cycles;
+ unsigned int row_addr_cycles;
};
static int use_dma = 1;
module_param(use_dma, bool, 0444);
MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
+#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN
static struct pxa3xx_nand_cmdset smallpage_cmdset = {
.read1 = 0x0000,
.read2 = 0x0050,
@@ -291,11 +255,35 @@ static struct pxa3xx_nand_flash micron1GbX16 = {
.chip_id = 0xb12c,
};
+static struct pxa3xx_nand_timing stm2GbX16_timing = {
+ .tCH = 10,
+ .tCS = 35,
+ .tWH = 15,
+ .tWP = 25,
+ .tRH = 15,
+ .tRP = 25,
+ .tR = 25000,
+ .tWHR = 60,
+ .tAR = 10,
+};
+
+static struct pxa3xx_nand_flash stm2GbX16 = {
+ .timing = &stm2GbX16_timing,
+ .page_per_block = 64,
+ .page_size = 2048,
+ .flash_width = 16,
+ .dfc_width = 16,
+ .num_blocks = 2048,
+ .chip_id = 0xba20,
+};
+
static struct pxa3xx_nand_flash *builtin_flash_types[] = {
&samsung512MbX16,
&micron1GbX8,
&micron1GbX16,
+ &stm2GbX16,
};
+#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */
#define NDTR0_tCH(c) (min((c), 7) << 19)
#define NDTR0_tCS(c) (min((c), 7) << 16)
@@ -312,7 +300,7 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = {
#define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1)
static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
- struct pxa3xx_nand_timing *t)
+ const struct pxa3xx_nand_timing *t)
{
unsigned long nand_clk = clk_get_rate(info->clk);
uint32_t ndtr0, ndtr1;
@@ -354,8 +342,8 @@ static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
uint16_t cmd, int column, int page_addr)
{
- struct pxa3xx_nand_flash *f = info->flash_info;
- struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+ const struct pxa3xx_nand_flash *f = info->flash_info;
+ const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
/* calculate data size */
switch (f->page_size) {
@@ -373,14 +361,14 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
info->ndcb1 = 0;
info->ndcb2 = 0;
- info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles);
+ info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
- if (f->col_addr_cycles == 2) {
+ if (info->col_addr_cycles == 2) {
/* large block, 2 cycles for column address
* row address starts from 3rd cycle
*/
info->ndcb1 |= (page_addr << 16) | (column & 0xffff);
- if (f->row_addr_cycles == 3)
+ if (info->row_addr_cycles == 3)
info->ndcb2 = (page_addr >> 16) & 0xff;
} else
/* small block, 1 cycles for column address
@@ -406,7 +394,7 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
{
- struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
+ const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
info->ndcb1 = 0;
@@ -641,8 +629,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
int column, int page_addr)
{
struct pxa3xx_nand_info *info = mtd->priv;
- struct pxa3xx_nand_flash *flash_info = info->flash_info;
- struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
+ const struct pxa3xx_nand_flash *flash_info = info->flash_info;
+ const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
int ret;
info->use_dma = (use_dma) ? 1 : 0;
@@ -720,7 +708,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
info->use_dma = 0; /* force PIO read */
info->buf_start = 0;
info->buf_count = (command == NAND_CMD_READID) ?
- flash_info->read_id_bytes : 1;
+ info->read_id_bytes : 1;
if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
cmdset->read_id : cmdset->read_status))
@@ -861,8 +849,8 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
{
- struct pxa3xx_nand_flash *f = info->flash_info;
- struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+ const struct pxa3xx_nand_flash *f = info->flash_info;
+ const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
uint32_t ndcr;
uint8_t id_buff[8];
@@ -891,7 +879,7 @@ fail_timeout:
}
static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
- struct pxa3xx_nand_flash *f)
+ const struct pxa3xx_nand_flash *f)
{
struct platform_device *pdev = info->pdev;
struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
@@ -904,25 +892,25 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
return -EINVAL;
/* calculate flash information */
- f->oob_size = (f->page_size == 2048) ? 64 : 16;
- f->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+ info->oob_size = (f->page_size == 2048) ? 64 : 16;
+ info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
/* calculate addressing information */
- f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+ info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
if (f->num_blocks * f->page_per_block > 65536)
- f->row_addr_cycles = 3;
+ info->row_addr_cycles = 3;
else
- f->row_addr_cycles = 2;
+ info->row_addr_cycles = 2;
ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
- ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+ ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
- ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes);
+ ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
ndcr |= NDCR_SPARE_EN; /* enable spare by default */
info->reg_ndcr = ndcr;
@@ -932,12 +920,27 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
return 0;
}
-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
+ const struct pxa3xx_nand_platform_data *pdata)
{
- struct pxa3xx_nand_flash *f;
- uint32_t id;
+ const struct pxa3xx_nand_flash *f;
+ uint32_t id = -1;
int i;
+ for (i = 0; i<pdata->num_flash; ++i) {
+ f = pdata->flash + i;
+
+ if (pxa3xx_nand_config_flash(info, f))
+ continue;
+
+ if (__readid(info, &id))
+ continue;
+
+ if (id == f->chip_id)
+ return 0;
+ }
+
+#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN
for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
f = builtin_flash_types[i];
@@ -951,7 +954,11 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
if (id == f->chip_id)
return 0;
}
+#endif
+ dev_warn(&info->pdev->dev,
+ "failed to detect configured nand flash; found %04x instead of\n",
+ id);
return -ENODEV;
}
@@ -1014,7 +1021,7 @@ static struct nand_ecclayout hw_largepage_ecclayout = {
static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
struct pxa3xx_nand_info *info)
{
- struct pxa3xx_nand_flash *f = info->flash_info;
+ const struct pxa3xx_nand_flash *f = info->flash_info;
struct nand_chip *this = &info->nand_chip;
this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
@@ -1135,7 +1142,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
goto fail_free_buf;
}
- ret = pxa3xx_nand_detect_flash(info);
+ ret = pxa3xx_nand_detect_flash(info, pdata);
if (ret) {
dev_err(&pdev->dev, "failed to detect flash\n");
ret = -ENODEV;
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
new file mode 100644
index 00000000000..821acb08ff1
--- /dev/null
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -0,0 +1,878 @@
+/*
+ * SuperH FLCTL nand controller
+ *
+ * Copyright © 2008 Renesas Solutions Corp.
+ * Copyright © 2008 Atom Create Engineering Co., Ltd.
+ *
+ * Based on fsl_elbc_nand.c, Copyright © 2006-2007 Freescale Semiconductor
+ *
+ * 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.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/sh_flctl.h>
+
+static struct nand_ecclayout flctl_4secc_oob_16 = {
+ .eccbytes = 10,
+ .eccpos = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+ .oobfree = {
+ {.offset = 12,
+ . length = 4} },
+};
+
+static struct nand_ecclayout flctl_4secc_oob_64 = {
+ .eccbytes = 10,
+ .eccpos = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57},
+ .oobfree = {
+ {.offset = 60,
+ . length = 4} },
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr flctl_4secc_smallpage = {
+ .options = NAND_BBT_SCAN2NDPAGE,
+ .offs = 11,
+ .len = 1,
+ .pattern = scan_ff_pattern,
+};
+
+static struct nand_bbt_descr flctl_4secc_largepage = {
+ .options = 0,
+ .offs = 58,
+ .len = 2,
+ .pattern = scan_ff_pattern,
+};
+
+static void empty_fifo(struct sh_flctl *flctl)
+{
+ writel(0x000c0000, FLINTDMACR(flctl)); /* FIFO Clear */
+ writel(0x00000000, FLINTDMACR(flctl)); /* Clear Error flags */
+}
+
+static void start_translation(struct sh_flctl *flctl)
+{
+ writeb(TRSTRT, FLTRCR(flctl));
+}
+
+static void wait_completion(struct sh_flctl *flctl)
+{
+ uint32_t timeout = LOOP_TIMEOUT_MAX;
+
+ while (timeout--) {
+ if (readb(FLTRCR(flctl)) & TREND) {
+ writeb(0x0, FLTRCR(flctl));
+ return;
+ }
+ udelay(1);
+ }
+
+ printk(KERN_ERR "wait_completion(): Timeout occured \n");
+ writeb(0x0, FLTRCR(flctl));
+}
+
+static void set_addr(struct mtd_info *mtd, int column, int page_addr)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ uint32_t addr = 0;
+
+ if (column == -1) {
+ addr = page_addr; /* ERASE1 */
+ } else if (page_addr != -1) {
+ /* SEQIN, READ0, etc.. */
+ if (flctl->page_size) {
+ addr = column & 0x0FFF;
+ addr |= (page_addr & 0xff) << 16;
+ addr |= ((page_addr >> 8) & 0xff) << 24;
+ /* big than 128MB */
+ if (flctl->rw_ADRCNT == ADRCNT2_E) {
+ uint32_t addr2;
+ addr2 = (page_addr >> 16) & 0xff;
+ writel(addr2, FLADR2(flctl));
+ }
+ } else {
+ addr = column;
+ addr |= (page_addr & 0xff) << 8;
+ addr |= ((page_addr >> 8) & 0xff) << 16;
+ addr |= ((page_addr >> 16) & 0xff) << 24;
+ }
+ }
+ writel(addr, FLADR(flctl));
+}
+
+static void wait_rfifo_ready(struct sh_flctl *flctl)
+{
+ uint32_t timeout = LOOP_TIMEOUT_MAX;
+
+ while (timeout--) {
+ uint32_t val;
+ /* check FIFO */
+ val = readl(FLDTCNTR(flctl)) >> 16;
+ if (val & 0xFF)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "wait_rfifo_ready(): Timeout occured \n");
+}
+
+static void wait_wfifo_ready(struct sh_flctl *flctl)
+{
+ uint32_t len, timeout = LOOP_TIMEOUT_MAX;
+
+ while (timeout--) {
+ /* check FIFO */
+ len = (readl(FLDTCNTR(flctl)) >> 16) & 0xFF;
+ if (len >= 4)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "wait_wfifo_ready(): Timeout occured \n");
+}
+
+static int wait_recfifo_ready(struct sh_flctl *flctl)
+{
+ uint32_t timeout = LOOP_TIMEOUT_MAX;
+ int checked[4];
+ void __iomem *ecc_reg[4];
+ int i;
+ uint32_t data, size;
+
+ memset(checked, 0, sizeof(checked));
+
+ while (timeout--) {
+ size = readl(FLDTCNTR(flctl)) >> 24;
+ if (size & 0xFF)
+ return 0; /* success */
+
+ if (readl(FL4ECCCR(flctl)) & _4ECCFA)
+ return 1; /* can't correct */
+
+ udelay(1);
+ if (!(readl(FL4ECCCR(flctl)) & _4ECCEND))
+ continue;
+
+ /* start error correction */
+ ecc_reg[0] = FL4ECCRESULT0(flctl);
+ ecc_reg[1] = FL4ECCRESULT1(flctl);
+ ecc_reg[2] = FL4ECCRESULT2(flctl);
+ ecc_reg[3] = FL4ECCRESULT3(flctl);
+
+ for (i = 0; i < 3; i++) {
+ data = readl(ecc_reg[i]);
+ if (data != INIT_FL4ECCRESULT_VAL && !checked[i]) {
+ uint8_t org;
+ int index;
+
+ index = data >> 16;
+ org = flctl->done_buff[index];
+ flctl->done_buff[index] = org ^ (data & 0xFF);
+ checked[i] = 1;
+ }
+ }
+
+ writel(0, FL4ECCCR(flctl));
+ }
+
+ printk(KERN_ERR "wait_recfifo_ready(): Timeout occured \n");
+ return 1; /* timeout */
+}
+
+static void wait_wecfifo_ready(struct sh_flctl *flctl)
+{
+ uint32_t timeout = LOOP_TIMEOUT_MAX;
+ uint32_t len;
+
+ while (timeout--) {
+ /* check FLECFIFO */
+ len = (readl(FLDTCNTR(flctl)) >> 24) & 0xFF;
+ if (len >= 4)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "wait_wecfifo_ready(): Timeout occured \n");
+}
+
+static void read_datareg(struct sh_flctl *flctl, int offset)
+{
+ unsigned long data;
+ unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
+
+ wait_completion(flctl);
+
+ data = readl(FLDATAR(flctl));
+ *buf = le32_to_cpu(data);
+}
+
+static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+{
+ int i, len_4align;
+ unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
+ void *fifo_addr = (void *)FLDTFIFO(flctl);
+
+ len_4align = (rlen + 3) / 4;
+
+ for (i = 0; i < len_4align; i++) {
+ wait_rfifo_ready(flctl);
+ buf[i] = readl(fifo_addr);
+ buf[i] = be32_to_cpu(buf[i]);
+ }
+}
+
+static int read_ecfiforeg(struct sh_flctl *flctl, uint8_t *buff)
+{
+ int i;
+ unsigned long *ecc_buf = (unsigned long *)buff;
+ void *fifo_addr = (void *)FLECFIFO(flctl);
+
+ for (i = 0; i < 4; i++) {
+ if (wait_recfifo_ready(flctl))
+ return 1;
+ ecc_buf[i] = readl(fifo_addr);
+ ecc_buf[i] = be32_to_cpu(ecc_buf[i]);
+ }
+
+ return 0;
+}
+
+static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+{
+ int i, len_4align;
+ unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
+ void *fifo_addr = (void *)FLDTFIFO(flctl);
+
+ len_4align = (rlen + 3) / 4;
+ for (i = 0; i < len_4align; i++) {
+ wait_wfifo_ready(flctl);
+ writel(cpu_to_be32(data[i]), fifo_addr);
+ }
+}
+
+static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ uint32_t flcmncr_val = readl(FLCMNCR(flctl));
+ uint32_t flcmdcr_val, addr_len_bytes = 0;
+
+ /* Set SNAND bit if page size is 2048byte */
+ if (flctl->page_size)
+ flcmncr_val |= SNAND_E;
+ else
+ flcmncr_val &= ~SNAND_E;
+
+ /* default FLCMDCR val */
+ flcmdcr_val = DOCMD1_E | DOADR_E;
+
+ /* Set for FLCMDCR */
+ switch (cmd) {
+ case NAND_CMD_ERASE1:
+ addr_len_bytes = flctl->erase_ADRCNT;
+ flcmdcr_val |= DOCMD2_E;
+ break;
+ case NAND_CMD_READ0:
+ case NAND_CMD_READOOB:
+ addr_len_bytes = flctl->rw_ADRCNT;
+ flcmdcr_val |= CDSRC_E;
+ break;
+ case NAND_CMD_SEQIN:
+ /* This case is that cmd is READ0 or READ1 or READ00 */
+ flcmdcr_val &= ~DOADR_E; /* ONLY execute 1st cmd */
+ break;
+ case NAND_CMD_PAGEPROG:
+ addr_len_bytes = flctl->rw_ADRCNT;
+ flcmdcr_val |= DOCMD2_E | CDSRC_E | SELRW;
+ break;
+ case NAND_CMD_READID:
+ flcmncr_val &= ~SNAND_E;
+ addr_len_bytes = ADRCNT_1;
+ break;
+ case NAND_CMD_STATUS:
+ case NAND_CMD_RESET:
+ flcmncr_val &= ~SNAND_E;
+ flcmdcr_val &= ~(DOADR_E | DOSR_E);
+ break;
+ default:
+ break;
+ }
+
+ /* Set address bytes parameter */
+ flcmdcr_val |= addr_len_bytes;
+
+ /* Now actually write */
+ writel(flcmncr_val, FLCMNCR(flctl));
+ writel(flcmdcr_val, FLCMDCR(flctl));
+ writel(flcmcdr_val, FLCMCDR(flctl));
+}
+
+static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+ chip->read_buf(mtd, p, eccsize);
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ if (flctl->hwecc_cant_correct[i])
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += 0;
+ }
+
+ return 0;
+}
+
+static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ const uint8_t *p = buf;
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+ chip->write_buf(mtd, p, eccsize);
+}
+
+static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ int sector, page_sectors;
+
+ if (flctl->page_size)
+ page_sectors = 4;
+ else
+ page_sectors = 1;
+
+ writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT,
+ FLCMNCR(flctl));
+
+ set_cmd_regs(mtd, NAND_CMD_READ0,
+ (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
+
+ for (sector = 0; sector < page_sectors; sector++) {
+ int ret;
+
+ empty_fifo(flctl);
+ writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
+ writel(page_addr << 2 | sector, FLADR(flctl));
+
+ start_translation(flctl);
+ read_fiforeg(flctl, 512, 512 * sector);
+
+ ret = read_ecfiforeg(flctl,
+ &flctl->done_buff[mtd->writesize + 16 * sector]);
+
+ if (ret)
+ flctl->hwecc_cant_correct[sector] = 1;
+
+ writel(0x0, FL4ECCCR(flctl));
+ wait_completion(flctl);
+ }
+ writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT),
+ FLCMNCR(flctl));
+}
+
+static void execmd_read_oob(struct mtd_info *mtd, int page_addr)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+
+ set_cmd_regs(mtd, NAND_CMD_READ0,
+ (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
+
+ empty_fifo(flctl);
+ if (flctl->page_size) {
+ int i;
+ /* In case that the page size is 2k */
+ for (i = 0; i < 16 * 3; i++)
+ flctl->done_buff[i] = 0xFF;
+
+ set_addr(mtd, 3 * 528 + 512, page_addr);
+ writel(16, FLDTCNTR(flctl));
+
+ start_translation(flctl);
+ read_fiforeg(flctl, 16, 16 * 3);
+ wait_completion(flctl);
+ } else {
+ /* In case that the page size is 512b */
+ set_addr(mtd, 512, page_addr);
+ writel(16, FLDTCNTR(flctl));
+
+ start_translation(flctl);
+ read_fiforeg(flctl, 16, 0);
+ wait_completion(flctl);
+ }
+}
+
+static void execmd_write_page_sector(struct mtd_info *mtd)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ int i, page_addr = flctl->seqin_page_addr;
+ int sector, page_sectors;
+
+ if (flctl->page_size)
+ page_sectors = 4;
+ else
+ page_sectors = 1;
+
+ writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl));
+
+ set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
+ (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
+
+ for (sector = 0; sector < page_sectors; sector++) {
+ empty_fifo(flctl);
+ writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
+ writel(page_addr << 2 | sector, FLADR(flctl));
+
+ start_translation(flctl);
+ write_fiforeg(flctl, 512, 512 * sector);
+
+ for (i = 0; i < 4; i++) {
+ wait_wecfifo_ready(flctl); /* wait for write ready */
+ writel(0xFFFFFFFF, FLECFIFO(flctl));
+ }
+ wait_completion(flctl);
+ }
+
+ writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl));
+}
+
+static void execmd_write_oob(struct mtd_info *mtd)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ int page_addr = flctl->seqin_page_addr;
+ int sector, page_sectors;
+
+ if (flctl->page_size) {
+ sector = 3;
+ page_sectors = 4;
+ } else {
+ sector = 0;
+ page_sectors = 1;
+ }
+
+ set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
+ (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
+
+ for (; sector < page_sectors; sector++) {
+ empty_fifo(flctl);
+ set_addr(mtd, sector * 528 + 512, page_addr);
+ writel(16, FLDTCNTR(flctl)); /* set read size */
+
+ start_translation(flctl);
+ write_fiforeg(flctl, 16, 16 * sector);
+ wait_completion(flctl);
+ }
+}
+
+static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ uint32_t read_cmd = 0;
+
+ flctl->read_bytes = 0;
+ if (command != NAND_CMD_PAGEPROG)
+ flctl->index = 0;
+
+ switch (command) {
+ case NAND_CMD_READ1:
+ case NAND_CMD_READ0:
+ if (flctl->hwecc) {
+ /* read page with hwecc */
+ execmd_read_page_sector(mtd, page_addr);
+ break;
+ }
+ empty_fifo(flctl);
+ if (flctl->page_size)
+ set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8)
+ | command);
+ else
+ set_cmd_regs(mtd, command, command);
+
+ set_addr(mtd, 0, page_addr);
+
+ flctl->read_bytes = mtd->writesize + mtd->oobsize;
+ flctl->index += column;
+ goto read_normal_exit;
+
+ case NAND_CMD_READOOB:
+ if (flctl->hwecc) {
+ /* read page with hwecc */
+ execmd_read_oob(mtd, page_addr);
+ break;
+ }
+
+ empty_fifo(flctl);
+ if (flctl->page_size) {
+ set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8)
+ | NAND_CMD_READ0);
+ set_addr(mtd, mtd->writesize, page_addr);
+ } else {
+ set_cmd_regs(mtd, command, command);
+ set_addr(mtd, 0, page_addr);
+ }
+ flctl->read_bytes = mtd->oobsize;
+ goto read_normal_exit;
+
+ case NAND_CMD_READID:
+ empty_fifo(flctl);
+ set_cmd_regs(mtd, command, command);
+ set_addr(mtd, 0, 0);
+
+ flctl->read_bytes = 4;
+ writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
+ start_translation(flctl);
+ read_datareg(flctl, 0); /* read and end */
+ break;
+
+ case NAND_CMD_ERASE1:
+ flctl->erase1_page_addr = page_addr;
+ break;
+
+ case NAND_CMD_ERASE2:
+ set_cmd_regs(mtd, NAND_CMD_ERASE1,
+ (command << 8) | NAND_CMD_ERASE1);
+ set_addr(mtd, -1, flctl->erase1_page_addr);
+ start_translation(flctl);
+ wait_completion(flctl);
+ break;
+
+ case NAND_CMD_SEQIN:
+ if (!flctl->page_size) {
+ /* output read command */
+ if (column >= mtd->writesize) {
+ column -= mtd->writesize;
+ read_cmd = NAND_CMD_READOOB;
+ } else if (column < 256) {
+ read_cmd = NAND_CMD_READ0;
+ } else {
+ column -= 256;
+ read_cmd = NAND_CMD_READ1;
+ }
+ }
+ flctl->seqin_column = column;
+ flctl->seqin_page_addr = page_addr;
+ flctl->seqin_read_cmd = read_cmd;
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ empty_fifo(flctl);
+ if (!flctl->page_size) {
+ set_cmd_regs(mtd, NAND_CMD_SEQIN,
+ flctl->seqin_read_cmd);
+ set_addr(mtd, -1, -1);
+ writel(0, FLDTCNTR(flctl)); /* set 0 size */
+ start_translation(flctl);
+ wait_completion(flctl);
+ }
+ if (flctl->hwecc) {
+ /* write page with hwecc */
+ if (flctl->seqin_column == mtd->writesize)
+ execmd_write_oob(mtd);
+ else if (!flctl->seqin_column)
+ execmd_write_page_sector(mtd);
+ else
+ printk(KERN_ERR "Invalid address !?\n");
+ break;
+ }
+ set_cmd_regs(mtd, command, (command << 8) | NAND_CMD_SEQIN);
+ set_addr(mtd, flctl->seqin_column, flctl->seqin_page_addr);
+ writel(flctl->index, FLDTCNTR(flctl)); /* set write size */
+ start_translation(flctl);
+ write_fiforeg(flctl, flctl->index, 0);
+ wait_completion(flctl);
+ break;
+
+ case NAND_CMD_STATUS:
+ set_cmd_regs(mtd, command, command);
+ set_addr(mtd, -1, -1);
+
+ flctl->read_bytes = 1;
+ writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
+ start_translation(flctl);
+ read_datareg(flctl, 0); /* read and end */
+ break;
+
+ case NAND_CMD_RESET:
+ set_cmd_regs(mtd, command, command);
+ set_addr(mtd, -1, -1);
+
+ writel(0, FLDTCNTR(flctl)); /* set 0 size */
+ start_translation(flctl);
+ wait_completion(flctl);
+ break;
+
+ default:
+ break;
+ }
+ return;
+
+read_normal_exit:
+ writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
+ start_translation(flctl);
+ read_fiforeg(flctl, flctl->read_bytes, 0);
+ wait_completion(flctl);
+ return;
+}
+
+static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ uint32_t flcmncr_val = readl(FLCMNCR(flctl));
+
+ switch (chipnr) {
+ case -1:
+ flcmncr_val &= ~CE0_ENABLE;
+ writel(flcmncr_val, FLCMNCR(flctl));
+ break;
+ case 0:
+ flcmncr_val |= CE0_ENABLE;
+ writel(flcmncr_val, FLCMNCR(flctl));
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ int i, index = flctl->index;
+
+ for (i = 0; i < len; i++)
+ flctl->done_buff[index + i] = buf[i];
+ flctl->index += len;
+}
+
+static uint8_t flctl_read_byte(struct mtd_info *mtd)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ int index = flctl->index;
+ uint8_t data;
+
+ data = flctl->done_buff[index];
+ flctl->index++;
+ return data;
+}
+
+static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = flctl_read_byte(mtd);
+}
+
+static int flctl_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (buf[i] != flctl_read_byte(mtd))
+ return -EFAULT;
+ return 0;
+}
+
+static void flctl_register_init(struct sh_flctl *flctl, unsigned long val)
+{
+ writel(val, FLCMNCR(flctl));
+}
+
+static int flctl_chip_init_tail(struct mtd_info *mtd)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ struct nand_chip *chip = &flctl->chip;
+
+ if (mtd->writesize == 512) {
+ flctl->page_size = 0;
+ if (chip->chipsize > (32 << 20)) {
+ /* big than 32MB */
+ flctl->rw_ADRCNT = ADRCNT_4;
+ flctl->erase_ADRCNT = ADRCNT_3;
+ } else if (chip->chipsize > (2 << 16)) {
+ /* big than 128KB */
+ flctl->rw_ADRCNT = ADRCNT_3;
+ flctl->erase_ADRCNT = ADRCNT_2;
+ } else {
+ flctl->rw_ADRCNT = ADRCNT_2;
+ flctl->erase_ADRCNT = ADRCNT_1;
+ }
+ } else {
+ flctl->page_size = 1;
+ if (chip->chipsize > (128 << 20)) {
+ /* big than 128MB */
+ flctl->rw_ADRCNT = ADRCNT2_E;
+ flctl->erase_ADRCNT = ADRCNT_3;
+ } else if (chip->chipsize > (8 << 16)) {
+ /* big than 512KB */
+ flctl->rw_ADRCNT = ADRCNT_4;
+ flctl->erase_ADRCNT = ADRCNT_2;
+ } else {
+ flctl->rw_ADRCNT = ADRCNT_3;
+ flctl->erase_ADRCNT = ADRCNT_1;
+ }
+ }
+
+ if (flctl->hwecc) {
+ if (mtd->writesize == 512) {
+ chip->ecc.layout = &flctl_4secc_oob_16;
+ chip->badblock_pattern = &flctl_4secc_smallpage;
+ } else {
+ chip->ecc.layout = &flctl_4secc_oob_64;
+ chip->badblock_pattern = &flctl_4secc_largepage;
+ }
+
+ chip->ecc.size = 512;
+ chip->ecc.bytes = 10;
+ chip->ecc.read_page = flctl_read_page_hwecc;
+ chip->ecc.write_page = flctl_write_page_hwecc;
+ chip->ecc.mode = NAND_ECC_HW;
+
+ /* 4 symbols ECC enabled */
+ writel(readl(FLCMNCR(flctl)) | _4ECCEN | ECCPOS2 | ECCPOS_02,
+ FLCMNCR(flctl));
+ } else {
+ chip->ecc.mode = NAND_ECC_SOFT;
+ }
+
+ return 0;
+}
+
+static int __init flctl_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct sh_flctl *flctl;
+ struct mtd_info *flctl_mtd;
+ struct nand_chip *nand;
+ struct sh_flctl_platform_data *pdata;
+ int ret;
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+ printk(KERN_ERR "sh_flctl platform_data not found.\n");
+ return -ENODEV;
+ }
+
+ flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
+ if (!flctl) {
+ printk(KERN_ERR "Unable to allocate NAND MTD dev structure.\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ printk(KERN_ERR "%s: resource not found.\n", __func__);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ flctl->reg = ioremap(res->start, res->end - res->start + 1);
+ if (flctl->reg == NULL) {
+ printk(KERN_ERR "%s: ioremap error.\n", __func__);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, flctl);
+ flctl_mtd = &flctl->mtd;
+ nand = &flctl->chip;
+ flctl_mtd->priv = nand;
+ flctl->hwecc = pdata->has_hwecc;
+
+ flctl_register_init(flctl, pdata->flcmncr_val);
+
+ nand->options = NAND_NO_AUTOINCR;
+
+ /* Set address of hardware control function */
+ /* 20 us command delay time */
+ nand->chip_delay = 20;
+
+ nand->read_byte = flctl_read_byte;
+ nand->write_buf = flctl_write_buf;
+ nand->read_buf = flctl_read_buf;
+ nand->verify_buf = flctl_verify_buf;
+ nand->select_chip = flctl_select_chip;
+ nand->cmdfunc = flctl_cmdfunc;
+
+ ret = nand_scan_ident(flctl_mtd, 1);
+ if (ret)
+ goto err;
+
+ ret = flctl_chip_init_tail(flctl_mtd);
+ if (ret)
+ goto err;
+
+ ret = nand_scan_tail(flctl_mtd);
+ if (ret)
+ goto err;
+
+ add_mtd_partitions(flctl_mtd, pdata->parts, pdata->nr_parts);
+
+ return 0;
+
+err:
+ kfree(flctl);
+ return ret;
+}
+
+static int __exit flctl_remove(struct platform_device *pdev)
+{
+ struct sh_flctl *flctl = platform_get_drvdata(pdev);
+
+ nand_release(&flctl->mtd);
+ kfree(flctl);
+
+ return 0;
+}
+
+static struct platform_driver flctl_driver = {
+ .probe = flctl_probe,
+ .remove = flctl_remove,
+ .driver = {
+ .name = "sh_flctl",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init flctl_nand_init(void)
+{
+ return platform_driver_register(&flctl_driver);
+}
+
+static void __exit flctl_nand_cleanup(void)
+{
+ platform_driver_unregister(&flctl_driver);
+}
+
+module_init(flctl_nand_init);
+module_exit(flctl_nand_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_DESCRIPTION("SuperH FLCTL driver");
+MODULE_ALIAS("platform:sh_flctl");
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
deleted file mode 100644
index bbf492e6830..00000000000
--- a/drivers/mtd/nand/toto.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * drivers/mtd/nand/toto.c
- *
- * Copyright (c) 2003 Texas Instruments
- *
- * Derived from drivers/mtd/autcpu12.c
- *
- * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Overview:
- * This is a device driver for the NAND flash device found on the
- * TI fido board. It supports 32MiB and 64MiB cards
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/sizes.h>
-#include <asm/arch/toto.h>
-#include <asm/arch-omap1510/hardware.h>
-#include <asm/arch/gpio.h>
-
-#define CONFIG_NAND_WORKAROUND 1
-
-/*
- * MTD structure for TOTO board
- */
-static struct mtd_info *toto_mtd = NULL;
-
-static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
-
-/*
- * Define partitions for flash devices
- */
-
-static struct mtd_partition partition_info64M[] = {
- { .name = "toto kernel partition 1",
- .offset = 0,
- .size = 2 * SZ_1M },
- { .name = "toto file sys partition 2",
- .offset = 2 * SZ_1M,
- .size = 14 * SZ_1M },
- { .name = "toto user partition 3",
- .offset = 16 * SZ_1M,
- .size = 16 * SZ_1M },
- { .name = "toto devboard extra partition 4",
- .offset = 32 * SZ_1M,
- .size = 32 * SZ_1M },
-};
-
-static struct mtd_partition partition_info32M[] = {
- { .name = "toto kernel partition 1",
- .offset = 0,
- .size = 2 * SZ_1M },
- { .name = "toto file sys partition 2",
- .offset = 2 * SZ_1M,
- .size = 14 * SZ_1M },
- { .name = "toto user partition 3",
- .offset = 16 * SZ_1M,
- .size = 16 * SZ_1M },
-};
-
-#define NUM_PARTITIONS32M 3
-#define NUM_PARTITIONS64M 4
-
-/*
- * hardware specific access to control-lines
- *
- * ctrl:
- * NAND_NCE: bit 0 -> bit 14 (0x4000)
- * NAND_CLE: bit 1 -> bit 12 (0x1000)
- * NAND_ALE: bit 2 -> bit 1 (0x0002)
- */
-static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
- unsigned int ctrl)
-{
- struct nand_chip *chip = mtd->priv;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- unsigned long bits;
-
- /* hopefully enough time for tc make proceding write to clear */
- udelay(1);
-
- bits = (~ctrl & NAND_NCE) << 14;
- bits |= (ctrl & NAND_CLE) << 12;
- bits |= (ctrl & NAND_ALE) >> 1;
-
-#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
- gpiosetout(0x5002, bits);
-
-#ifdef CONFIG_NAND_WORKAROUND
- /* "some" dev boards busted, blue wired to rts2 :( */
- rts2setout(2, (ctrl & NAND_CLE) << 1);
-#endif
- /* allow time to ensure gpio state to over take memory write */
- udelay(1);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- * Main initialization routine
- */
-static int __init toto_init(void)
-{
- struct nand_chip *this;
- int err = 0;
-
- /* Allocate memory for MTD device structure and private data */
- toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
- if (!toto_mtd) {
- printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
- err = -ENOMEM;
- goto out;
- }
-
- /* Get pointer to private data */
- this = (struct nand_chip *)(&toto_mtd[1]);
-
- /* Initialize structures */
- memset(toto_mtd, 0, sizeof(struct mtd_info));
- memset(this, 0, sizeof(struct nand_chip));
-
- /* Link the private data with the MTD structure */
- toto_mtd->priv = this;
- toto_mtd->owner = THIS_MODULE;
-
- /* Set address of NAND IO lines */
- this->IO_ADDR_R = toto_io_base;
- this->IO_ADDR_W = toto_io_base;
- this->cmd_ctrl = toto_hwcontrol;
- this->dev_ready = NULL;
- /* 25 us command delay time */
- this->chip_delay = 30;
- this->ecc.mode = NAND_ECC_SOFT;
-
- /* Scan to find existance of the device */
- if (nand_scan(toto_mtd, 1)) {
- err = -ENXIO;
- goto out_mtd;
- }
-
- /* Register the partitions */
- switch (toto_mtd->size) {
- case SZ_64M:
- add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
- break;
- case SZ_32M:
- add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
- break;
- default:{
- printk(KERN_WARNING "Unsupported Nand device\n");
- err = -ENXIO;
- goto out_buf;
- }
- }
-
- gpioreserve(NAND_MASK); /* claim our gpios */
- archflashwp(0, 0); /* open up flash for writing */
-
- goto out;
-
- out_mtd:
- kfree(toto_mtd);
- out:
- return err;
-}
-
-module_init(toto_init);
-
-/*
- * Clean up routine
- */
-static void __exit toto_cleanup(void)
-{
- /* Release resources, unregister device */
- nand_release(toto_mtd);
-
- /* Free the MTD device structure */
- kfree(toto_mtd);
-
- /* stop flash writes */
- archflashwp(0, 1);
-
- /* release gpios to system */
- gpiorelease(NAND_MASK);
-}
-
-module_exit(toto_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Richard Woodruff <r-woodruff2@ti.com>");
-MODULE_DESCRIPTION("Glue layer for NAND flash on toto board");
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 4f80c2fd89a..9e45b3f39c0 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -20,7 +20,6 @@
#include <linux/mtd/partitions.h>
int __devinit of_mtd_parse_partitions(struct device *dev,
- struct mtd_info *mtd,
struct device_node *node,
struct mtd_partition **pparts)
{
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index cb41cbca64f..79fa79e8f8d 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -27,8 +27,16 @@ config MTD_ONENAND_GENERIC
help
Support for OneNAND flash via platform device driver.
+config MTD_ONENAND_OMAP2
+ tristate "OneNAND on OMAP2/OMAP3 support"
+ depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3)
+ help
+ Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
+ via the GPMC memory controller.
+
config MTD_ONENAND_OTP
bool "OneNAND OTP Support"
+ select HAVE_MTD_OTP
help
One Block of the NAND Flash Array memory is reserved as
a One-Time Programmable Block memory area.
diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile
index 4d2eacfd7e1..64b6cc61a52 100644
--- a/drivers/mtd/onenand/Makefile
+++ b/drivers/mtd/onenand/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
# Board specific.
obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
+obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o
# Simulator
obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
new file mode 100644
index 00000000000..8387e05daae
--- /dev/null
+++ b/drivers/mtd/onenand/omap2.c
@@ -0,0 +1,802 @@
+/*
+ * linux/drivers/mtd/onenand/omap2.c
+ *
+ * OneNAND driver for OMAP2 / OMAP3
+ *
+ * Copyright © 2005-2006 Nokia Corporation
+ *
+ * Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjölä
+ * IRQ and DMA support written by Timo Teras
+ *
+ * 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 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/mach/flash.h>
+#include <asm/arch/gpmc.h>
+#include <asm/arch/onenand.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/gpmc.h>
+#include <asm/arch/pm.h>
+
+#include <linux/dma-mapping.h>
+#include <asm/dma-mapping.h>
+#include <asm/arch/dma.h>
+
+#include <asm/arch/board.h>
+
+#define DRIVER_NAME "omap2-onenand"
+
+#define ONENAND_IO_SIZE SZ_128K
+#define ONENAND_BUFRAM_SIZE (1024 * 5)
+
+struct omap2_onenand {
+ struct platform_device *pdev;
+ int gpmc_cs;
+ unsigned long phys_base;
+ int gpio_irq;
+ struct mtd_info mtd;
+ struct mtd_partition *parts;
+ struct onenand_chip onenand;
+ struct completion irq_done;
+ struct completion dma_done;
+ int dma_channel;
+ int freq;
+ int (*setup)(void __iomem *base, int freq);
+};
+
+static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
+{
+ struct omap2_onenand *c = data;
+
+ complete(&c->dma_done);
+}
+
+static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
+{
+ struct omap2_onenand *c = dev_id;
+
+ complete(&c->irq_done);
+
+ return IRQ_HANDLED;
+}
+
+static inline unsigned short read_reg(struct omap2_onenand *c, int reg)
+{
+ return readw(c->onenand.base + reg);
+}
+
+static inline void write_reg(struct omap2_onenand *c, unsigned short value,
+ int reg)
+{
+ writew(value, c->onenand.base + reg);
+}
+
+static void wait_err(char *msg, int state, unsigned int ctrl, unsigned int intr)
+{
+ printk(KERN_ERR "onenand_wait: %s! state %d ctrl 0x%04x intr 0x%04x\n",
+ msg, state, ctrl, intr);
+}
+
+static void wait_warn(char *msg, int state, unsigned int ctrl,
+ unsigned int intr)
+{
+ printk(KERN_WARNING "onenand_wait: %s! state %d ctrl 0x%04x "
+ "intr 0x%04x\n", msg, state, ctrl, intr);
+}
+
+static int omap2_onenand_wait(struct mtd_info *mtd, int state)
+{
+ struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+ unsigned int intr = 0;
+ unsigned int ctrl;
+ unsigned long timeout;
+ u32 syscfg;
+
+ if (state == FL_RESETING) {
+ int i;
+
+ for (i = 0; i < 20; i++) {
+ udelay(1);
+ intr = read_reg(c, ONENAND_REG_INTERRUPT);
+ if (intr & ONENAND_INT_MASTER)
+ break;
+ }
+ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+ if (ctrl & ONENAND_CTRL_ERROR) {
+ wait_err("controller error", state, ctrl, intr);
+ return -EIO;
+ }
+ if (!(intr & ONENAND_INT_RESET)) {
+ wait_err("timeout", state, ctrl, intr);
+ return -EIO;
+ }
+ return 0;
+ }
+
+ if (state != FL_READING) {
+ int result;
+
+ /* Turn interrupts on */
+ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+ if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
+ syscfg |= ONENAND_SYS_CFG1_IOBE;
+ write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
+ if (cpu_is_omap34xx())
+ /* Add a delay to let GPIO settle */
+ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+ }
+
+ INIT_COMPLETION(c->irq_done);
+ if (c->gpio_irq) {
+ result = omap_get_gpio_datain(c->gpio_irq);
+ if (result == -1) {
+ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+ intr = read_reg(c, ONENAND_REG_INTERRUPT);
+ wait_err("gpio error", state, ctrl, intr);
+ return -EIO;
+ }
+ } else
+ result = 0;
+ if (result == 0) {
+ int retry_cnt = 0;
+retry:
+ result = wait_for_completion_timeout(&c->irq_done,
+ msecs_to_jiffies(20));
+ if (result == 0) {
+ /* Timeout after 20ms */
+ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+ if (ctrl & ONENAND_CTRL_ONGO) {
+ /*
+ * The operation seems to be still going
+ * so give it some more time.
+ */
+ retry_cnt += 1;
+ if (retry_cnt < 3)
+ goto retry;
+ intr = read_reg(c,
+ ONENAND_REG_INTERRUPT);
+ wait_err("timeout", state, ctrl, intr);
+ return -EIO;
+ }
+ intr = read_reg(c, ONENAND_REG_INTERRUPT);
+ if ((intr & ONENAND_INT_MASTER) == 0)
+ wait_warn("timeout", state, ctrl, intr);
+ }
+ }
+ } else {
+ int retry_cnt = 0;
+
+ /* Turn interrupts off */
+ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+ syscfg &= ~ONENAND_SYS_CFG1_IOBE;
+ write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
+
+ timeout = jiffies + msecs_to_jiffies(20);
+ while (1) {
+ if (time_before(jiffies, timeout)) {
+ intr = read_reg(c, ONENAND_REG_INTERRUPT);
+ if (intr & ONENAND_INT_MASTER)
+ break;
+ } else {
+ /* Timeout after 20ms */
+ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+ if (ctrl & ONENAND_CTRL_ONGO) {
+ /*
+ * The operation seems to be still going
+ * so give it some more time.
+ */
+ retry_cnt += 1;
+ if (retry_cnt < 3) {
+ timeout = jiffies +
+ msecs_to_jiffies(20);
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ intr = read_reg(c, ONENAND_REG_INTERRUPT);
+ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+
+ if (intr & ONENAND_INT_READ) {
+ int ecc = read_reg(c, ONENAND_REG_ECC_STATUS);
+
+ if (ecc) {
+ unsigned int addr1, addr8;
+
+ addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1);
+ addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8);
+ if (ecc & ONENAND_ECC_2BIT_ALL) {
+ printk(KERN_ERR "onenand_wait: ECC error = "
+ "0x%04x, addr1 %#x, addr8 %#x\n",
+ ecc, addr1, addr8);
+ mtd->ecc_stats.failed++;
+ return -EBADMSG;
+ } else if (ecc & ONENAND_ECC_1BIT_ALL) {
+ printk(KERN_NOTICE "onenand_wait: correctable "
+ "ECC error = 0x%04x, addr1 %#x, "
+ "addr8 %#x\n", ecc, addr1, addr8);
+ mtd->ecc_stats.corrected++;
+ }
+ }
+ } else if (state == FL_READING) {
+ wait_err("timeout", state, ctrl, intr);
+ return -EIO;
+ }
+
+ if (ctrl & ONENAND_CTRL_ERROR) {
+ wait_err("controller error", state, ctrl, intr);
+ if (ctrl & ONENAND_CTRL_LOCK)
+ printk(KERN_ERR "onenand_wait: "
+ "Device is write protected!!!\n");
+ return -EIO;
+ }
+
+ if (ctrl & 0xFE9F)
+ wait_warn("unexpected controller status", state, ctrl, intr);
+
+ return 0;
+}
+
+static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
+{
+ struct onenand_chip *this = mtd->priv;
+
+ if (ONENAND_CURRENT_BUFFERRAM(this)) {
+ if (area == ONENAND_DATARAM)
+ return mtd->writesize;
+ if (area == ONENAND_SPARERAM)
+ return mtd->oobsize;
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_ARCH_OMAP3) || defined(MULTI_OMAP2)
+
+static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ dma_addr_t dma_src, dma_dst;
+ int bram_offset;
+ unsigned long timeout;
+ void *buf = (void *)buffer;
+ size_t xtra;
+ volatile unsigned *done;
+
+ bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+ if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
+ goto out_copy;
+
+ if (buf >= high_memory) {
+ struct page *p1;
+
+ if (((size_t)buf & PAGE_MASK) !=
+ ((size_t)(buf + count - 1) & PAGE_MASK))
+ goto out_copy;
+ p1 = vmalloc_to_page(buf);
+ if (!p1)
+ goto out_copy;
+ buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
+ }
+
+ xtra = count & 3;
+ if (xtra) {
+ count -= xtra;
+ memcpy(buf + count, this->base + bram_offset + count, xtra);
+ }
+
+ dma_src = c->phys_base + bram_offset;
+ dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
+ if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+ dev_err(&c->pdev->dev,
+ "Couldn't DMA map a %d byte buffer\n",
+ count);
+ goto out_copy;
+ }
+
+ omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+ count >> 2, 1, 0, 0, 0);
+ omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_src, 0, 0);
+ omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_dst, 0, 0);
+
+ INIT_COMPLETION(c->dma_done);
+ omap_start_dma(c->dma_channel);
+
+ timeout = jiffies + msecs_to_jiffies(20);
+ done = &c->dma_done.done;
+ while (time_before(jiffies, timeout))
+ if (*done)
+ break;
+
+ dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
+
+ if (!*done) {
+ dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
+ goto out_copy;
+ }
+
+ return 0;
+
+out_copy:
+ memcpy(buf, this->base + bram_offset, count);
+ return 0;
+}
+
+static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count)
+{
+ struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ dma_addr_t dma_src, dma_dst;
+ int bram_offset;
+ unsigned long timeout;
+ void *buf = (void *)buffer;
+ volatile unsigned *done;
+
+ bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+ if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
+ goto out_copy;
+
+ /* panic_write() may be in an interrupt context */
+ if (in_interrupt())
+ goto out_copy;
+
+ if (buf >= high_memory) {
+ struct page *p1;
+
+ if (((size_t)buf & PAGE_MASK) !=
+ ((size_t)(buf + count - 1) & PAGE_MASK))
+ goto out_copy;
+ p1 = vmalloc_to_page(buf);
+ if (!p1)
+ goto out_copy;
+ buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
+ }
+
+ dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
+ dma_dst = c->phys_base + bram_offset;
+ if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+ dev_err(&c->pdev->dev,
+ "Couldn't DMA map a %d byte buffer\n",
+ count);
+ return -1;
+ }
+
+ omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+ count >> 2, 1, 0, 0, 0);
+ omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_src, 0, 0);
+ omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_dst, 0, 0);
+
+ INIT_COMPLETION(c->dma_done);
+ omap_start_dma(c->dma_channel);
+
+ timeout = jiffies + msecs_to_jiffies(20);
+ done = &c->dma_done.done;
+ while (time_before(jiffies, timeout))
+ if (*done)
+ break;
+
+ dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
+
+ if (!*done) {
+ dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
+ goto out_copy;
+ }
+
+ return 0;
+
+out_copy:
+ memcpy(this->base + bram_offset, buf, count);
+ return 0;
+}
+
+#else
+
+int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count);
+
+int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count);
+
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(MULTI_OMAP2)
+
+static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ dma_addr_t dma_src, dma_dst;
+ int bram_offset;
+
+ bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+ /* DMA is not used. Revisit PM requirements before enabling it. */
+ if (1 || (c->dma_channel < 0) ||
+ ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
+ (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
+ memcpy(buffer, (__force void *)(this->base + bram_offset),
+ count);
+ return 0;
+ }
+
+ dma_src = c->phys_base + bram_offset;
+ dma_dst = dma_map_single(&c->pdev->dev, buffer, count,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+ dev_err(&c->pdev->dev,
+ "Couldn't DMA map a %d byte buffer\n",
+ count);
+ return -1;
+ }
+
+ omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+ count / 4, 1, 0, 0, 0);
+ omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_src, 0, 0);
+ omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_dst, 0, 0);
+
+ INIT_COMPLETION(c->dma_done);
+ omap_start_dma(c->dma_channel);
+ wait_for_completion(&c->dma_done);
+
+ dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
+
+ return 0;
+}
+
+static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count)
+{
+ struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ dma_addr_t dma_src, dma_dst;
+ int bram_offset;
+
+ bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+ /* DMA is not used. Revisit PM requirements before enabling it. */
+ if (1 || (c->dma_channel < 0) ||
+ ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
+ (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
+ memcpy((__force void *)(this->base + bram_offset), buffer,
+ count);
+ return 0;
+ }
+
+ dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count,
+ DMA_TO_DEVICE);
+ dma_dst = c->phys_base + bram_offset;
+ if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+ dev_err(&c->pdev->dev,
+ "Couldn't DMA map a %d byte buffer\n",
+ count);
+ return -1;
+ }
+
+ omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S16,
+ count / 2, 1, 0, 0, 0);
+ omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_src, 0, 0);
+ omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_dst, 0, 0);
+
+ INIT_COMPLETION(c->dma_done);
+ omap_start_dma(c->dma_channel);
+ wait_for_completion(&c->dma_done);
+
+ dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
+
+ return 0;
+}
+
+#else
+
+int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count);
+
+int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count);
+
+#endif
+
+static struct platform_driver omap2_onenand_driver;
+
+static int __adjust_timing(struct device *dev, void *data)
+{
+ int ret = 0;
+ struct omap2_onenand *c;
+
+ c = dev_get_drvdata(dev);
+
+ BUG_ON(c->setup == NULL);
+
+ /* DMA is not in use so this is all that is needed */
+ /* Revisit for OMAP3! */
+ ret = c->setup(c->onenand.base, c->freq);
+
+ return ret;
+}
+
+int omap2_onenand_rephase(void)
+{
+ return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
+ NULL, __adjust_timing);
+}
+
+static void __devexit omap2_onenand_shutdown(struct platform_device *pdev)
+{
+ struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
+
+ /* With certain content in the buffer RAM, the OMAP boot ROM code
+ * can recognize the flash chip incorrectly. Zero it out before
+ * soft reset.
+ */
+ memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
+}
+
+static int __devinit omap2_onenand_probe(struct platform_device *pdev)
+{
+ struct omap_onenand_platform_data *pdata;
+ struct omap2_onenand *c;
+ int r;
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "platform data missing\n");
+ return -ENODEV;
+ }
+
+ c = kzalloc(sizeof(struct omap2_onenand), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+
+ init_completion(&c->irq_done);
+ init_completion(&c->dma_done);
+ c->gpmc_cs = pdata->cs;
+ c->gpio_irq = pdata->gpio_irq;
+ c->dma_channel = pdata->dma_channel;
+ if (c->dma_channel < 0) {
+ /* if -1, don't use DMA */
+ c->gpio_irq = 0;
+ }
+
+ r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
+ if (r < 0) {
+ dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+ goto err_kfree;
+ }
+
+ if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
+ pdev->dev.driver->name) == NULL) {
+ dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
+ "size: 0x%x\n", c->phys_base, ONENAND_IO_SIZE);
+ r = -EBUSY;
+ goto err_free_cs;
+ }
+ c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
+ if (c->onenand.base == NULL) {
+ r = -ENOMEM;
+ goto err_release_mem_region;
+ }
+
+ if (pdata->onenand_setup != NULL) {
+ r = pdata->onenand_setup(c->onenand.base, c->freq);
+ if (r < 0) {
+ dev_err(&pdev->dev, "Onenand platform setup failed: "
+ "%d\n", r);
+ goto err_iounmap;
+ }
+ c->setup = pdata->onenand_setup;
+ }
+
+ if (c->gpio_irq) {
+ if ((r = omap_request_gpio(c->gpio_irq)) < 0) {
+ dev_err(&pdev->dev, "Failed to request GPIO%d for "
+ "OneNAND\n", c->gpio_irq);
+ goto err_iounmap;
+ }
+ omap_set_gpio_direction(c->gpio_irq, 1);
+
+ if ((r = request_irq(OMAP_GPIO_IRQ(c->gpio_irq),
+ omap2_onenand_interrupt, IRQF_TRIGGER_RISING,
+ pdev->dev.driver->name, c)) < 0)
+ goto err_release_gpio;
+ }
+
+ if (c->dma_channel >= 0) {
+ r = omap_request_dma(0, pdev->dev.driver->name,
+ omap2_onenand_dma_cb, (void *) c,
+ &c->dma_channel);
+ if (r == 0) {
+ omap_set_dma_write_mode(c->dma_channel,
+ OMAP_DMA_WRITE_NON_POSTED);
+ omap_set_dma_src_data_pack(c->dma_channel, 1);
+ omap_set_dma_src_burst_mode(c->dma_channel,
+ OMAP_DMA_DATA_BURST_8);
+ omap_set_dma_dest_data_pack(c->dma_channel, 1);
+ omap_set_dma_dest_burst_mode(c->dma_channel,
+ OMAP_DMA_DATA_BURST_8);
+ } else {
+ dev_info(&pdev->dev,
+ "failed to allocate DMA for OneNAND, "
+ "using PIO instead\n");
+ c->dma_channel = -1;
+ }
+ }
+
+ dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
+ "base %p\n", c->gpmc_cs, c->phys_base,
+ c->onenand.base);
+
+ c->pdev = pdev;
+ c->mtd.name = pdev->dev.bus_id;
+ c->mtd.priv = &c->onenand;
+ c->mtd.owner = THIS_MODULE;
+
+ if (c->dma_channel >= 0) {
+ struct onenand_chip *this = &c->onenand;
+
+ this->wait = omap2_onenand_wait;
+ if (cpu_is_omap34xx()) {
+ this->read_bufferram = omap3_onenand_read_bufferram;
+ this->write_bufferram = omap3_onenand_write_bufferram;
+ } else {
+ this->read_bufferram = omap2_onenand_read_bufferram;
+ this->write_bufferram = omap2_onenand_write_bufferram;
+ }
+ }
+
+ if ((r = onenand_scan(&c->mtd, 1)) < 0)
+ goto err_release_dma;
+
+ switch ((c->onenand.version_id >> 4) & 0xf) {
+ case 0:
+ c->freq = 40;
+ break;
+ case 1:
+ c->freq = 54;
+ break;
+ case 2:
+ c->freq = 66;
+ break;
+ case 3:
+ c->freq = 83;
+ break;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (pdata->parts != NULL)
+ r = add_mtd_partitions(&c->mtd, pdata->parts,
+ pdata->nr_parts);
+ else
+#endif
+ r = add_mtd_device(&c->mtd);
+ if (r < 0)
+ goto err_release_onenand;
+
+ platform_set_drvdata(pdev, c);
+
+ return 0;
+
+err_release_onenand:
+ onenand_release(&c->mtd);
+err_release_dma:
+ if (c->dma_channel != -1)
+ omap_free_dma(c->dma_channel);
+ if (c->gpio_irq)
+ free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
+err_release_gpio:
+ if (c->gpio_irq)
+ omap_free_gpio(c->gpio_irq);
+err_iounmap:
+ iounmap(c->onenand.base);
+err_release_mem_region:
+ release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+err_free_cs:
+ gpmc_cs_free(c->gpmc_cs);
+err_kfree:
+ kfree(c);
+
+ return r;
+}
+
+static int __devexit omap2_onenand_remove(struct platform_device *pdev)
+{
+ struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
+
+ BUG_ON(c == NULL);
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (c->parts)
+ del_mtd_partitions(&c->mtd);
+ else
+ del_mtd_device(&c->mtd);
+#else
+ del_mtd_device(&c->mtd);
+#endif
+
+ onenand_release(&c->mtd);
+ if (c->dma_channel != -1)
+ omap_free_dma(c->dma_channel);
+ omap2_onenand_shutdown(pdev);
+ platform_set_drvdata(pdev, NULL);
+ if (c->gpio_irq) {
+ free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
+ omap_free_gpio(c->gpio_irq);
+ }
+ iounmap(c->onenand.base);
+ release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+ kfree(c);
+
+ return 0;
+}
+
+static struct platform_driver omap2_onenand_driver = {
+ .probe = omap2_onenand_probe,
+ .remove = omap2_onenand_remove,
+ .shutdown = omap2_onenand_shutdown,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init omap2_onenand_init(void)
+{
+ printk(KERN_INFO "OneNAND driver initializing\n");
+ return platform_driver_register(&omap2_onenand_driver);
+}
+
+static void __exit omap2_onenand_exit(void)
+{
+ platform_driver_unregister(&omap2_onenand_driver);
+}
+
+module_init(omap2_onenand_init);
+module_exit(omap2_onenand_exit);
+
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
+MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 926cf3a4135..90ed319f26e 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1794,7 +1794,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
return -EINVAL;
}
- instr->fail_addr = 0xffffffff;
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
/* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_ERASING);
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index a5f3d60047d..33a5d6ed6f1 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -321,8 +321,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
DEBUG(MTD_DEBUG_LEVEL1,
"SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len,
- (ssfdc->map_len + MAX_PHYS_BLK_PER_ZONE - 1) /
- MAX_PHYS_BLK_PER_ZONE);
+ DIV_ROUND_UP(ssfdc->map_len, MAX_PHYS_BLK_PER_ZONE));
/* Set geometry */
ssfdc->heads = 16;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 03c759b4eeb..b30a0b83d7f 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -104,12 +104,9 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
struct ubi_volume_desc *desc;
int vol_id = iminor(inode) - 1, mode, ubi_num;
- lock_kernel();
ubi_num = ubi_major2num(imajor(inode));
- if (ubi_num < 0) {
- unlock_kernel();
+ if (ubi_num < 0)
return ubi_num;
- }
if (file->f_mode & FMODE_WRITE)
mode = UBI_READWRITE;
@@ -119,7 +116,6 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
dbg_gen("open volume %d, mode %d", vol_id, mode);
desc = ubi_open_volume(ubi_num, vol_id, mode);
- unlock_kernel();
if (IS_ERR(desc))
return PTR_ERR(desc);
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 967bb4406df..4f2daa5bbec 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -387,7 +387,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
pnum, vol_id, lnum, ec, sqnum, bitflips);
sv = add_volume(si, vol_id, pnum, vid_hdr);
- if (IS_ERR(sv) < 0)
+ if (IS_ERR(sv))
return PTR_ERR(sv);
if (si->max_sqnum < sqnum)
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 217d0e111b2..333c8941552 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -244,8 +244,8 @@ static int vtbl_check(const struct ubi_device *ubi,
}
if (reserved_pebs > ubi->good_peb_count) {
- dbg_err("too large reserved_pebs, good PEBs %d",
- ubi->good_peb_count);
+ dbg_err("too large reserved_pebs %d, good PEBs %d",
+ reserved_pebs, ubi->good_peb_count);
err = 9;
goto bad;
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 491ee16da5c..9ba295d9dd9 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -90,7 +90,7 @@ static int vortex_debug = 1;
#include <linux/eisa.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
-#include <asm/irq.h> /* For NR_IRQS only. */
+#include <asm/irq.h> /* For nr_irqs only. */
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -1221,7 +1221,7 @@ static int __devinit vortex_probe1(struct device *gendev,
if (print_info)
printk(", IRQ %d\n", dev->irq);
/* Tell them about an invalid IRQ. */
- if (dev->irq <= 0 || dev->irq >= NR_IRQS)
+ if (dev->irq <= 0 || dev->irq >= nr_irqs)
printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
dev->irq);
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 85fa40a0a66..9ba1f0b4642 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1836,10 +1836,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
- dev_err(&pdev->dev,
- "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
+ dev_info(&pdev->dev,
+ "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip, use 8139too\n",
pdev->vendor, pdev->device, pdev->revision);
- dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
return -ENODEV;
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 0daf8c15e38..63f906b0489 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -946,10 +946,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) {
dev_info(&pdev->dev,
- "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
+ "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n",
pdev->vendor, pdev->device, pdev->revision);
- dev_info(&pdev->dev,
- "Use the \"8139cp\" driver for improved performance and stability.\n");
+ return -ENODEV;
}
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ad301ace608..f749b40f954 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -464,6 +464,12 @@ config MIPS_JAZZ_SONIC
This is the driver for the onboard card of MIPS Magnum 4000,
Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
+config XTENSA_XT2000_SONIC
+ tristate "Xtensa XT2000 onboard SONIC Ethernet support"
+ depends on XTENSA_PLATFORM_XT2000
+ help
+ This is the driver for the onboard card of the Xtensa XT2000 board.
+
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
depends on SOC_AU1X00
@@ -888,7 +894,7 @@ config SMC91X
select CRC32
select MII
depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || \
- SOC_AU1X00 || BLACKFIN || MN10300
+ MIPS || BLACKFIN || MN10300
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -960,7 +966,7 @@ config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
select MII
- depends on ARCH_PXA || SUPERH
+ depends on ARM || SUPERH
help
This is a driver for SMSC's LAN911x series of Ethernet chipsets
including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -2003,6 +2009,11 @@ config IGB_LRO
If in doubt, say N.
+config IGB_DCA
+ bool "Enable DCA"
+ default y
+ depends on IGB && DCA && !(IGB=y && DCA=m)
+
source "drivers/net/ixp2000/Kconfig"
config MYRI_SBUS
@@ -2504,6 +2515,15 @@ config PASEMI_MAC
This driver supports the on-chip 1/10Gbit Ethernet controller on
PA Semi's PWRficient line of chips.
+config MLX4_EN
+ tristate "Mellanox Technologies 10Gbit Ethernet support"
+ depends on PCI && INET
+ select MLX4_CORE
+ select INET_LRO
+ help
+ This driver supports Mellanox Technologies ConnectX Ethernet
+ devices.
+
config MLX4_CORE
tristate
depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fa2510b2e60..f19acf8b922 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -227,6 +227,8 @@ pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
obj-$(CONFIG_MLX4_CORE) += mlx4/
obj-$(CONFIG_ENC28J60) += enc28j60.o
+obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
+
obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 4207d6efddc..9a314d88e7b 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -838,12 +838,12 @@ static int ax_probe(struct platform_device *pdev)
/* find the platform resources */
- dev->irq = platform_get_irq(pdev, 0);
- if (dev->irq < 0) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
dev_err(&pdev->dev, "no IRQ specified\n");
- ret = -ENXIO;
goto exit_mem;
}
+ dev->irq = ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 8e2be24f3fe..832739f38db 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1341,18 +1341,24 @@ static int bond_compute_features(struct bonding *bond)
int i;
features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES);
- features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
- NETIF_F_GSO_MASK | NETIF_F_NO_CSUM;
+ features |= NETIF_F_GSO_MASK | NETIF_F_NO_CSUM;
+
+ if (!bond->first_slave)
+ goto done;
+
+ features &= ~NETIF_F_ONE_FOR_ALL;
bond_for_each_slave(bond, slave, i) {
- features = netdev_compute_features(features,
- slave->dev->features);
+ features = netdev_increment_features(features,
+ slave->dev->features,
+ NETIF_F_ONE_FOR_ALL);
if (slave->dev->hard_header_len > max_hard_header_len)
max_hard_header_len = slave->dev->hard_header_len;
}
+done:
features |= (bond_dev->features & BOND_VLAN_FEATURES);
- bond_dev->features = features;
+ bond_dev->features = netdev_fix_features(features, NULL);
bond_dev->hard_header_len = max_hard_header_len;
return 0;
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
index 4407ac9bb55..ff1611f90e7 100644
--- a/drivers/net/cxgb3/l2t.c
+++ b/drivers/net/cxgb3/l2t.c
@@ -431,6 +431,7 @@ struct l2t_data *t3_init_l2t(unsigned int l2t_capacity)
for (i = 0; i < l2t_capacity; ++i) {
d->l2tab[i].idx = i;
d->l2tab[i].state = L2T_STATE_UNUSED;
+ __skb_queue_head_init(&d->l2tab[i].arpq);
spin_lock_init(&d->l2tab[i].lock);
atomic_set(&d->l2tab[i].refcnt, 0);
}
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index f42c23f4265..5a9083e3f44 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -47,15 +47,6 @@
#define CARDNAME "dm9000"
#define DRV_VERSION "1.31"
-#ifdef CONFIG_BLACKFIN
-#define readsb insb
-#define readsw insw
-#define readsl insl
-#define writesb outsb
-#define writesw outsw
-#define writesl outsl
-#endif
-
/*
* Transmit timeout, default 5 seconds.
*/
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 5524271eedc..82dd1a891ce 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0093"
+#define DRV_VERSION "EHEA_0094"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index b70c5314f53..422fcb93e2c 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -2863,7 +2863,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
struct ehea_adapter *adapter;
mutex_lock(&dlpar_mem_lock);
- ehea_info("LPAR memory enlarged - re-initializing driver");
+ ehea_info("LPAR memory changed - re-initializing driver");
list_for_each_entry(adapter, &adapter_list, list)
if (adapter->active_ports) {
@@ -2900,13 +2900,6 @@ static void ehea_rereg_mrs(struct work_struct *work)
}
}
- ehea_destroy_busmap();
- ret = ehea_create_busmap();
- if (ret) {
- ehea_error("creating ehea busmap failed");
- goto out;
- }
-
clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
list_for_each_entry(adapter, &adapter_list, list)
@@ -3519,9 +3512,21 @@ void ehea_crash_handler(void)
static int ehea_mem_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
+ struct memory_notify *arg = data;
switch (action) {
- case MEM_OFFLINE:
- ehea_info("memory has been removed");
+ case MEM_CANCEL_OFFLINE:
+ ehea_info("memory offlining canceled");
+ /* Readd canceled memory block */
+ case MEM_ONLINE:
+ ehea_info("memory is going online");
+ if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
+ return NOTIFY_BAD;
+ ehea_rereg_mrs(NULL);
+ break;
+ case MEM_GOING_OFFLINE:
+ ehea_info("memory is going offline");
+ if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
+ return NOTIFY_BAD;
ehea_rereg_mrs(NULL);
break;
default:
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index db8a9257e68..9b61dc9865d 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -567,7 +567,7 @@ static inline int ehea_calc_index(unsigned long i, unsigned long s)
static inline int ehea_init_top_bmap(struct ehea_top_bmap *ehea_top_bmap,
int dir)
{
- if(!ehea_top_bmap->dir[dir]) {
+ if (!ehea_top_bmap->dir[dir]) {
ehea_top_bmap->dir[dir] =
kzalloc(sizeof(struct ehea_dir_bmap), GFP_KERNEL);
if (!ehea_top_bmap->dir[dir])
@@ -578,7 +578,7 @@ static inline int ehea_init_top_bmap(struct ehea_top_bmap *ehea_top_bmap,
static inline int ehea_init_bmap(struct ehea_bmap *ehea_bmap, int top, int dir)
{
- if(!ehea_bmap->top[top]) {
+ if (!ehea_bmap->top[top]) {
ehea_bmap->top[top] =
kzalloc(sizeof(struct ehea_top_bmap), GFP_KERNEL);
if (!ehea_bmap->top[top])
@@ -587,53 +587,124 @@ static inline int ehea_init_bmap(struct ehea_bmap *ehea_bmap, int top, int dir)
return ehea_init_top_bmap(ehea_bmap->top[top], dir);
}
-static int ehea_create_busmap_callback(unsigned long pfn,
- unsigned long nr_pages, void *arg)
-{
- unsigned long i, mr_len, start_section, end_section;
- start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
- end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
- mr_len = *(unsigned long *)arg;
+static DEFINE_MUTEX(ehea_busmap_mutex);
+static unsigned long ehea_mr_len;
- if (!ehea_bmap)
- ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
- if (!ehea_bmap)
- return -ENOMEM;
+#define EHEA_BUSMAP_ADD_SECT 1
+#define EHEA_BUSMAP_REM_SECT 0
- for (i = start_section; i < end_section; i++) {
- int ret;
- int top, dir, idx;
- u64 vaddr;
+static void ehea_rebuild_busmap(void)
+{
+ u64 vaddr = EHEA_BUSMAP_START;
+ int top, dir, idx;
+
+ for (top = 0; top < EHEA_MAP_ENTRIES; top++) {
+ struct ehea_top_bmap *ehea_top;
+ int valid_dir_entries = 0;
- top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
- dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
+ if (!ehea_bmap->top[top])
+ continue;
+ ehea_top = ehea_bmap->top[top];
+ for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) {
+ struct ehea_dir_bmap *ehea_dir;
+ int valid_entries = 0;
- ret = ehea_init_bmap(ehea_bmap, top, dir);
- if(ret)
- return ret;
+ if (!ehea_top->dir[dir])
+ continue;
+ valid_dir_entries++;
+ ehea_dir = ehea_top->dir[dir];
+ for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) {
+ if (!ehea_dir->ent[idx])
+ continue;
+ valid_entries++;
+ ehea_dir->ent[idx] = vaddr;
+ vaddr += EHEA_SECTSIZE;
+ }
+ if (!valid_entries) {
+ ehea_top->dir[dir] = NULL;
+ kfree(ehea_dir);
+ }
+ }
+ if (!valid_dir_entries) {
+ ehea_bmap->top[top] = NULL;
+ kfree(ehea_top);
+ }
+ }
+}
- idx = i & EHEA_INDEX_MASK;
- vaddr = EHEA_BUSMAP_START + mr_len + i * EHEA_SECTSIZE;
+static int ehea_update_busmap(unsigned long pfn, unsigned long pgnum, int add)
+{
+ unsigned long i, start_section, end_section;
- ehea_bmap->top[top]->dir[dir]->ent[idx] = vaddr;
+ if (!ehea_bmap) {
+ ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
+ if (!ehea_bmap)
+ return -ENOMEM;
}
- mr_len += nr_pages * PAGE_SIZE;
- *(unsigned long *)arg = mr_len;
+ start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
+ end_section = start_section + ((pgnum * PAGE_SIZE) / EHEA_SECTSIZE);
+ /* Mark entries as valid or invalid only; address is assigned later */
+ for (i = start_section; i < end_section; i++) {
+ u64 flag;
+ int top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
+ int dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
+ int idx = i & EHEA_INDEX_MASK;
+
+ if (add) {
+ int ret = ehea_init_bmap(ehea_bmap, top, dir);
+ if (ret)
+ return ret;
+ flag = 1; /* valid */
+ ehea_mr_len += EHEA_SECTSIZE;
+ } else {
+ if (!ehea_bmap->top[top])
+ continue;
+ if (!ehea_bmap->top[top]->dir[dir])
+ continue;
+ flag = 0; /* invalid */
+ ehea_mr_len -= EHEA_SECTSIZE;
+ }
+ ehea_bmap->top[top]->dir[dir]->ent[idx] = flag;
+ }
+ ehea_rebuild_busmap(); /* Assign contiguous addresses for mr */
return 0;
}
-static unsigned long ehea_mr_len;
+int ehea_add_sect_bmap(unsigned long pfn, unsigned long nr_pages)
+{
+ int ret;
-static DEFINE_MUTEX(ehea_busmap_mutex);
+ mutex_lock(&ehea_busmap_mutex);
+ ret = ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
+ mutex_unlock(&ehea_busmap_mutex);
+ return ret;
+}
+
+int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages)
+{
+ int ret;
+
+ mutex_lock(&ehea_busmap_mutex);
+ ret = ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_REM_SECT);
+ mutex_unlock(&ehea_busmap_mutex);
+ return ret;
+}
+
+static int ehea_create_busmap_callback(unsigned long pfn,
+ unsigned long nr_pages, void *arg)
+{
+ return ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
+}
int ehea_create_busmap(void)
{
int ret;
+
mutex_lock(&ehea_busmap_mutex);
ehea_mr_len = 0;
- ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, &ehea_mr_len,
+ ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
ehea_create_busmap_callback);
mutex_unlock(&ehea_busmap_mutex);
return ret;
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index 0bb6f92fa2f..1e58dc06b7d 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -378,6 +378,8 @@ int ehea_rem_mr(struct ehea_mr *mr);
void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
+int ehea_add_sect_bmap(unsigned long pfn, unsigned long nr_pages);
+int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages);
int ehea_create_busmap(void);
void ehea_destroy_busmap(void);
u64 ehea_map_vaddr(void *caddr);
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 4e4f68304e8..aec3b97e794 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -401,6 +401,21 @@ static int mpc52xx_fec_hard_start_xmit(struct sk_buff *skb, struct net_device *d
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void mpc52xx_fec_poll_controller(struct net_device *dev)
+{
+ struct mpc52xx_fec_priv *priv = netdev_priv(dev);
+
+ disable_irq(priv->t_irq);
+ mpc52xx_fec_tx_interrupt(priv->t_irq, dev);
+ enable_irq(priv->t_irq);
+ disable_irq(priv->r_irq);
+ mpc52xx_fec_rx_interrupt(priv->r_irq, dev);
+ enable_irq(priv->r_irq);
+}
+#endif
+
+
/* This handles BestComm transmit task interrupts
*/
static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
@@ -926,6 +941,9 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
ndev->tx_timeout = mpc52xx_fec_tx_timeout;
ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT;
ndev->base_addr = mem.start;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = mpc52xx_fec_poll_controller;
+#endif
priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
index 08e18bcb970..45dd9bdc5d6 100644
--- a/drivers/net/fec_mpc52xx_phy.c
+++ b/drivers/net/fec_mpc52xx_phy.c
@@ -2,6 +2,7 @@
* Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver
*
* Copyright (C) 2007 Domen Puncer, Telargo, Inc.
+ * Copyright (C) 2008 Wolfram Sang, Pengutronix
*
* 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
@@ -21,58 +22,45 @@ struct mpc52xx_fec_mdio_priv {
struct mpc52xx_fec __iomem *regs;
};
-static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id,
+ int reg, u32 value)
{
struct mpc52xx_fec_mdio_priv *priv = bus->priv;
struct mpc52xx_fec __iomem *fec;
int tries = 100;
- u32 request = FEC_MII_READ_FRAME;
+
+ value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
+ value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
fec = priv->regs;
out_be32(&fec->ievent, FEC_IEVENT_MII);
-
- request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
- request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
-
- out_be32(&priv->regs->mii_data, request);
+ out_be32(&priv->regs->mii_data, value);
/* wait for it to finish, this takes about 23 us on lite5200b */
while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
udelay(5);
- if (tries == 0)
+ if (!tries)
return -ETIMEDOUT;
- return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK;
+ return value & FEC_MII_DATA_OP_RD ?
+ in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK : 0;
}
-static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
+static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
{
- struct mpc52xx_fec_mdio_priv *priv = bus->priv;
- struct mpc52xx_fec __iomem *fec;
- u32 value = data;
- int tries = 100;
-
- fec = priv->regs;
- out_be32(&fec->ievent, FEC_IEVENT_MII);
-
- value |= FEC_MII_WRITE_FRAME;
- value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
- value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
-
- out_be32(&priv->regs->mii_data, value);
-
- /* wait for request to finish */
- while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
- udelay(5);
-
- if (tries == 0)
- return -ETIMEDOUT;
+ return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, FEC_MII_READ_FRAME);
+}
- return 0;
+static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg,
+ u16 data)
+{
+ return mpc52xx_fec_mdio_transfer(bus, phy_id, reg,
+ data | FEC_MII_WRITE_FRAME);
}
-static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match)
+static int mpc52xx_fec_mdio_probe(struct of_device *of,
+ const struct of_device_id *match)
{
struct device *dev = &of->dev;
struct device_node *np = of->node;
@@ -131,7 +119,8 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i
dev_set_drvdata(dev, bus);
/* set MII speed */
- out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
+ out_be32(&priv->regs->mii_speed,
+ ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
/* enable MII interrupt */
out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII);
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index b5bb7ae2817..64b201134fd 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -161,7 +161,7 @@ static int gfar_probe(struct platform_device *pdev)
struct gfar_private *priv = NULL;
struct gianfar_platform_data *einfo;
struct resource *r;
- int err = 0;
+ int err = 0, irq;
DECLARE_MAC_BUF(mac);
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
@@ -187,15 +187,25 @@ static int gfar_probe(struct platform_device *pdev)
/* fill out IRQ fields */
if (einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- priv->interruptTransmit = platform_get_irq_byname(pdev, "tx");
- priv->interruptReceive = platform_get_irq_byname(pdev, "rx");
- priv->interruptError = platform_get_irq_byname(pdev, "error");
- if (priv->interruptTransmit < 0 || priv->interruptReceive < 0 || priv->interruptError < 0)
+ irq = platform_get_irq_byname(pdev, "tx");
+ if (irq < 0)
+ goto regs_fail;
+ priv->interruptTransmit = irq;
+
+ irq = platform_get_irq_byname(pdev, "rx");
+ if (irq < 0)
+ goto regs_fail;
+ priv->interruptReceive = irq;
+
+ irq = platform_get_irq_byname(pdev, "error");
+ if (irq < 0)
goto regs_fail;
+ priv->interruptError = irq;
} else {
- priv->interruptTransmit = platform_get_irq(pdev, 0);
- if (priv->interruptTransmit < 0)
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
goto regs_fail;
+ priv->interruptTransmit = irq;
}
/* get a pointer to the register memory */
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 17ac6975d70..b6a816e60c0 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -416,10 +416,10 @@ static int ser12_open(struct net_device *dev)
if (!dev || !bc)
return -ENXIO;
if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||
- dev->irq < 2 || dev->irq > NR_IRQS) {
+ dev->irq < 2 || dev->irq > nr_irqs) {
printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "
"or irq (2 <= irq <= %d)\n",
- 0xffff-SER12_EXTENT, NR_IRQS);
+ 0xffff-SER12_EXTENT, nr_irqs);
return -ENXIO;
}
if (bc->baud < 300 || bc->baud > 4800) {
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 45ae9d1191d..c17e39bc546 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1465,7 +1465,7 @@ static void z8530_init(void)
printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
flag=" ";
- for (k = 0; k < NR_IRQS; k++)
+ for (k = 0; k < nr_irqs; k++)
if (Ivec[k].used)
{
printk("%s%d", flag, k);
@@ -1728,7 +1728,7 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (hwcfg.irq == 2) hwcfg.irq = 9;
- if (hwcfg.irq < 0 || hwcfg.irq >= NR_IRQS)
+ if (hwcfg.irq < 0 || hwcfg.irq >= nr_irqs)
return -EINVAL;
if (!Ivec[hwcfg.irq].used && hwcfg.irq)
@@ -2148,7 +2148,7 @@ static void __exit scc_cleanup_driver(void)
}
/* To unload the port must be closed so no real IRQ pending */
- for (k=0; k < NR_IRQS ; k++)
+ for (k = 0; k < nr_irqs ; k++)
if (Ivec[k].used) free_irq(k, NULL);
local_irq_enable();
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index efcf21c9f5c..2ee2622258f 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2604,8 +2604,16 @@ static int __devinit emac_init_config(struct emac_instance *dev)
if (of_device_is_compatible(np, "ibm,emac-440ep") ||
of_device_is_compatible(np, "ibm,emac-440gr"))
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
- if (of_device_is_compatible(np, "ibm,emac-405ez"))
+ if (of_device_is_compatible(np, "ibm,emac-405ez")) {
+#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CONTROL
dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
+#else
+ printk(KERN_ERR "%s: Flow control not disabled!\n",
+ np->full_name);
+ return -ENXIO;
+#endif
+ }
+
}
/* Fixup some feature bits based on the device tree */
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 1839d3f154a..ecf9798987f 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -280,9 +280,11 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
mal_schedule_poll(mal);
set_mal_dcrn(mal, MAL_TXEOBISR, r);
+#ifdef CONFIG_PPC_DCR_NATIVE
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
+#endif
return IRQ_HANDLED;
}
@@ -298,9 +300,11 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
mal_schedule_poll(mal);
set_mal_dcrn(mal, MAL_RXEOBISR, r);
+#ifdef CONFIG_PPC_DCR_NATIVE
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
+#endif
return IRQ_HANDLED;
}
@@ -572,9 +576,18 @@ static int __devinit mal_probe(struct of_device *ofdev,
goto fail;
}
- if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
+ if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez")) {
+#if defined(CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT) && \
+ defined(CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR)
mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
MAL_FTR_COMMON_ERR_INT);
+#else
+ printk(KERN_ERR "%s: Support for 405EZ not enabled!\n",
+ ofdev->node->full_name);
+ err = -ENODEV;
+ goto fail;
+#endif
+ }
mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 93d02efa9a0..1f397cd9941 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -38,10 +38,11 @@
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/pci.h>
+#include <linux/pci-aspm.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
#include <linux/dca.h>
#endif
#include "igb.h"
@@ -106,11 +107,11 @@ static irqreturn_t igb_msix_other(int irq, void *);
static irqreturn_t igb_msix_rx(int irq, void *);
static irqreturn_t igb_msix_tx(int irq, void *);
static int igb_clean_rx_ring_msix(struct napi_struct *, int);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
static void igb_update_rx_dca(struct igb_ring *);
static void igb_update_tx_dca(struct igb_ring *);
static void igb_setup_dca(struct igb_adapter *);
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_IGB_DCA */
static bool igb_clean_tx_irq(struct igb_ring *);
static int igb_poll(struct napi_struct *, int);
static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int);
@@ -131,7 +132,7 @@ static int igb_suspend(struct pci_dev *, pm_message_t);
static int igb_resume(struct pci_dev *);
#endif
static void igb_shutdown(struct pci_dev *);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
static int igb_notify_dca(struct notifier_block *, unsigned long, void *);
static struct notifier_block dca_notifier = {
.notifier_call = igb_notify_dca,
@@ -207,7 +208,7 @@ static int __init igb_init_module(void)
global_quad_port_a = 0;
ret = pci_register_driver(&igb_driver);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
dca_register_notify(&dca_notifier);
#endif
return ret;
@@ -223,7 +224,7 @@ module_init(igb_init_module);
**/
static void __exit igb_exit_module(void)
{
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
dca_unregister_notify(&dca_notifier);
#endif
pci_unregister_driver(&igb_driver);
@@ -966,10 +967,11 @@ static int __devinit igb_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct igb_adapter *adapter;
struct e1000_hw *hw;
+ struct pci_dev *us_dev;
const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
unsigned long mmio_start, mmio_len;
- int i, err, pci_using_dac;
- u16 eeprom_data = 0;
+ int i, err, pci_using_dac, pos;
+ u16 eeprom_data = 0, state = 0;
u16 eeprom_apme_mask = IGB_EEPROM_APME;
u32 part_num;
int bars, need_ioport;
@@ -1004,6 +1006,28 @@ static int __devinit igb_probe(struct pci_dev *pdev,
}
}
+ /* 82575 requires that the pci-e link partner disable the L0s state */
+ switch (pdev->device) {
+ case E1000_DEV_ID_82575EB_COPPER:
+ case E1000_DEV_ID_82575EB_FIBER_SERDES:
+ case E1000_DEV_ID_82575GB_QUAD_COPPER:
+ us_dev = pdev->bus->self;
+ pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP);
+ if (pos) {
+ pci_read_config_word(us_dev, pos + PCI_EXP_LNKCTL,
+ &state);
+ state &= ~PCIE_LINK_STATE_L0S;
+ pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL,
+ state);
+ printk(KERN_INFO "Disabling ASPM L0s upstream switch "
+ "port %x:%x.%x\n", us_dev->bus->number,
+ PCI_SLOT(us_dev->devfn),
+ PCI_FUNC(us_dev->devfn));
+ }
+ default:
+ break;
+ }
+
err = pci_request_selected_regions(pdev, bars, igb_driver_name);
if (err)
goto err_pci_reg;
@@ -1237,7 +1261,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
if (err)
goto err_register;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if ((adapter->flags & IGB_FLAG_HAS_DCA) &&
(dca_add_requester(&pdev->dev) == 0)) {
adapter->flags |= IGB_FLAG_DCA_ENABLED;
@@ -1311,7 +1335,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
struct e1000_hw *hw = &adapter->hw;
#endif
@@ -1323,7 +1347,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
flush_scheduled_work();
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED) {
dev_info(&pdev->dev, "DCA disabled\n");
dca_remove_requester(&pdev->dev);
@@ -3271,7 +3295,7 @@ static irqreturn_t igb_msix_tx(int irq, void *data)
struct igb_adapter *adapter = tx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_tx_dca(tx_ring);
#endif
@@ -3323,14 +3347,14 @@ static irqreturn_t igb_msix_rx(int irq, void *data)
if (netif_rx_schedule_prep(adapter->netdev, &rx_ring->napi))
__netif_rx_schedule(adapter->netdev, &rx_ring->napi);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_rx_dca(rx_ring);
#endif
return IRQ_HANDLED;
}
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
static void igb_update_rx_dca(struct igb_ring *rx_ring)
{
u32 dca_rxctrl;
@@ -3450,7 +3474,7 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event,
return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_IGB_DCA */
/**
* igb_intr_msi - Interrupt Handler
@@ -3529,13 +3553,13 @@ static int igb_poll(struct napi_struct *napi, int budget)
int tx_clean_complete, work_done = 0;
/* this poll routine only supports one tx and one rx queue */
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_tx_dca(&adapter->tx_ring[0]);
#endif
tx_clean_complete = igb_clean_tx_irq(&adapter->tx_ring[0]);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_rx_dca(&adapter->rx_ring[0]);
#endif
@@ -3563,7 +3587,7 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget)
struct net_device *netdev = adapter->netdev;
int work_done = 0;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IGB_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_rx_dca(rx_ring);
#endif
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 0952a6528f5..a7a97bf998f 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -1,4 +1,9 @@
obj-$(CONFIG_MLX4_CORE) += mlx4_core.o
mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
- mr.o pd.o profile.o qp.o reset.o srq.o
+ mr.o pd.o port.o profile.o qp.o reset.o srq.o
+
+obj-$(CONFIG_MLX4_EN) += mlx4_en.o
+
+mlx4_en-y := en_main.o en_tx.o en_rx.o en_params.o en_port.o en_cq.o \
+ en_resources.o en_netdev.o
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index b411b79d72a..ad95d5f7b63 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -48,13 +48,16 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
if (obj >= bitmap->max) {
- bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
+ bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
+ & bitmap->mask;
obj = find_first_zero_bit(bitmap->table, bitmap->max);
}
if (obj < bitmap->max) {
set_bit(obj, bitmap->table);
- bitmap->last = (obj + 1) & (bitmap->max - 1);
+ bitmap->last = (obj + 1);
+ if (bitmap->last == bitmap->max)
+ bitmap->last = 0;
obj |= bitmap->top;
} else
obj = -1;
@@ -66,16 +69,90 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
{
- obj &= bitmap->max - 1;
+ mlx4_bitmap_free_range(bitmap, obj, 1);
+}
+
+static unsigned long find_aligned_range(unsigned long *bitmap,
+ u32 start, u32 nbits,
+ int len, int align)
+{
+ unsigned long end, i;
+
+again:
+ start = ALIGN(start, align);
+
+ while ((start < nbits) && test_bit(start, bitmap))
+ start += align;
+
+ if (start >= nbits)
+ return -1;
+
+ end = start+len;
+ if (end > nbits)
+ return -1;
+
+ for (i = start + 1; i < end; i++) {
+ if (test_bit(i, bitmap)) {
+ start = i + 1;
+ goto again;
+ }
+ }
+
+ return start;
+}
+
+u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
+{
+ u32 obj, i;
+
+ if (likely(cnt == 1 && align == 1))
+ return mlx4_bitmap_alloc(bitmap);
+
+ spin_lock(&bitmap->lock);
+
+ obj = find_aligned_range(bitmap->table, bitmap->last,
+ bitmap->max, cnt, align);
+ if (obj >= bitmap->max) {
+ bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
+ & bitmap->mask;
+ obj = find_aligned_range(bitmap->table, 0, bitmap->max,
+ cnt, align);
+ }
+
+ if (obj < bitmap->max) {
+ for (i = 0; i < cnt; i++)
+ set_bit(obj + i, bitmap->table);
+ if (obj == bitmap->last) {
+ bitmap->last = (obj + cnt);
+ if (bitmap->last >= bitmap->max)
+ bitmap->last = 0;
+ }
+ obj |= bitmap->top;
+ } else
+ obj = -1;
+
+ spin_unlock(&bitmap->lock);
+
+ return obj;
+}
+
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
+{
+ u32 i;
+
+ obj &= bitmap->max + bitmap->reserved_top - 1;
spin_lock(&bitmap->lock);
- clear_bit(obj, bitmap->table);
+ for (i = 0; i < cnt; i++)
+ clear_bit(obj + i, bitmap->table);
bitmap->last = min(bitmap->last, obj);
- bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
+ bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
+ & bitmap->mask;
spin_unlock(&bitmap->lock);
}
-int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved)
+int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
+ u32 reserved_bot, u32 reserved_top)
{
int i;
@@ -85,14 +162,16 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved
bitmap->last = 0;
bitmap->top = 0;
- bitmap->max = num;
+ bitmap->max = num - reserved_top;
bitmap->mask = mask;
+ bitmap->reserved_top = reserved_top;
spin_lock_init(&bitmap->lock);
- bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL);
+ bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
+ sizeof (long), GFP_KERNEL);
if (!bitmap->table)
return -ENOMEM;
- for (i = 0; i < reserved; ++i)
+ for (i = 0; i < reserved_bot; ++i)
set_bit(i, bitmap->table);
return 0;
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index 9bb50e3f897..b7ad2829d67 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -300,7 +300,7 @@ int mlx4_init_cq_table(struct mlx4_dev *dev)
INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC);
err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs,
- dev->caps.num_cqs - 1, dev->caps.reserved_cqs);
+ dev->caps.num_cqs - 1, dev->caps.reserved_cqs, 0);
if (err)
return err;
diff --git a/drivers/net/mlx4/en_cq.c b/drivers/net/mlx4/en_cq.c
new file mode 100644
index 00000000000..1368a8010af
--- /dev/null
+++ b/drivers/net/mlx4/en_cq.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/mlx4/cq.h>
+#include <linux/mlx4/qp.h>
+#include <linux/mlx4/cmd.h>
+
+#include "mlx4_en.h"
+
+static void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event)
+{
+ return;
+}
+
+
+int mlx4_en_create_cq(struct mlx4_en_priv *priv,
+ struct mlx4_en_cq *cq,
+ int entries, int ring, enum cq_type mode)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ cq->size = entries;
+ if (mode == RX)
+ cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
+ else
+ cq->buf_size = sizeof(struct mlx4_cqe);
+
+ cq->ring = ring;
+ cq->is_tx = mode;
+ spin_lock_init(&cq->lock);
+
+ err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres,
+ cq->buf_size, 2 * PAGE_SIZE);
+ if (err)
+ return err;
+
+ err = mlx4_en_map_buffer(&cq->wqres.buf);
+ if (err)
+ mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
+
+ return err;
+}
+
+int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ cq->dev = mdev->pndev[priv->port];
+ cq->mcq.set_ci_db = cq->wqres.db.db;
+ cq->mcq.arm_db = cq->wqres.db.db + 1;
+ *cq->mcq.set_ci_db = 0;
+ *cq->mcq.arm_db = 0;
+ cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
+ memset(cq->buf, 0, cq->buf_size);
+
+ err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar,
+ cq->wqres.db.dma, &cq->mcq, cq->is_tx);
+ if (err)
+ return err;
+
+ cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
+ cq->mcq.event = mlx4_en_cq_event;
+
+ if (cq->is_tx) {
+ init_timer(&cq->timer);
+ cq->timer.function = mlx4_en_poll_tx_cq;
+ cq->timer.data = (unsigned long) cq;
+ } else {
+ netif_napi_add(cq->dev, &cq->napi, mlx4_en_poll_rx_cq, 64);
+ napi_enable(&cq->napi);
+ }
+
+ return 0;
+}
+
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ mlx4_en_unmap_buffer(&cq->wqres.buf);
+ mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
+ cq->buf_size = 0;
+ cq->buf = NULL;
+}
+
+void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ if (cq->is_tx)
+ del_timer(&cq->timer);
+ else
+ napi_disable(&cq->napi);
+
+ mlx4_cq_free(mdev->dev, &cq->mcq);
+}
+
+/* Set rx cq moderation parameters */
+int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+{
+ return mlx4_cq_modify(priv->mdev->dev, &cq->mcq,
+ cq->moder_cnt, cq->moder_time);
+}
+
+int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+{
+ cq->armed = 1;
+ mlx4_cq_arm(&cq->mcq, MLX4_CQ_DB_REQ_NOT, priv->mdev->uar_map,
+ &priv->mdev->uar_lock);
+
+ return 0;
+}
+
+
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
new file mode 100644
index 00000000000..1b0eebf84f7
--- /dev/null
+++ b/drivers/net/mlx4/en_main.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/cpumask.h>
+
+#include <linux/mlx4/driver.h>
+#include <linux/mlx4/device.h>
+#include <linux/mlx4/cmd.h>
+
+#include "mlx4_en.h"
+
+MODULE_AUTHOR("Liran Liss, Yevgeny Petrilin");
+MODULE_DESCRIPTION("Mellanox ConnectX HCA Ethernet driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRV_VERSION " ("DRV_RELDATE")");
+
+static const char mlx4_en_version[] =
+ DRV_NAME ": Mellanox ConnectX HCA Ethernet driver v"
+ DRV_VERSION " (" DRV_RELDATE ")\n";
+
+static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
+ enum mlx4_dev_event event, int port)
+{
+ struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr;
+ struct mlx4_en_priv *priv;
+
+ if (!mdev->pndev[port])
+ return;
+
+ priv = netdev_priv(mdev->pndev[port]);
+ switch (event) {
+ case MLX4_DEV_EVENT_PORT_UP:
+ case MLX4_DEV_EVENT_PORT_DOWN:
+ /* To prevent races, we poll the link state in a separate
+ task rather than changing it here */
+ priv->link_state = event;
+ queue_work(mdev->workqueue, &priv->linkstate_task);
+ break;
+
+ case MLX4_DEV_EVENT_CATASTROPHIC_ERROR:
+ mlx4_err(mdev, "Internal error detected, restarting device\n");
+ break;
+
+ default:
+ mlx4_warn(mdev, "Unhandled event: %d\n", event);
+ }
+}
+
+static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
+{
+ struct mlx4_en_dev *mdev = endev_ptr;
+ int i;
+
+ mutex_lock(&mdev->state_lock);
+ mdev->device_up = false;
+ mutex_unlock(&mdev->state_lock);
+
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
+ if (mdev->pndev[i])
+ mlx4_en_destroy_netdev(mdev->pndev[i]);
+
+ flush_workqueue(mdev->workqueue);
+ destroy_workqueue(mdev->workqueue);
+ mlx4_mr_free(dev, &mdev->mr);
+ mlx4_uar_free(dev, &mdev->priv_uar);
+ mlx4_pd_free(dev, mdev->priv_pdn);
+ kfree(mdev);
+}
+
+static void *mlx4_en_add(struct mlx4_dev *dev)
+{
+ static int mlx4_en_version_printed;
+ struct mlx4_en_dev *mdev;
+ int i;
+ int err;
+
+ if (!mlx4_en_version_printed) {
+ printk(KERN_INFO "%s", mlx4_en_version);
+ mlx4_en_version_printed++;
+ }
+
+ mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
+ if (!mdev) {
+ dev_err(&dev->pdev->dev, "Device struct alloc failed, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_free_res;
+ }
+
+ if (mlx4_pd_alloc(dev, &mdev->priv_pdn))
+ goto err_free_dev;
+
+ if (mlx4_uar_alloc(dev, &mdev->priv_uar))
+ goto err_pd;
+
+ mdev->uar_map = ioremap(mdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+ if (!mdev->uar_map)
+ goto err_uar;
+ spin_lock_init(&mdev->uar_lock);
+
+ mdev->dev = dev;
+ mdev->dma_device = &(dev->pdev->dev);
+ mdev->pdev = dev->pdev;
+ mdev->device_up = false;
+
+ mdev->LSO_support = !!(dev->caps.flags & (1 << 15));
+ if (!mdev->LSO_support)
+ mlx4_warn(mdev, "LSO not supported, please upgrade to later "
+ "FW version to enable LSO\n");
+
+ if (mlx4_mr_alloc(mdev->dev, mdev->priv_pdn, 0, ~0ull,
+ MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ,
+ 0, 0, &mdev->mr)) {
+ mlx4_err(mdev, "Failed allocating memory region\n");
+ goto err_uar;
+ }
+ if (mlx4_mr_enable(mdev->dev, &mdev->mr)) {
+ mlx4_err(mdev, "Failed enabling memory region\n");
+ goto err_mr;
+ }
+
+ /* Build device profile according to supplied module parameters */
+ err = mlx4_en_get_profile(mdev);
+ if (err) {
+ mlx4_err(mdev, "Bad module parameters, aborting.\n");
+ goto err_mr;
+ }
+
+ /* Configure wich ports to start according to module parameters */
+ mdev->port_cnt = 0;
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
+ mdev->port_cnt++;
+
+ /* If we did not receive an explicit number of Rx rings, default to
+ * the number of completion vectors populated by the mlx4_core */
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+ mlx4_info(mdev, "Using %d tx rings for port:%d\n",
+ mdev->profile.prof[i].tx_ring_num, i);
+ if (!mdev->profile.prof[i].rx_ring_num) {
+ mdev->profile.prof[i].rx_ring_num = 1;
+ mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
+ 1, i);
+ } else
+ mlx4_info(mdev, "Using %d rx rings for port:%d\n",
+ mdev->profile.prof[i].rx_ring_num, i);
+ }
+
+ /* Create our own workqueue for reset/multicast tasks
+ * Note: we cannot use the shared workqueue because of deadlocks caused
+ * by the rtnl lock */
+ mdev->workqueue = create_singlethread_workqueue("mlx4_en");
+ if (!mdev->workqueue) {
+ err = -ENOMEM;
+ goto err_close_nic;
+ }
+
+ /* At this stage all non-port specific tasks are complete:
+ * mark the card state as up */
+ mutex_init(&mdev->state_lock);
+ mdev->device_up = true;
+
+ /* Setup ports */
+
+ /* Create a netdev for each port */
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+ mlx4_info(mdev, "Activating port:%d\n", i);
+ if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) {
+ mdev->pndev[i] = NULL;
+ goto err_free_netdev;
+ }
+ }
+ return mdev;
+
+
+err_free_netdev:
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+ if (mdev->pndev[i])
+ mlx4_en_destroy_netdev(mdev->pndev[i]);
+ }
+
+ mutex_lock(&mdev->state_lock);
+ mdev->device_up = false;
+ mutex_unlock(&mdev->state_lock);
+ flush_workqueue(mdev->workqueue);
+
+ /* Stop event queue before we drop down to release shared SW state */
+
+err_close_nic:
+ destroy_workqueue(mdev->workqueue);
+err_mr:
+ mlx4_mr_free(dev, &mdev->mr);
+err_uar:
+ mlx4_uar_free(dev, &mdev->priv_uar);
+err_pd:
+ mlx4_pd_free(dev, mdev->priv_pdn);
+err_free_dev:
+ kfree(mdev);
+err_free_res:
+ return NULL;
+}
+
+static struct mlx4_interface mlx4_en_interface = {
+ .add = mlx4_en_add,
+ .remove = mlx4_en_remove,
+ .event = mlx4_en_event,
+};
+
+static int __init mlx4_en_init(void)
+{
+ return mlx4_register_interface(&mlx4_en_interface);
+}
+
+static void __exit mlx4_en_cleanup(void)
+{
+ mlx4_unregister_interface(&mlx4_en_interface);
+}
+
+module_init(mlx4_en_init);
+module_exit(mlx4_en_cleanup);
+
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
new file mode 100644
index 00000000000..a339afbeed3
--- /dev/null
+++ b/drivers/net/mlx4/en_netdev.c
@@ -0,0 +1,1088 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/tcp.h>
+#include <linux/if_vlan.h>
+#include <linux/delay.h>
+
+#include <linux/mlx4/driver.h>
+#include <linux/mlx4/device.h>
+#include <linux/mlx4/cmd.h>
+#include <linux/mlx4/cq.h>
+
+#include "mlx4_en.h"
+#include "en_port.h"
+
+
+static void mlx4_en_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ mlx4_dbg(HW, priv, "Registering VLAN group:%p\n", grp);
+ priv->vlgrp = grp;
+
+ mutex_lock(&mdev->state_lock);
+ if (mdev->device_up && priv->port_up) {
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, grp);
+ if (err)
+ mlx4_err(mdev, "Failed configuring VLAN filter\n");
+ }
+ mutex_unlock(&mdev->state_lock);
+}
+
+static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ if (!priv->vlgrp)
+ return;
+
+ mlx4_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n",
+ vid, vlan_group_get_device(priv->vlgrp, vid));
+
+ /* Add VID to port VLAN filter */
+ mutex_lock(&mdev->state_lock);
+ if (mdev->device_up && priv->port_up) {
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+ if (err)
+ mlx4_err(mdev, "Failed configuring VLAN filter\n");
+ }
+ mutex_unlock(&mdev->state_lock);
+}
+
+static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ if (!priv->vlgrp)
+ return;
+
+ mlx4_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp "
+ "entry:%p)\n", vid, priv->vlgrp,
+ vlan_group_get_device(priv->vlgrp, vid));
+ vlan_group_set_device(priv->vlgrp, vid, NULL);
+
+ /* Remove VID from port VLAN filter */
+ mutex_lock(&mdev->state_lock);
+ if (mdev->device_up && priv->port_up) {
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+ if (err)
+ mlx4_err(mdev, "Failed configuring VLAN filter\n");
+ }
+ mutex_unlock(&mdev->state_lock);
+}
+
+static u64 mlx4_en_mac_to_u64(u8 *addr)
+{
+ u64 mac = 0;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ mac <<= 8;
+ mac |= addr[i];
+ }
+ return mac;
+}
+
+static int mlx4_en_set_mac(struct net_device *dev, void *addr)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct sockaddr *saddr = addr;
+
+ if (!is_valid_ether_addr(saddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
+ priv->mac = mlx4_en_mac_to_u64(dev->dev_addr);
+ queue_work(mdev->workqueue, &priv->mac_task);
+ return 0;
+}
+
+static void mlx4_en_do_set_mac(struct work_struct *work)
+{
+ struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
+ mac_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err = 0;
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ /* Remove old MAC and insert the new one */
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+ err = mlx4_register_mac(mdev->dev, priv->port,
+ priv->mac, &priv->mac_index);
+ if (err)
+ mlx4_err(mdev, "Failed changing HW MAC address\n");
+ } else
+ mlx4_dbg(HW, priv, "Port is down, exiting...\n");
+
+ mutex_unlock(&mdev->state_lock);
+}
+
+static void mlx4_en_clear_list(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct dev_mc_list *plist = priv->mc_list;
+ struct dev_mc_list *next;
+
+ while (plist) {
+ next = plist->next;
+ kfree(plist);
+ plist = next;
+ }
+ priv->mc_list = NULL;
+}
+
+static void mlx4_en_cache_mclist(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct dev_mc_list *mclist;
+ struct dev_mc_list *tmp;
+ struct dev_mc_list *plist = NULL;
+
+ for (mclist = dev->mc_list; mclist; mclist = mclist->next) {
+ tmp = kmalloc(sizeof(struct dev_mc_list), GFP_ATOMIC);
+ if (!tmp) {
+ mlx4_err(mdev, "failed to allocate multicast list\n");
+ mlx4_en_clear_list(dev);
+ return;
+ }
+ memcpy(tmp, mclist, sizeof(struct dev_mc_list));
+ tmp->next = NULL;
+ if (plist)
+ plist->next = tmp;
+ else
+ priv->mc_list = tmp;
+ plist = tmp;
+ }
+}
+
+
+static void mlx4_en_set_multicast(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ if (!priv->port_up)
+ return;
+
+ queue_work(priv->mdev->workqueue, &priv->mcast_task);
+}
+
+static void mlx4_en_do_set_multicast(struct work_struct *work)
+{
+ struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
+ mcast_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct net_device *dev = priv->dev;
+ struct dev_mc_list *mclist;
+ u64 mcast_addr = 0;
+ int err;
+
+ mutex_lock(&mdev->state_lock);
+ if (!mdev->device_up) {
+ mlx4_dbg(HW, priv, "Card is not up, ignoring "
+ "multicast change.\n");
+ goto out;
+ }
+ if (!priv->port_up) {
+ mlx4_dbg(HW, priv, "Port is down, ignoring "
+ "multicast change.\n");
+ goto out;
+ }
+
+ /*
+ * Promsicuous mode: disable all filters
+ */
+
+ if (dev->flags & IFF_PROMISC) {
+ if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
+ if (netif_msg_rx_status(priv))
+ mlx4_warn(mdev, "Port:%d entering promiscuous mode\n",
+ priv->port);
+ priv->flags |= MLX4_EN_FLAG_PROMISC;
+
+ /* Enable promiscouos mode */
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
+ priv->base_qpn, 1);
+ if (err)
+ mlx4_err(mdev, "Failed enabling "
+ "promiscous mode\n");
+
+ /* Disable port multicast filter (unconditionally) */
+ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
+ 0, MLX4_MCAST_DISABLE);
+ if (err)
+ mlx4_err(mdev, "Failed disabling "
+ "multicast filter\n");
+
+ /* Disable port VLAN filter */
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
+ if (err)
+ mlx4_err(mdev, "Failed disabling "
+ "VLAN filter\n");
+ }
+ goto out;
+ }
+
+ /*
+ * Not in promiscous mode
+ */
+
+ if (priv->flags & MLX4_EN_FLAG_PROMISC) {
+ if (netif_msg_rx_status(priv))
+ mlx4_warn(mdev, "Port:%d leaving promiscuous mode\n",
+ priv->port);
+ priv->flags &= ~MLX4_EN_FLAG_PROMISC;
+
+ /* Disable promiscouos mode */
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
+ priv->base_qpn, 0);
+ if (err)
+ mlx4_err(mdev, "Failed disabling promiscous mode\n");
+
+ /* Enable port VLAN filter */
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+ if (err)
+ mlx4_err(mdev, "Failed enabling VLAN filter\n");
+ }
+
+ /* Enable/disable the multicast filter according to IFF_ALLMULTI */
+ if (dev->flags & IFF_ALLMULTI) {
+ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
+ 0, MLX4_MCAST_DISABLE);
+ if (err)
+ mlx4_err(mdev, "Failed disabling multicast filter\n");
+ } else {
+ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
+ 0, MLX4_MCAST_DISABLE);
+ if (err)
+ mlx4_err(mdev, "Failed disabling multicast filter\n");
+
+ /* Flush mcast filter and init it with broadcast address */
+ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
+ 1, MLX4_MCAST_CONFIG);
+
+ /* Update multicast list - we cache all addresses so they won't
+ * change while HW is updated holding the command semaphor */
+ netif_tx_lock_bh(dev);
+ mlx4_en_cache_mclist(dev);
+ netif_tx_unlock_bh(dev);
+ for (mclist = priv->mc_list; mclist; mclist = mclist->next) {
+ mcast_addr = mlx4_en_mac_to_u64(mclist->dmi_addr);
+ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
+ mcast_addr, 0, MLX4_MCAST_CONFIG);
+ }
+ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
+ 0, MLX4_MCAST_ENABLE);
+ if (err)
+ mlx4_err(mdev, "Failed enabling multicast filter\n");
+
+ mlx4_en_clear_list(dev);
+ }
+out:
+ mutex_unlock(&mdev->state_lock);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void mlx4_en_netpoll(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_cq *cq;
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ cq = &priv->rx_cq[i];
+ spin_lock_irqsave(&cq->lock, flags);
+ napi_synchronize(&cq->napi);
+ mlx4_en_process_rx_cq(dev, cq, 0);
+ spin_unlock_irqrestore(&cq->lock, flags);
+ }
+}
+#endif
+
+static void mlx4_en_tx_timeout(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ if (netif_msg_timer(priv))
+ mlx4_warn(mdev, "Tx timeout called on port:%d\n", priv->port);
+
+ if (netif_carrier_ok(dev)) {
+ priv->port_stats.tx_timeout++;
+ mlx4_dbg(DRV, priv, "Scheduling watchdog\n");
+ queue_work(mdev->workqueue, &priv->watchdog_task);
+ }
+}
+
+
+static struct net_device_stats *mlx4_en_get_stats(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ spin_lock_bh(&priv->stats_lock);
+ memcpy(&priv->ret_stats, &priv->stats, sizeof(priv->stats));
+ spin_unlock_bh(&priv->stats_lock);
+
+ return &priv->ret_stats;
+}
+
+static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_cq *cq;
+ int i;
+
+ /* If we haven't received a specific coalescing setting
+ * (module param), we set the moderation paramters as follows:
+ * - moder_cnt is set to the number of mtu sized packets to
+ * satisfy our coelsing target.
+ * - moder_time is set to a fixed value.
+ */
+ priv->rx_frames = (mdev->profile.rx_moder_cnt ==
+ MLX4_EN_AUTO_CONF) ?
+ MLX4_EN_RX_COAL_TARGET /
+ priv->dev->mtu + 1 :
+ mdev->profile.rx_moder_cnt;
+ priv->rx_usecs = (mdev->profile.rx_moder_time ==
+ MLX4_EN_AUTO_CONF) ?
+ MLX4_EN_RX_COAL_TIME :
+ mdev->profile.rx_moder_time;
+ mlx4_dbg(INTR, priv, "Default coalesing params for mtu:%d - "
+ "rx_frames:%d rx_usecs:%d\n",
+ priv->dev->mtu, priv->rx_frames, priv->rx_usecs);
+
+ /* Setup cq moderation params */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ cq = &priv->rx_cq[i];
+ cq->moder_cnt = priv->rx_frames;
+ cq->moder_time = priv->rx_usecs;
+ }
+
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ cq = &priv->tx_cq[i];
+ cq->moder_cnt = MLX4_EN_TX_COAL_PKTS;
+ cq->moder_time = MLX4_EN_TX_COAL_TIME;
+ }
+
+ /* Reset auto-moderation params */
+ priv->pkt_rate_low = MLX4_EN_RX_RATE_LOW;
+ priv->rx_usecs_low = MLX4_EN_RX_COAL_TIME_LOW;
+ priv->pkt_rate_high = MLX4_EN_RX_RATE_HIGH;
+ priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
+ priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
+ priv->adaptive_rx_coal = mdev->profile.auto_moder;
+ priv->last_moder_time = MLX4_EN_AUTO_CONF;
+ priv->last_moder_jiffies = 0;
+ priv->last_moder_packets = 0;
+ priv->last_moder_tx_packets = 0;
+ priv->last_moder_bytes = 0;
+}
+
+static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
+{
+ unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_cq *cq;
+ unsigned long packets;
+ unsigned long rate;
+ unsigned long avg_pkt_size;
+ unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long tx_packets;
+ unsigned long tx_pkt_diff;
+ unsigned long rx_pkt_diff;
+ int moder_time;
+ int i, err;
+
+ if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
+ return;
+
+ spin_lock_bh(&priv->stats_lock);
+ rx_packets = priv->stats.rx_packets;
+ rx_bytes = priv->stats.rx_bytes;
+ tx_packets = priv->stats.tx_packets;
+ spin_unlock_bh(&priv->stats_lock);
+
+ if (!priv->last_moder_jiffies || !period)
+ goto out;
+
+ tx_pkt_diff = ((unsigned long) (tx_packets -
+ priv->last_moder_tx_packets));
+ rx_pkt_diff = ((unsigned long) (rx_packets -
+ priv->last_moder_packets));
+ packets = max(tx_pkt_diff, rx_pkt_diff);
+ rate = packets * HZ / period;
+ avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
+ priv->last_moder_bytes)) / packets : 0;
+
+ /* Apply auto-moderation only when packet rate exceeds a rate that
+ * it matters */
+ if (rate > MLX4_EN_RX_RATE_THRESH) {
+ /* If tx and rx packet rates are not balanced, assume that
+ * traffic is mainly BW bound and apply maximum moderation.
+ * Otherwise, moderate according to packet rate */
+ if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
+ 2 * rx_pkt_diff > 3 * tx_pkt_diff) {
+ moder_time = priv->rx_usecs_high;
+ } else {
+ if (rate < priv->pkt_rate_low)
+ moder_time = priv->rx_usecs_low;
+ else if (rate > priv->pkt_rate_high)
+ moder_time = priv->rx_usecs_high;
+ else
+ moder_time = (rate - priv->pkt_rate_low) *
+ (priv->rx_usecs_high - priv->rx_usecs_low) /
+ (priv->pkt_rate_high - priv->pkt_rate_low) +
+ priv->rx_usecs_low;
+ }
+ } else {
+ /* When packet rate is low, use default moderation rather than
+ * 0 to prevent interrupt storms if traffic suddenly increases */
+ moder_time = priv->rx_usecs;
+ }
+
+ mlx4_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
+ tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period);
+
+ mlx4_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu "
+ "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n",
+ priv->last_moder_time, moder_time, period, packets,
+ avg_pkt_size, rate);
+
+ if (moder_time != priv->last_moder_time) {
+ priv->last_moder_time = moder_time;
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ cq = &priv->rx_cq[i];
+ cq->moder_time = moder_time;
+ err = mlx4_en_set_cq_moder(priv, cq);
+ if (err) {
+ mlx4_err(mdev, "Failed modifying moderation for cq:%d "
+ "on port:%d\n", i, priv->port);
+ break;
+ }
+ }
+ }
+
+out:
+ priv->last_moder_packets = rx_packets;
+ priv->last_moder_tx_packets = tx_packets;
+ priv->last_moder_bytes = rx_bytes;
+ priv->last_moder_jiffies = jiffies;
+}
+
+static void mlx4_en_do_get_stats(struct work_struct *work)
+{
+ struct delayed_work *delay = container_of(work, struct delayed_work, work);
+ struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
+ stats_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
+ if (err)
+ mlx4_dbg(HW, priv, "Could not update stats for "
+ "port:%d\n", priv->port);
+
+ mutex_lock(&mdev->state_lock);
+ if (mdev->device_up) {
+ if (priv->port_up)
+ mlx4_en_auto_moderation(priv);
+
+ queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
+ }
+ mutex_unlock(&mdev->state_lock);
+}
+
+static void mlx4_en_linkstate(struct work_struct *work)
+{
+ struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
+ linkstate_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int linkstate = priv->link_state;
+
+ mutex_lock(&mdev->state_lock);
+ /* If observable port state changed set carrier state and
+ * report to system log */
+ if (priv->last_link_state != linkstate) {
+ if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
+ if (netif_msg_link(priv))
+ mlx4_info(mdev, "Port %d - link down\n", priv->port);
+ netif_carrier_off(priv->dev);
+ } else {
+ if (netif_msg_link(priv))
+ mlx4_info(mdev, "Port %d - link up\n", priv->port);
+ netif_carrier_on(priv->dev);
+ }
+ }
+ priv->last_link_state = linkstate;
+ mutex_unlock(&mdev->state_lock);
+}
+
+
+static int mlx4_en_start_port(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_cq *cq;
+ struct mlx4_en_tx_ring *tx_ring;
+ struct mlx4_en_rx_ring *rx_ring;
+ int rx_index = 0;
+ int tx_index = 0;
+ u16 stride;
+ int err = 0;
+ int i;
+ int j;
+
+ if (priv->port_up) {
+ mlx4_dbg(DRV, priv, "start port called while port already up\n");
+ return 0;
+ }
+
+ /* Calculate Rx buf size */
+ dev->mtu = min(dev->mtu, priv->max_mtu);
+ mlx4_en_calc_rx_buf(dev);
+ mlx4_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size);
+ stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
+ DS_SIZE * priv->num_frags);
+ /* Configure rx cq's and rings */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ cq = &priv->rx_cq[i];
+ rx_ring = &priv->rx_ring[i];
+
+ err = mlx4_en_activate_cq(priv, cq);
+ if (err) {
+ mlx4_err(mdev, "Failed activating Rx CQ\n");
+ goto rx_err;
+ }
+ for (j = 0; j < cq->size; j++)
+ cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK;
+ err = mlx4_en_set_cq_moder(priv, cq);
+ if (err) {
+ mlx4_err(mdev, "Failed setting cq moderation parameters");
+ mlx4_en_deactivate_cq(priv, cq);
+ goto cq_err;
+ }
+ mlx4_en_arm_cq(priv, cq);
+
+ ++rx_index;
+ }
+
+ err = mlx4_en_activate_rx_rings(priv);
+ if (err) {
+ mlx4_err(mdev, "Failed to activate RX rings\n");
+ goto cq_err;
+ }
+
+ err = mlx4_en_config_rss_steer(priv);
+ if (err) {
+ mlx4_err(mdev, "Failed configuring rss steering\n");
+ goto rx_err;
+ }
+
+ /* Configure tx cq's and rings */
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ /* Configure cq */
+ cq = &priv->tx_cq[i];
+ err = mlx4_en_activate_cq(priv, cq);
+ if (err) {
+ mlx4_err(mdev, "Failed allocating Tx CQ\n");
+ goto tx_err;
+ }
+ err = mlx4_en_set_cq_moder(priv, cq);
+ if (err) {
+ mlx4_err(mdev, "Failed setting cq moderation parameters");
+ mlx4_en_deactivate_cq(priv, cq);
+ goto tx_err;
+ }
+ mlx4_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
+ cq->buf->wqe_index = cpu_to_be16(0xffff);
+
+ /* Configure ring */
+ tx_ring = &priv->tx_ring[i];
+ err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
+ priv->rx_ring[0].srq.srqn);
+ if (err) {
+ mlx4_err(mdev, "Failed allocating Tx ring\n");
+ mlx4_en_deactivate_cq(priv, cq);
+ goto tx_err;
+ }
+ /* Set initial ownership of all Tx TXBBs to SW (1) */
+ for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
+ *((u32 *) (tx_ring->buf + j)) = 0xffffffff;
+ ++tx_index;
+ }
+
+ /* Configure port */
+ err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+ priv->rx_skb_size + ETH_FCS_LEN,
+ mdev->profile.tx_pause,
+ mdev->profile.tx_ppp,
+ mdev->profile.rx_pause,
+ mdev->profile.rx_ppp);
+ if (err) {
+ mlx4_err(mdev, "Failed setting port general configurations"
+ " for port %d, with error %d\n", priv->port, err);
+ goto tx_err;
+ }
+ /* Set default qp number */
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0);
+ if (err) {
+ mlx4_err(mdev, "Failed setting default qp numbers\n");
+ goto tx_err;
+ }
+ /* Set port mac number */
+ mlx4_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
+ err = mlx4_register_mac(mdev->dev, priv->port,
+ priv->mac, &priv->mac_index);
+ if (err) {
+ mlx4_err(mdev, "Failed setting port mac\n");
+ goto tx_err;
+ }
+
+ /* Init port */
+ mlx4_dbg(HW, priv, "Initializing port\n");
+ err = mlx4_INIT_PORT(mdev->dev, priv->port);
+ if (err) {
+ mlx4_err(mdev, "Failed Initializing port\n");
+ goto mac_err;
+ }
+
+ /* Schedule multicast task to populate multicast list */
+ queue_work(mdev->workqueue, &priv->mcast_task);
+
+ priv->port_up = true;
+ netif_start_queue(dev);
+ return 0;
+
+mac_err:
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+tx_err:
+ while (tx_index--) {
+ mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
+ mlx4_en_deactivate_cq(priv, &priv->tx_cq[tx_index]);
+ }
+
+ mlx4_en_release_rss_steer(priv);
+rx_err:
+ for (i = 0; i < priv->rx_ring_num; i++)
+ mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[rx_index]);
+cq_err:
+ while (rx_index--)
+ mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
+
+ return err; /* need to close devices */
+}
+
+
+static void mlx4_en_stop_port(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int i;
+
+ if (!priv->port_up) {
+ mlx4_dbg(DRV, priv, "stop port (%d) called while port already down\n",
+ priv->port);
+ return;
+ }
+ netif_stop_queue(dev);
+
+ /* Synchronize with tx routine */
+ netif_tx_lock_bh(dev);
+ priv->port_up = false;
+ netif_tx_unlock_bh(dev);
+
+ /* close port*/
+ mlx4_CLOSE_PORT(mdev->dev, priv->port);
+
+ /* Unregister Mac address for the port */
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+
+ /* Free TX Rings */
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]);
+ mlx4_en_deactivate_cq(priv, &priv->tx_cq[i]);
+ }
+ msleep(10);
+
+ for (i = 0; i < priv->tx_ring_num; i++)
+ mlx4_en_free_tx_buf(dev, &priv->tx_ring[i]);
+
+ /* Free RSS qps */
+ mlx4_en_release_rss_steer(priv);
+
+ /* Free RX Rings */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
+ while (test_bit(NAPI_STATE_SCHED, &priv->rx_cq[i].napi.state))
+ msleep(1);
+ mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]);
+ }
+}
+
+static void mlx4_en_restart(struct work_struct *work)
+{
+ struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
+ watchdog_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct net_device *dev = priv->dev;
+
+ mlx4_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
+ mlx4_en_stop_port(dev);
+ if (mlx4_en_start_port(dev))
+ mlx4_err(mdev, "Failed restarting port %d\n", priv->port);
+}
+
+
+static int mlx4_en_open(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int i;
+ int err = 0;
+
+ mutex_lock(&mdev->state_lock);
+
+ if (!mdev->device_up) {
+ mlx4_err(mdev, "Cannot open - device down/disabled\n");
+ err = -EBUSY;
+ goto out;
+ }
+
+ /* Reset HW statistics and performance counters */
+ if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
+ mlx4_dbg(HW, priv, "Failed dumping statistics\n");
+
+ memset(&priv->stats, 0, sizeof(priv->stats));
+ memset(&priv->pstats, 0, sizeof(priv->pstats));
+
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->tx_ring[i].bytes = 0;
+ priv->tx_ring[i].packets = 0;
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_ring[i].bytes = 0;
+ priv->rx_ring[i].packets = 0;
+ }
+
+ mlx4_en_set_default_moderation(priv);
+ err = mlx4_en_start_port(dev);
+ if (err)
+ mlx4_err(mdev, "Failed starting port:%d\n", priv->port);
+
+out:
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
+
+
+static int mlx4_en_close(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ if (netif_msg_ifdown(priv))
+ mlx4_info(mdev, "Close called for port:%d\n", priv->port);
+
+ mutex_lock(&mdev->state_lock);
+
+ mlx4_en_stop_port(dev);
+ netif_carrier_off(dev);
+
+ mutex_unlock(&mdev->state_lock);
+ return 0;
+}
+
+static void mlx4_en_free_resources(struct mlx4_en_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ if (priv->tx_ring[i].tx_info)
+ mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
+ if (priv->tx_cq[i].buf)
+ mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+ }
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (priv->rx_ring[i].rx_info)
+ mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
+ if (priv->rx_cq[i].buf)
+ mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
+ }
+}
+
+static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_port_profile *prof = priv->prof;
+ int i;
+
+ /* Create tx Rings */
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
+ prof->tx_ring_size, i, TX))
+ goto err;
+
+ if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
+ prof->tx_ring_size, TXBB_SIZE))
+ goto err;
+ }
+
+ /* Create rx Rings */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (mlx4_en_create_cq(priv, &priv->rx_cq[i],
+ prof->rx_ring_size, i, RX))
+ goto err;
+
+ if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i],
+ prof->rx_ring_size, priv->stride))
+ goto err;
+ }
+
+ return 0;
+
+err:
+ mlx4_err(mdev, "Failed to allocate NIC resources\n");
+ return -ENOMEM;
+}
+
+
+void mlx4_en_destroy_netdev(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ mlx4_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
+
+ /* Unregister device - this will close the port if it was up */
+ if (priv->registered)
+ unregister_netdev(dev);
+
+ if (priv->allocated)
+ mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
+
+ cancel_delayed_work(&priv->stats_task);
+ cancel_delayed_work(&priv->refill_task);
+ /* flush any pending task for this netdev */
+ flush_workqueue(mdev->workqueue);
+
+ /* Detach the netdev so tasks would not attempt to access it */
+ mutex_lock(&mdev->state_lock);
+ mdev->pndev[priv->port] = NULL;
+ mutex_unlock(&mdev->state_lock);
+
+ mlx4_en_free_resources(priv);
+ free_netdev(dev);
+}
+
+static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err = 0;
+
+ mlx4_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n",
+ dev->mtu, new_mtu);
+
+ if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
+ mlx4_err(mdev, "Bad MTU size:%d.\n", new_mtu);
+ return -EPERM;
+ }
+ dev->mtu = new_mtu;
+
+ if (netif_running(dev)) {
+ mutex_lock(&mdev->state_lock);
+ if (!mdev->device_up) {
+ /* NIC is probably restarting - let watchdog task reset
+ * the port */
+ mlx4_dbg(DRV, priv, "Change MTU called with card down!?\n");
+ } else {
+ mlx4_en_stop_port(dev);
+ mlx4_en_set_default_moderation(priv);
+ err = mlx4_en_start_port(dev);
+ if (err) {
+ mlx4_err(mdev, "Failed restarting port:%d\n",
+ priv->port);
+ queue_work(mdev->workqueue, &priv->watchdog_task);
+ }
+ }
+ mutex_unlock(&mdev->state_lock);
+ }
+ return 0;
+}
+
+int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ struct mlx4_en_port_profile *prof)
+{
+ struct net_device *dev;
+ struct mlx4_en_priv *priv;
+ int i;
+ int err;
+
+ dev = alloc_etherdev(sizeof(struct mlx4_en_priv));
+ if (dev == NULL) {
+ mlx4_err(mdev, "Net device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev);
+
+ /*
+ * Initialize driver private data
+ */
+
+ priv = netdev_priv(dev);
+ memset(priv, 0, sizeof(struct mlx4_en_priv));
+ priv->dev = dev;
+ priv->mdev = mdev;
+ priv->prof = prof;
+ priv->port = port;
+ priv->port_up = false;
+ priv->rx_csum = 1;
+ priv->flags = prof->flags;
+ priv->tx_ring_num = prof->tx_ring_num;
+ priv->rx_ring_num = prof->rx_ring_num;
+ priv->mc_list = NULL;
+ priv->mac_index = -1;
+ priv->msg_enable = MLX4_EN_MSG_LEVEL;
+ spin_lock_init(&priv->stats_lock);
+ INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast);
+ INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac);
+ INIT_DELAYED_WORK(&priv->refill_task, mlx4_en_rx_refill);
+ INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
+ INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
+ INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
+
+ /* Query for default mac and max mtu */
+ priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
+ priv->mac = mdev->dev->caps.def_mac[priv->port];
+ if (ILLEGAL_MAC(priv->mac)) {
+ mlx4_err(mdev, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
+ priv->port, priv->mac);
+ err = -EINVAL;
+ goto out;
+ }
+
+ priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
+ DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
+ err = mlx4_en_alloc_resources(priv);
+ if (err)
+ goto out;
+
+ /* Populate Rx default RSS mappings */
+ mlx4_en_set_default_rss_map(priv, &priv->rss_map, priv->rx_ring_num *
+ RSS_FACTOR, priv->rx_ring_num);
+ /* Allocate page for receive rings */
+ err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
+ MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
+ if (err) {
+ mlx4_err(mdev, "Failed to allocate page for rx qps\n");
+ goto out;
+ }
+ priv->allocated = 1;
+
+ /* Populate Tx priority mappings */
+ mlx4_en_set_prio_map(priv, priv->tx_prio_map, prof->tx_ring_num);
+
+ /*
+ * Initialize netdev entry points
+ */
+
+ dev->open = &mlx4_en_open;
+ dev->stop = &mlx4_en_close;
+ dev->hard_start_xmit = &mlx4_en_xmit;
+ dev->get_stats = &mlx4_en_get_stats;
+ dev->set_multicast_list = &mlx4_en_set_multicast;
+ dev->set_mac_address = &mlx4_en_set_mac;
+ dev->change_mtu = &mlx4_en_change_mtu;
+ dev->tx_timeout = &mlx4_en_tx_timeout;
+ dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
+ dev->vlan_rx_register = mlx4_en_vlan_rx_register;
+ dev->vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid;
+ dev->vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = mlx4_en_netpoll;
+#endif
+ SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
+
+ /* Set defualt MAC */
+ dev->addr_len = ETH_ALEN;
+ for (i = 0; i < ETH_ALEN; i++)
+ dev->dev_addr[ETH_ALEN - 1 - i] =
+ (u8) (priv->mac >> (8 * i));
+
+ /*
+ * Set driver features
+ */
+ dev->features |= NETIF_F_SG;
+ dev->features |= NETIF_F_HW_CSUM;
+ dev->features |= NETIF_F_HIGHDMA;
+ dev->features |= NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_FILTER;
+ if (mdev->profile.num_lro)
+ dev->features |= NETIF_F_LRO;
+ if (mdev->LSO_support) {
+ dev->features |= NETIF_F_TSO;
+ dev->features |= NETIF_F_TSO6;
+ }
+
+ mdev->pndev[port] = dev;
+
+ netif_carrier_off(dev);
+ err = register_netdev(dev);
+ if (err) {
+ mlx4_err(mdev, "Netdev registration failed\n");
+ goto out;
+ }
+ priv->registered = 1;
+ queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
+ return 0;
+
+out:
+ mlx4_en_destroy_netdev(dev);
+ return err;
+}
+
diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c
new file mode 100644
index 00000000000..c2e69b1bcd0
--- /dev/null
+++ b/drivers/net/mlx4/en_params.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+
+#include "mlx4_en.h"
+#include "en_port.h"
+
+#define MLX4_EN_PARM_INT(X, def_val, desc) \
+ static unsigned int X = def_val;\
+ module_param(X , uint, 0444); \
+ MODULE_PARM_DESC(X, desc);
+
+
+/*
+ * Device scope module parameters
+ */
+
+
+/* Use a XOR rathern than Toeplitz hash function for RSS */
+MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
+
+/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
+MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
+
+/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
+MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
+ "Number of LRO sessions per ring or disabled (0)");
+
+/* Priority pausing */
+MLX4_EN_PARM_INT(pptx, MLX4_EN_DEF_TX_PAUSE,
+ "Pause policy on TX: 0 never generate pause frames "
+ "1 generate pause frames according to RX buffer threshold");
+MLX4_EN_PARM_INT(pprx, MLX4_EN_DEF_RX_PAUSE,
+ "Pause policy on RX: 0 ignore received pause frames "
+ "1 respect received pause frames");
+MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
+ " Per priority bit mask");
+MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
+ " Per priority bit mask");
+
+/* Interrupt moderation tunning */
+MLX4_EN_PARM_INT(rx_moder_cnt, MLX4_EN_AUTO_CONF,
+ "Max coalesced descriptors for Rx interrupt moderation");
+MLX4_EN_PARM_INT(rx_moder_time, MLX4_EN_AUTO_CONF,
+ "Timeout following last packet for Rx interrupt moderation");
+MLX4_EN_PARM_INT(auto_moder, 1, "Enable dynamic interrupt moderation");
+
+MLX4_EN_PARM_INT(rx_ring_num1, 0, "Number or Rx rings for port 1 (0 = #cores)");
+MLX4_EN_PARM_INT(rx_ring_num2, 0, "Number or Rx rings for port 2 (0 = #cores)");
+
+MLX4_EN_PARM_INT(tx_ring_size1, MLX4_EN_AUTO_CONF, "Tx ring size for port 1");
+MLX4_EN_PARM_INT(tx_ring_size2, MLX4_EN_AUTO_CONF, "Tx ring size for port 2");
+MLX4_EN_PARM_INT(rx_ring_size1, MLX4_EN_AUTO_CONF, "Rx ring size for port 1");
+MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2");
+
+
+int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
+{
+ struct mlx4_en_profile *params = &mdev->profile;
+
+ params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF);
+ params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF);
+ params->auto_moder = auto_moder;
+ params->rss_xor = (rss_xor != 0);
+ params->rss_mask = rss_mask & 0x1f;
+ params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
+ params->rx_pause = pprx;
+ params->rx_ppp = pfcrx;
+ params->tx_pause = pptx;
+ params->tx_ppp = pfctx;
+ if (params->rx_ppp || params->tx_ppp) {
+ params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM;
+ params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM;
+ } else {
+ params->prof[1].tx_ring_num = 1;
+ params->prof[2].tx_ring_num = 1;
+ }
+ params->prof[1].rx_ring_num = min_t(int, rx_ring_num1, MAX_RX_RINGS);
+ params->prof[2].rx_ring_num = min_t(int, rx_ring_num2, MAX_RX_RINGS);
+
+ if (tx_ring_size1 == MLX4_EN_AUTO_CONF)
+ tx_ring_size1 = MLX4_EN_DEF_TX_RING_SIZE;
+ params->prof[1].tx_ring_size =
+ (tx_ring_size1 < MLX4_EN_MIN_TX_SIZE) ?
+ MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size1);
+
+ if (tx_ring_size2 == MLX4_EN_AUTO_CONF)
+ tx_ring_size2 = MLX4_EN_DEF_TX_RING_SIZE;
+ params->prof[2].tx_ring_size =
+ (tx_ring_size2 < MLX4_EN_MIN_TX_SIZE) ?
+ MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size2);
+
+ if (rx_ring_size1 == MLX4_EN_AUTO_CONF)
+ rx_ring_size1 = MLX4_EN_DEF_RX_RING_SIZE;
+ params->prof[1].rx_ring_size =
+ (rx_ring_size1 < MLX4_EN_MIN_RX_SIZE) ?
+ MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size1);
+
+ if (rx_ring_size2 == MLX4_EN_AUTO_CONF)
+ rx_ring_size2 = MLX4_EN_DEF_RX_RING_SIZE;
+ params->prof[2].rx_ring_size =
+ (rx_ring_size2 < MLX4_EN_MIN_RX_SIZE) ?
+ MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size2);
+ return 0;
+}
+
+
+/*
+ * Ethtool support
+ */
+
+static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
+{
+ int i;
+
+ priv->port_stats.lro_aggregated = 0;
+ priv->port_stats.lro_flushed = 0;
+ priv->port_stats.lro_no_desc = 0;
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
+ priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
+ priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
+ }
+}
+
+static void
+mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
+ strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
+ sprintf(drvinfo->fw_version, "%d.%d.%d",
+ (u16) (mdev->dev->caps.fw_ver >> 32),
+ (u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
+ (u16) (mdev->dev->caps.fw_ver & 0xffff));
+ strncpy(drvinfo->bus_info, pci_name(mdev->dev->pdev), 32);
+ drvinfo->n_stats = 0;
+ drvinfo->regdump_len = 0;
+ drvinfo->eedump_len = 0;
+}
+
+static u32 mlx4_en_get_tso(struct net_device *dev)
+{
+ return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int mlx4_en_set_tso(struct net_device *dev, u32 data)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ if (data) {
+ if (!priv->mdev->LSO_support)
+ return -EPERM;
+ dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
+ } else
+ dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+ return 0;
+}
+
+static u32 mlx4_en_get_rx_csum(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ return priv->rx_csum;
+}
+
+static int mlx4_en_set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ priv->rx_csum = (data != 0);
+ return 0;
+}
+
+static const char main_strings[][ETH_GSTRING_LEN] = {
+ "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+ "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+ "rx_length_errors", "rx_over_errors", "rx_crc_errors",
+ "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+ "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+ "tx_heartbeat_errors", "tx_window_errors",
+
+ /* port statistics */
+ "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
+ "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
+ "rx_csum_good", "rx_csum_none", "tx_chksum_offload",
+
+ /* packet statistics */
+ "broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3",
+ "rx_prio_4", "rx_prio_5", "rx_prio_6", "rx_prio_7", "tx_prio_0",
+ "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
+ "tx_prio_6", "tx_prio_7",
+};
+#define NUM_MAIN_STATS 21
+#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
+
+static u32 mlx4_en_get_msglevel(struct net_device *dev)
+{
+ return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
+}
+
+static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
+{
+ ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val;
+}
+
+static void mlx4_en_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ wol->supported = 0;
+ wol->wolopts = 0;
+
+ return;
+}
+
+static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ if (sset != ETH_SS_STATS)
+ return -EOPNOTSUPP;
+
+ return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2;
+}
+
+static void mlx4_en_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, uint64_t *data)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int index = 0;
+ int i;
+
+ spin_lock_bh(&priv->stats_lock);
+
+ mlx4_en_update_lro_stats(priv);
+
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ data[index++] = ((unsigned long *) &priv->stats)[i];
+ for (i = 0; i < NUM_PORT_STATS; i++)
+ data[index++] = ((unsigned long *) &priv->port_stats)[i];
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ data[index++] = priv->tx_ring[i].packets;
+ data[index++] = priv->tx_ring[i].bytes;
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ data[index++] = priv->rx_ring[i].packets;
+ data[index++] = priv->rx_ring[i].bytes;
+ }
+ for (i = 0; i < NUM_PKT_STATS; i++)
+ data[index++] = ((unsigned long *) &priv->pkstats)[i];
+ spin_unlock_bh(&priv->stats_lock);
+
+}
+
+static void mlx4_en_get_strings(struct net_device *dev,
+ uint32_t stringset, uint8_t *data)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int index = 0;
+ int i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ /* Add main counters */
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
+ for (i = 0; i < NUM_PORT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i + NUM_MAIN_STATS]);
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "tx%d_packets", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "tx%d_bytes", i);
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_packets", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_bytes", i);
+ }
+ for (i = 0; i < NUM_PKT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
+}
+
+static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->supported = SUPPORTED_10000baseT_Full;
+ cmd->advertising = SUPPORTED_10000baseT_Full;
+ if (netif_carrier_ok(dev)) {
+ cmd->speed = SPEED_10000;
+ cmd->duplex = DUPLEX_FULL;
+ } else {
+ cmd->speed = -1;
+ cmd->duplex = -1;
+ }
+ return 0;
+}
+
+static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ if ((cmd->autoneg == AUTONEG_ENABLE) ||
+ (cmd->speed != SPEED_10000) || (cmd->duplex != DUPLEX_FULL))
+ return -EINVAL;
+
+ /* Nothing to change */
+ return 0;
+}
+
+static int mlx4_en_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coal)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ coal->tx_coalesce_usecs = 0;
+ coal->tx_max_coalesced_frames = 0;
+ coal->rx_coalesce_usecs = priv->rx_usecs;
+ coal->rx_max_coalesced_frames = priv->rx_frames;
+
+ coal->pkt_rate_low = priv->pkt_rate_low;
+ coal->rx_coalesce_usecs_low = priv->rx_usecs_low;
+ coal->pkt_rate_high = priv->pkt_rate_high;
+ coal->rx_coalesce_usecs_high = priv->rx_usecs_high;
+ coal->rate_sample_interval = priv->sample_interval;
+ coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal;
+ return 0;
+}
+
+static int mlx4_en_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coal)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int err, i;
+
+ priv->rx_frames = (coal->rx_max_coalesced_frames ==
+ MLX4_EN_AUTO_CONF) ?
+ MLX4_EN_RX_COAL_TARGET /
+ priv->dev->mtu + 1 :
+ coal->rx_max_coalesced_frames;
+ priv->rx_usecs = (coal->rx_coalesce_usecs ==
+ MLX4_EN_AUTO_CONF) ?
+ MLX4_EN_RX_COAL_TIME :
+ coal->rx_coalesce_usecs;
+
+ /* Set adaptive coalescing params */
+ priv->pkt_rate_low = coal->pkt_rate_low;
+ priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
+ priv->pkt_rate_high = coal->pkt_rate_high;
+ priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
+ priv->sample_interval = coal->rate_sample_interval;
+ priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
+ priv->last_moder_time = MLX4_EN_AUTO_CONF;
+ if (priv->adaptive_rx_coal)
+ return 0;
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_cq[i].moder_cnt = priv->rx_frames;
+ priv->rx_cq[i].moder_time = priv->rx_usecs;
+ err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static int mlx4_en_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ mdev->profile.tx_pause = pause->tx_pause != 0;
+ mdev->profile.rx_pause = pause->rx_pause != 0;
+ err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+ priv->rx_skb_size + ETH_FCS_LEN,
+ mdev->profile.tx_pause,
+ mdev->profile.tx_ppp,
+ mdev->profile.rx_pause,
+ mdev->profile.rx_ppp);
+ if (err)
+ mlx4_err(mdev, "Failed setting pause params to\n");
+
+ return err;
+}
+
+static void mlx4_en_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ pause->tx_pause = mdev->profile.tx_pause;
+ pause->rx_pause = mdev->profile.rx_pause;
+}
+
+static void mlx4_en_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *param)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ memset(param, 0, sizeof(*param));
+ param->rx_max_pending = mdev->dev->caps.max_rq_sg;
+ param->tx_max_pending = mdev->dev->caps.max_sq_sg;
+ param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
+ param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
+}
+
+const struct ethtool_ops mlx4_en_ethtool_ops = {
+ .get_drvinfo = mlx4_en_get_drvinfo,
+ .get_settings = mlx4_en_get_settings,
+ .set_settings = mlx4_en_set_settings,
+#ifdef NETIF_F_TSO
+ .get_tso = mlx4_en_get_tso,
+ .set_tso = mlx4_en_set_tso,
+#endif
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_link = ethtool_op_get_link,
+ .get_rx_csum = mlx4_en_get_rx_csum,
+ .set_rx_csum = mlx4_en_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_ipv6_csum,
+ .get_strings = mlx4_en_get_strings,
+ .get_sset_count = mlx4_en_get_sset_count,
+ .get_ethtool_stats = mlx4_en_get_ethtool_stats,
+ .get_wol = mlx4_en_get_wol,
+ .get_msglevel = mlx4_en_get_msglevel,
+ .set_msglevel = mlx4_en_set_msglevel,
+ .get_coalesce = mlx4_en_get_coalesce,
+ .set_coalesce = mlx4_en_set_coalesce,
+ .get_pauseparam = mlx4_en_get_pauseparam,
+ .set_pauseparam = mlx4_en_set_pauseparam,
+ .get_ringparam = mlx4_en_get_ringparam,
+ .get_flags = ethtool_op_get_flags,
+ .set_flags = ethtool_op_set_flags,
+};
+
+
+
+
+
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
new file mode 100644
index 00000000000..c5a4c038975
--- /dev/null
+++ b/drivers/net/mlx4/en_port.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+
+#include <linux/if_vlan.h>
+
+#include <linux/mlx4/device.h>
+#include <linux/mlx4/cmd.h>
+
+#include "en_port.h"
+#include "mlx4_en.h"
+
+
+int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
+ u64 mac, u64 clear, u8 mode)
+{
+ return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
+ MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B);
+}
+
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_set_vlan_fltr_mbox *filter;
+ int i;
+ int j;
+ int index = 0;
+ u32 entry;
+ int err = 0;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ filter = mailbox->buf;
+ if (grp) {
+ memset(filter, 0, sizeof *filter);
+ for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
+ entry = 0;
+ for (j = 0; j < 32; j++)
+ if (vlan_group_get_device(grp, index++))
+ entry |= 1 << j;
+ filter->entry[i] = cpu_to_be32(entry);
+ }
+ } else {
+ /* When no vlans are configured we block all vlans */
+ memset(filter, 0, sizeof(*filter));
+ }
+ err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
+
+int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
+ u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_set_port_general_context *context;
+ int err;
+ u32 in_mod;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ context = mailbox->buf;
+ memset(context, 0, sizeof *context);
+
+ context->flags = SET_PORT_GEN_ALL_VALID;
+ context->mtu = cpu_to_be16(mtu);
+ context->pptx = (pptx * (!pfctx)) << 7;
+ context->pfctx = pfctx;
+ context->pprx = (pprx * (!pfcrx)) << 7;
+ context->pfcrx = pfcrx;
+
+ in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
+int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
+ u8 promisc)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_set_port_rqp_calc_context *context;
+ int err;
+ u32 in_mod;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ context = mailbox->buf;
+ memset(context, 0, sizeof *context);
+
+ context->base_qpn = cpu_to_be32(base_qpn);
+ context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | base_qpn);
+ context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_SHIFT | base_qpn);
+ context->intra_no_vlan = 0;
+ context->no_vlan = MLX4_NO_VLAN_IDX;
+ context->intra_vlan_miss = 0;
+ context->vlan_miss = MLX4_VLAN_MISS_IDX;
+
+ in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
+
+int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
+{
+ struct mlx4_en_stat_out_mbox *mlx4_en_stats;
+ struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+ struct net_device_stats *stats = &priv->stats;
+ struct mlx4_cmd_mailbox *mailbox;
+ u64 in_mod = reset << 8 | port;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ memset(mailbox->buf, 0, sizeof(*mlx4_en_stats));
+ err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0,
+ MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ goto out;
+
+ mlx4_en_stats = mailbox->buf;
+
+ spin_lock_bh(&priv->stats_lock);
+
+ stats->rx_packets = be32_to_cpu(mlx4_en_stats->RTOTFRMS) -
+ be32_to_cpu(mlx4_en_stats->RDROP);
+ stats->tx_packets = be64_to_cpu(mlx4_en_stats->TTOT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TTOT_novlan) +
+ be64_to_cpu(mlx4_en_stats->TTOT_loopbk);
+ stats->rx_bytes = be64_to_cpu(mlx4_en_stats->ROCT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->ROCT_novlan);
+
+ stats->tx_bytes = be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_novlan) +
+ be64_to_cpu(mlx4_en_stats->TTTLOCT_loopbk);
+
+ stats->rx_errors = be64_to_cpu(mlx4_en_stats->PCS) +
+ be32_to_cpu(mlx4_en_stats->RdropLength) +
+ be32_to_cpu(mlx4_en_stats->RJBBR) +
+ be32_to_cpu(mlx4_en_stats->RCRC) +
+ be32_to_cpu(mlx4_en_stats->RRUNT);
+ stats->tx_errors = be32_to_cpu(mlx4_en_stats->TDROP);
+ stats->multicast = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_1) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_2) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_3) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_4) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_5) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_6) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_7) +
+ be64_to_cpu(mlx4_en_stats->MCAST_novlan);
+ stats->collisions = 0;
+ stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
+ stats->rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+ stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
+ stats->rx_frame_errors = 0;
+ stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+ stats->rx_missed_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+ stats->tx_aborted_errors = 0;
+ stats->tx_carrier_errors = 0;
+ stats->tx_fifo_errors = 0;
+ stats->tx_heartbeat_errors = 0;
+ stats->tx_window_errors = 0;
+
+ priv->pkstats.broadcast =
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_novlan);
+ priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0);
+ priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1);
+ priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2);
+ priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3);
+ priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4);
+ priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5);
+ priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6);
+ priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7);
+ priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0);
+ priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1);
+ priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2);
+ priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3);
+ priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4);
+ priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5);
+ priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6);
+ priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7);
+ spin_unlock_bh(&priv->stats_lock);
+
+out:
+ mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+ return err;
+}
+
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
new file mode 100644
index 00000000000..e6477f12beb
--- /dev/null
+++ b/drivers/net/mlx4/en_port.h
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _MLX4_EN_PORT_H_
+#define _MLX4_EN_PORT_H_
+
+
+#define SET_PORT_GEN_ALL_VALID 0x7
+#define SET_PORT_PROMISC_SHIFT 31
+
+enum {
+ MLX4_CMD_SET_VLAN_FLTR = 0x47,
+ MLX4_CMD_SET_MCAST_FLTR = 0x48,
+ MLX4_CMD_DUMP_ETH_STATS = 0x49,
+};
+
+struct mlx4_set_port_general_context {
+ u8 reserved[3];
+ u8 flags;
+ u16 reserved2;
+ __be16 mtu;
+ u8 pptx;
+ u8 pfctx;
+ u16 reserved3;
+ u8 pprx;
+ u8 pfcrx;
+ u16 reserved4;
+};
+
+struct mlx4_set_port_rqp_calc_context {
+ __be32 base_qpn;
+ __be32 flags;
+ u8 reserved[3];
+ u8 mac_miss;
+ u8 intra_no_vlan;
+ u8 no_vlan;
+ u8 intra_vlan_miss;
+ u8 vlan_miss;
+ u8 reserved2[3];
+ u8 no_vlan_prio;
+ __be32 promisc;
+ __be32 mcast;
+};
+
+#define VLAN_FLTR_SIZE 128
+struct mlx4_set_vlan_fltr_mbox {
+ __be32 entry[VLAN_FLTR_SIZE];
+};
+
+
+enum {
+ MLX4_MCAST_CONFIG = 0,
+ MLX4_MCAST_DISABLE = 1,
+ MLX4_MCAST_ENABLE = 2,
+};
+
+
+struct mlx4_en_stat_out_mbox {
+ /* Received frames with a length of 64 octets */
+ __be64 R64_prio_0;
+ __be64 R64_prio_1;
+ __be64 R64_prio_2;
+ __be64 R64_prio_3;
+ __be64 R64_prio_4;
+ __be64 R64_prio_5;
+ __be64 R64_prio_6;
+ __be64 R64_prio_7;
+ __be64 R64_novlan;
+ /* Received frames with a length of 127 octets */
+ __be64 R127_prio_0;
+ __be64 R127_prio_1;
+ __be64 R127_prio_2;
+ __be64 R127_prio_3;
+ __be64 R127_prio_4;
+ __be64 R127_prio_5;
+ __be64 R127_prio_6;
+ __be64 R127_prio_7;
+ __be64 R127_novlan;
+ /* Received frames with a length of 255 octets */
+ __be64 R255_prio_0;
+ __be64 R255_prio_1;
+ __be64 R255_prio_2;
+ __be64 R255_prio_3;
+ __be64 R255_prio_4;
+ __be64 R255_prio_5;
+ __be64 R255_prio_6;
+ __be64 R255_prio_7;
+ __be64 R255_novlan;
+ /* Received frames with a length of 511 octets */
+ __be64 R511_prio_0;
+ __be64 R511_prio_1;
+ __be64 R511_prio_2;
+ __be64 R511_prio_3;
+ __be64 R511_prio_4;
+ __be64 R511_prio_5;
+ __be64 R511_prio_6;
+ __be64 R511_prio_7;
+ __be64 R511_novlan;
+ /* Received frames with a length of 1023 octets */
+ __be64 R1023_prio_0;
+ __be64 R1023_prio_1;
+ __be64 R1023_prio_2;
+ __be64 R1023_prio_3;
+ __be64 R1023_prio_4;
+ __be64 R1023_prio_5;
+ __be64 R1023_prio_6;
+ __be64 R1023_prio_7;
+ __be64 R1023_novlan;
+ /* Received frames with a length of 1518 octets */
+ __be64 R1518_prio_0;
+ __be64 R1518_prio_1;
+ __be64 R1518_prio_2;
+ __be64 R1518_prio_3;
+ __be64 R1518_prio_4;
+ __be64 R1518_prio_5;
+ __be64 R1518_prio_6;
+ __be64 R1518_prio_7;
+ __be64 R1518_novlan;
+ /* Received frames with a length of 1522 octets */
+ __be64 R1522_prio_0;
+ __be64 R1522_prio_1;
+ __be64 R1522_prio_2;
+ __be64 R1522_prio_3;
+ __be64 R1522_prio_4;
+ __be64 R1522_prio_5;
+ __be64 R1522_prio_6;
+ __be64 R1522_prio_7;
+ __be64 R1522_novlan;
+ /* Received frames with a length of 1548 octets */
+ __be64 R1548_prio_0;
+ __be64 R1548_prio_1;
+ __be64 R1548_prio_2;
+ __be64 R1548_prio_3;
+ __be64 R1548_prio_4;
+ __be64 R1548_prio_5;
+ __be64 R1548_prio_6;
+ __be64 R1548_prio_7;
+ __be64 R1548_novlan;
+ /* Received frames with a length of 1548 < octets < MTU */
+ __be64 R2MTU_prio_0;
+ __be64 R2MTU_prio_1;
+ __be64 R2MTU_prio_2;
+ __be64 R2MTU_prio_3;
+ __be64 R2MTU_prio_4;
+ __be64 R2MTU_prio_5;
+ __be64 R2MTU_prio_6;
+ __be64 R2MTU_prio_7;
+ __be64 R2MTU_novlan;
+ /* Received frames with a length of MTU< octets and good CRC */
+ __be64 RGIANT_prio_0;
+ __be64 RGIANT_prio_1;
+ __be64 RGIANT_prio_2;
+ __be64 RGIANT_prio_3;
+ __be64 RGIANT_prio_4;
+ __be64 RGIANT_prio_5;
+ __be64 RGIANT_prio_6;
+ __be64 RGIANT_prio_7;
+ __be64 RGIANT_novlan;
+ /* Received broadcast frames with good CRC */
+ __be64 RBCAST_prio_0;
+ __be64 RBCAST_prio_1;
+ __be64 RBCAST_prio_2;
+ __be64 RBCAST_prio_3;
+ __be64 RBCAST_prio_4;
+ __be64 RBCAST_prio_5;
+ __be64 RBCAST_prio_6;
+ __be64 RBCAST_prio_7;
+ __be64 RBCAST_novlan;
+ /* Received multicast frames with good CRC */
+ __be64 MCAST_prio_0;
+ __be64 MCAST_prio_1;
+ __be64 MCAST_prio_2;
+ __be64 MCAST_prio_3;
+ __be64 MCAST_prio_4;
+ __be64 MCAST_prio_5;
+ __be64 MCAST_prio_6;
+ __be64 MCAST_prio_7;
+ __be64 MCAST_novlan;
+ /* Received unicast not short or GIANT frames with good CRC */
+ __be64 RTOTG_prio_0;
+ __be64 RTOTG_prio_1;
+ __be64 RTOTG_prio_2;
+ __be64 RTOTG_prio_3;
+ __be64 RTOTG_prio_4;
+ __be64 RTOTG_prio_5;
+ __be64 RTOTG_prio_6;
+ __be64 RTOTG_prio_7;
+ __be64 RTOTG_novlan;
+
+ /* Count of total octets of received frames, includes framing characters */
+ __be64 RTTLOCT_prio_0;
+ /* Count of total octets of received frames, not including framing
+ characters */
+ __be64 RTTLOCT_NOFRM_prio_0;
+ /* Count of Total number of octets received
+ (only for frames without errors) */
+ __be64 ROCT_prio_0;
+
+ __be64 RTTLOCT_prio_1;
+ __be64 RTTLOCT_NOFRM_prio_1;
+ __be64 ROCT_prio_1;
+
+ __be64 RTTLOCT_prio_2;
+ __be64 RTTLOCT_NOFRM_prio_2;
+ __be64 ROCT_prio_2;
+
+ __be64 RTTLOCT_prio_3;
+ __be64 RTTLOCT_NOFRM_prio_3;
+ __be64 ROCT_prio_3;
+
+ __be64 RTTLOCT_prio_4;
+ __be64 RTTLOCT_NOFRM_prio_4;
+ __be64 ROCT_prio_4;
+
+ __be64 RTTLOCT_prio_5;
+ __be64 RTTLOCT_NOFRM_prio_5;
+ __be64 ROCT_prio_5;
+
+ __be64 RTTLOCT_prio_6;
+ __be64 RTTLOCT_NOFRM_prio_6;
+ __be64 ROCT_prio_6;
+
+ __be64 RTTLOCT_prio_7;
+ __be64 RTTLOCT_NOFRM_prio_7;
+ __be64 ROCT_prio_7;
+
+ __be64 RTTLOCT_novlan;
+ __be64 RTTLOCT_NOFRM_novlan;
+ __be64 ROCT_novlan;
+
+ /* Count of Total received frames including bad frames */
+ __be64 RTOT_prio_0;
+ /* Count of Total number of received frames with 802.1Q encapsulation */
+ __be64 R1Q_prio_0;
+ __be64 reserved1;
+
+ __be64 RTOT_prio_1;
+ __be64 R1Q_prio_1;
+ __be64 reserved2;
+
+ __be64 RTOT_prio_2;
+ __be64 R1Q_prio_2;
+ __be64 reserved3;
+
+ __be64 RTOT_prio_3;
+ __be64 R1Q_prio_3;
+ __be64 reserved4;
+
+ __be64 RTOT_prio_4;
+ __be64 R1Q_prio_4;
+ __be64 reserved5;
+
+ __be64 RTOT_prio_5;
+ __be64 R1Q_prio_5;
+ __be64 reserved6;
+
+ __be64 RTOT_prio_6;
+ __be64 R1Q_prio_6;
+ __be64 reserved7;
+
+ __be64 RTOT_prio_7;
+ __be64 R1Q_prio_7;
+ __be64 reserved8;
+
+ __be64 RTOT_novlan;
+ __be64 R1Q_novlan;
+ __be64 reserved9;
+
+ /* Total number of Successfully Received Control Frames */
+ __be64 RCNTL;
+ __be64 reserved10;
+ __be64 reserved11;
+ __be64 reserved12;
+ /* Count of received frames with a length/type field value between 46
+ (42 for VLANtagged frames) and 1500 (also 1500 for VLAN-tagged frames),
+ inclusive */
+ __be64 RInRangeLengthErr;
+ /* Count of received frames with length/type field between 1501 and 1535
+ decimal, inclusive */
+ __be64 ROutRangeLengthErr;
+ /* Count of received frames that are longer than max allowed size for
+ 802.3 frames (1518/1522) */
+ __be64 RFrmTooLong;
+ /* Count frames received with PCS error */
+ __be64 PCS;
+
+ /* Transmit frames with a length of 64 octets */
+ __be64 T64_prio_0;
+ __be64 T64_prio_1;
+ __be64 T64_prio_2;
+ __be64 T64_prio_3;
+ __be64 T64_prio_4;
+ __be64 T64_prio_5;
+ __be64 T64_prio_6;
+ __be64 T64_prio_7;
+ __be64 T64_novlan;
+ __be64 T64_loopbk;
+ /* Transmit frames with a length of 65 to 127 octets. */
+ __be64 T127_prio_0;
+ __be64 T127_prio_1;
+ __be64 T127_prio_2;
+ __be64 T127_prio_3;
+ __be64 T127_prio_4;
+ __be64 T127_prio_5;
+ __be64 T127_prio_6;
+ __be64 T127_prio_7;
+ __be64 T127_novlan;
+ __be64 T127_loopbk;
+ /* Transmit frames with a length of 128 to 255 octets */
+ __be64 T255_prio_0;
+ __be64 T255_prio_1;
+ __be64 T255_prio_2;
+ __be64 T255_prio_3;
+ __be64 T255_prio_4;
+ __be64 T255_prio_5;
+ __be64 T255_prio_6;
+ __be64 T255_prio_7;
+ __be64 T255_novlan;
+ __be64 T255_loopbk;
+ /* Transmit frames with a length of 256 to 511 octets */
+ __be64 T511_prio_0;
+ __be64 T511_prio_1;
+ __be64 T511_prio_2;
+ __be64 T511_prio_3;
+ __be64 T511_prio_4;
+ __be64 T511_prio_5;
+ __be64 T511_prio_6;
+ __be64 T511_prio_7;
+ __be64 T511_novlan;
+ __be64 T511_loopbk;
+ /* Transmit frames with a length of 512 to 1023 octets */
+ __be64 T1023_prio_0;
+ __be64 T1023_prio_1;
+ __be64 T1023_prio_2;
+ __be64 T1023_prio_3;
+ __be64 T1023_prio_4;
+ __be64 T1023_prio_5;
+ __be64 T1023_prio_6;
+ __be64 T1023_prio_7;
+ __be64 T1023_novlan;
+ __be64 T1023_loopbk;
+ /* Transmit frames with a length of 1024 to 1518 octets */
+ __be64 T1518_prio_0;
+ __be64 T1518_prio_1;
+ __be64 T1518_prio_2;
+ __be64 T1518_prio_3;
+ __be64 T1518_prio_4;
+ __be64 T1518_prio_5;
+ __be64 T1518_prio_6;
+ __be64 T1518_prio_7;
+ __be64 T1518_novlan;
+ __be64 T1518_loopbk;
+ /* Counts transmit frames with a length of 1519 to 1522 bytes */
+ __be64 T1522_prio_0;
+ __be64 T1522_prio_1;
+ __be64 T1522_prio_2;
+ __be64 T1522_prio_3;
+ __be64 T1522_prio_4;
+ __be64 T1522_prio_5;
+ __be64 T1522_prio_6;
+ __be64 T1522_prio_7;
+ __be64 T1522_novlan;
+ __be64 T1522_loopbk;
+ /* Transmit frames with a length of 1523 to 1548 octets */
+ __be64 T1548_prio_0;
+ __be64 T1548_prio_1;
+ __be64 T1548_prio_2;
+ __be64 T1548_prio_3;
+ __be64 T1548_prio_4;
+ __be64 T1548_prio_5;
+ __be64 T1548_prio_6;
+ __be64 T1548_prio_7;
+ __be64 T1548_novlan;
+ __be64 T1548_loopbk;
+ /* Counts transmit frames with a length of 1549 to MTU bytes */
+ __be64 T2MTU_prio_0;
+ __be64 T2MTU_prio_1;
+ __be64 T2MTU_prio_2;
+ __be64 T2MTU_prio_3;
+ __be64 T2MTU_prio_4;
+ __be64 T2MTU_prio_5;
+ __be64 T2MTU_prio_6;
+ __be64 T2MTU_prio_7;
+ __be64 T2MTU_novlan;
+ __be64 T2MTU_loopbk;
+ /* Transmit frames with a length greater than MTU octets and a good CRC. */
+ __be64 TGIANT_prio_0;
+ __be64 TGIANT_prio_1;
+ __be64 TGIANT_prio_2;
+ __be64 TGIANT_prio_3;
+ __be64 TGIANT_prio_4;
+ __be64 TGIANT_prio_5;
+ __be64 TGIANT_prio_6;
+ __be64 TGIANT_prio_7;
+ __be64 TGIANT_novlan;
+ __be64 TGIANT_loopbk;
+ /* Transmit broadcast frames with a good CRC */
+ __be64 TBCAST_prio_0;
+ __be64 TBCAST_prio_1;
+ __be64 TBCAST_prio_2;
+ __be64 TBCAST_prio_3;
+ __be64 TBCAST_prio_4;
+ __be64 TBCAST_prio_5;
+ __be64 TBCAST_prio_6;
+ __be64 TBCAST_prio_7;
+ __be64 TBCAST_novlan;
+ __be64 TBCAST_loopbk;
+ /* Transmit multicast frames with a good CRC */
+ __be64 TMCAST_prio_0;
+ __be64 TMCAST_prio_1;
+ __be64 TMCAST_prio_2;
+ __be64 TMCAST_prio_3;
+ __be64 TMCAST_prio_4;
+ __be64 TMCAST_prio_5;
+ __be64 TMCAST_prio_6;
+ __be64 TMCAST_prio_7;
+ __be64 TMCAST_novlan;
+ __be64 TMCAST_loopbk;
+ /* Transmit good frames that are neither broadcast nor multicast */
+ __be64 TTOTG_prio_0;
+ __be64 TTOTG_prio_1;
+ __be64 TTOTG_prio_2;
+ __be64 TTOTG_prio_3;
+ __be64 TTOTG_prio_4;
+ __be64 TTOTG_prio_5;
+ __be64 TTOTG_prio_6;
+ __be64 TTOTG_prio_7;
+ __be64 TTOTG_novlan;
+ __be64 TTOTG_loopbk;
+
+ /* total octets of transmitted frames, including framing characters */
+ __be64 TTTLOCT_prio_0;
+ /* total octets of transmitted frames, not including framing characters */
+ __be64 TTTLOCT_NOFRM_prio_0;
+ /* ifOutOctets */
+ __be64 TOCT_prio_0;
+
+ __be64 TTTLOCT_prio_1;
+ __be64 TTTLOCT_NOFRM_prio_1;
+ __be64 TOCT_prio_1;
+
+ __be64 TTTLOCT_prio_2;
+ __be64 TTTLOCT_NOFRM_prio_2;
+ __be64 TOCT_prio_2;
+
+ __be64 TTTLOCT_prio_3;
+ __be64 TTTLOCT_NOFRM_prio_3;
+ __be64 TOCT_prio_3;
+
+ __be64 TTTLOCT_prio_4;
+ __be64 TTTLOCT_NOFRM_prio_4;
+ __be64 TOCT_prio_4;
+
+ __be64 TTTLOCT_prio_5;
+ __be64 TTTLOCT_NOFRM_prio_5;
+ __be64 TOCT_prio_5;
+
+ __be64 TTTLOCT_prio_6;
+ __be64 TTTLOCT_NOFRM_prio_6;
+ __be64 TOCT_prio_6;
+
+ __be64 TTTLOCT_prio_7;
+ __be64 TTTLOCT_NOFRM_prio_7;
+ __be64 TOCT_prio_7;
+
+ __be64 TTTLOCT_novlan;
+ __be64 TTTLOCT_NOFRM_novlan;
+ __be64 TOCT_novlan;
+
+ __be64 TTTLOCT_loopbk;
+ __be64 TTTLOCT_NOFRM_loopbk;
+ __be64 TOCT_loopbk;
+
+ /* Total frames transmitted with a good CRC that are not aborted */
+ __be64 TTOT_prio_0;
+ /* Total number of frames transmitted with 802.1Q encapsulation */
+ __be64 T1Q_prio_0;
+ __be64 reserved13;
+
+ __be64 TTOT_prio_1;
+ __be64 T1Q_prio_1;
+ __be64 reserved14;
+
+ __be64 TTOT_prio_2;
+ __be64 T1Q_prio_2;
+ __be64 reserved15;
+
+ __be64 TTOT_prio_3;
+ __be64 T1Q_prio_3;
+ __be64 reserved16;
+
+ __be64 TTOT_prio_4;
+ __be64 T1Q_prio_4;
+ __be64 reserved17;
+
+ __be64 TTOT_prio_5;
+ __be64 T1Q_prio_5;
+ __be64 reserved18;
+
+ __be64 TTOT_prio_6;
+ __be64 T1Q_prio_6;
+ __be64 reserved19;
+
+ __be64 TTOT_prio_7;
+ __be64 T1Q_prio_7;
+ __be64 reserved20;
+
+ __be64 TTOT_novlan;
+ __be64 T1Q_novlan;
+ __be64 reserved21;
+
+ __be64 TTOT_loopbk;
+ __be64 T1Q_loopbk;
+ __be64 reserved22;
+
+ /* Received frames with a length greater than MTU octets and a bad CRC */
+ __be32 RJBBR;
+ /* Received frames with a bad CRC that are not runts, jabbers,
+ or alignment errors */
+ __be32 RCRC;
+ /* Received frames with SFD with a length of less than 64 octets and a
+ bad CRC */
+ __be32 RRUNT;
+ /* Received frames with a length less than 64 octets and a good CRC */
+ __be32 RSHORT;
+ /* Total Number of Received Packets Dropped */
+ __be32 RDROP;
+ /* Drop due to overflow */
+ __be32 RdropOvflw;
+ /* Drop due to overflow */
+ __be32 RdropLength;
+ /* Total of good frames. Does not include frames received with
+ frame-too-long, FCS, or length errors */
+ __be32 RTOTFRMS;
+ /* Total dropped Xmited packets */
+ __be32 TDROP;
+};
+
+
+#endif
diff --git a/drivers/net/mlx4/en_resources.c b/drivers/net/mlx4/en_resources.c
new file mode 100644
index 00000000000..a0545209e50
--- /dev/null
+++ b/drivers/net/mlx4/en_resources.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/mlx4/qp.h>
+
+#include "mlx4_en.h"
+
+void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
+ int is_tx, int rss, int qpn, int cqn, int srqn,
+ struct mlx4_qp_context *context)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ memset(context, 0, sizeof *context);
+ context->flags = cpu_to_be32(7 << 16 | rss << 13);
+ context->pd = cpu_to_be32(mdev->priv_pdn);
+ context->mtu_msgmax = 0xff;
+ context->rq_size_stride = 0;
+ if (is_tx)
+ context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
+ else
+ context->sq_size_stride = 1;
+ context->usr_page = cpu_to_be32(mdev->priv_uar.index);
+ context->local_qpn = cpu_to_be32(qpn);
+ context->pri_path.ackto = 1 & 0x07;
+ context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6;
+ context->pri_path.counter_index = 0xff;
+ context->cqn_send = cpu_to_be32(cqn);
+ context->cqn_recv = cpu_to_be32(cqn);
+ context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
+ if (!rss)
+ context->srqn = cpu_to_be32(MLX4_EN_USE_SRQ | srqn);
+}
+
+
+int mlx4_en_map_buffer(struct mlx4_buf *buf)
+{
+ struct page **pages;
+ int i;
+
+ if (BITS_PER_LONG == 64 || buf->nbufs == 1)
+ return 0;
+
+ pages = kmalloc(sizeof *pages * buf->nbufs, GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ for (i = 0; i < buf->nbufs; ++i)
+ pages[i] = virt_to_page(buf->page_list[i].buf);
+
+ buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL);
+ kfree(pages);
+ if (!buf->direct.buf)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void mlx4_en_unmap_buffer(struct mlx4_buf *buf)
+{
+ if (BITS_PER_LONG == 64 || buf->nbufs == 1)
+ return;
+
+ vunmap(buf->direct.buf);
+}
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
new file mode 100644
index 00000000000..6232227f56c
--- /dev/null
+++ b/drivers/net/mlx4/en_rx.c
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/mlx4/cq.h>
+#include <linux/mlx4/qp.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
+
+#include "mlx4_en.h"
+
+static void *get_wqe(struct mlx4_en_rx_ring *ring, int n)
+{
+ int offset = n << ring->srq.wqe_shift;
+ return ring->buf + offset;
+}
+
+static void mlx4_en_srq_event(struct mlx4_srq *srq, enum mlx4_event type)
+{
+ return;
+}
+
+static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
+ void **ip_hdr, void **tcpudp_hdr,
+ u64 *hdr_flags, void *priv)
+{
+ *mac_hdr = page_address(frags->page) + frags->page_offset;
+ *ip_hdr = *mac_hdr + ETH_HLEN;
+ *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr));
+ *hdr_flags = LRO_IPV4 | LRO_TCP;
+
+ return 0;
+}
+
+static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_desc *rx_desc,
+ struct skb_frag_struct *skb_frags,
+ struct mlx4_en_rx_alloc *ring_alloc,
+ int i)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_frag_info *frag_info = &priv->frag_info[i];
+ struct mlx4_en_rx_alloc *page_alloc = &ring_alloc[i];
+ struct page *page;
+ dma_addr_t dma;
+
+ if (page_alloc->offset == frag_info->last_offset) {
+ /* Allocate new page */
+ page = alloc_pages(GFP_ATOMIC | __GFP_COMP, MLX4_EN_ALLOC_ORDER);
+ if (!page)
+ return -ENOMEM;
+
+ skb_frags[i].page = page_alloc->page;
+ skb_frags[i].page_offset = page_alloc->offset;
+ page_alloc->page = page;
+ page_alloc->offset = frag_info->frag_align;
+ } else {
+ page = page_alloc->page;
+ get_page(page);
+
+ skb_frags[i].page = page;
+ skb_frags[i].page_offset = page_alloc->offset;
+ page_alloc->offset += frag_info->frag_stride;
+ }
+ dma = pci_map_single(mdev->pdev, page_address(skb_frags[i].page) +
+ skb_frags[i].page_offset, frag_info->frag_size,
+ PCI_DMA_FROMDEVICE);
+ rx_desc->data[i].addr = cpu_to_be64(dma);
+ return 0;
+}
+
+static int mlx4_en_init_allocator(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring)
+{
+ struct mlx4_en_rx_alloc *page_alloc;
+ int i;
+
+ for (i = 0; i < priv->num_frags; i++) {
+ page_alloc = &ring->page_alloc[i];
+ page_alloc->page = alloc_pages(GFP_ATOMIC | __GFP_COMP,
+ MLX4_EN_ALLOC_ORDER);
+ if (!page_alloc->page)
+ goto out;
+
+ page_alloc->offset = priv->frag_info[i].frag_align;
+ mlx4_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n",
+ i, page_alloc->page);
+ }
+ return 0;
+
+out:
+ while (i--) {
+ page_alloc = &ring->page_alloc[i];
+ put_page(page_alloc->page);
+ page_alloc->page = NULL;
+ }
+ return -ENOMEM;
+}
+
+static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring)
+{
+ struct mlx4_en_rx_alloc *page_alloc;
+ int i;
+
+ for (i = 0; i < priv->num_frags; i++) {
+ page_alloc = &ring->page_alloc[i];
+ mlx4_dbg(DRV, priv, "Freeing allocator:%d count:%d\n",
+ i, page_count(page_alloc->page));
+
+ put_page(page_alloc->page);
+ page_alloc->page = NULL;
+ }
+}
+
+
+static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring, int index)
+{
+ struct mlx4_en_rx_desc *rx_desc = ring->buf + ring->stride * index;
+ struct skb_frag_struct *skb_frags = ring->rx_info +
+ (index << priv->log_rx_info);
+ int possible_frags;
+ int i;
+
+ /* Pre-link descriptor */
+ rx_desc->next.next_wqe_index = cpu_to_be16((index + 1) & ring->size_mask);
+
+ /* Set size and memtype fields */
+ for (i = 0; i < priv->num_frags; i++) {
+ skb_frags[i].size = priv->frag_info[i].frag_size;
+ rx_desc->data[i].byte_count =
+ cpu_to_be32(priv->frag_info[i].frag_size);
+ rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key);
+ }
+
+ /* If the number of used fragments does not fill up the ring stride,
+ * remaining (unused) fragments must be padded with null address/size
+ * and a special memory key */
+ possible_frags = (ring->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
+ for (i = priv->num_frags; i < possible_frags; i++) {
+ rx_desc->data[i].byte_count = 0;
+ rx_desc->data[i].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
+ rx_desc->data[i].addr = 0;
+ }
+}
+
+
+static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring, int index)
+{
+ struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride);
+ struct skb_frag_struct *skb_frags = ring->rx_info +
+ (index << priv->log_rx_info);
+ int i;
+
+ for (i = 0; i < priv->num_frags; i++)
+ if (mlx4_en_alloc_frag(priv, rx_desc, skb_frags, ring->page_alloc, i))
+ goto err;
+
+ return 0;
+
+err:
+ while (i--)
+ put_page(skb_frags[i].page);
+ return -ENOMEM;
+}
+
+static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
+{
+ *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
+}
+
+static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_rx_ring *ring;
+ int ring_ind;
+ int buf_ind;
+
+ for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) {
+ for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
+ ring = &priv->rx_ring[ring_ind];
+
+ if (mlx4_en_prepare_rx_desc(priv, ring,
+ ring->actual_size)) {
+ if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) {
+ mlx4_err(mdev, "Failed to allocate "
+ "enough rx buffers\n");
+ return -ENOMEM;
+ } else {
+ if (netif_msg_rx_err(priv))
+ mlx4_warn(mdev,
+ "Only %d buffers allocated\n",
+ ring->actual_size);
+ goto out;
+ }
+ }
+ ring->actual_size++;
+ ring->prod++;
+ }
+ }
+out:
+ return 0;
+}
+
+static int mlx4_en_fill_rx_buf(struct net_device *dev,
+ struct mlx4_en_rx_ring *ring)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int num = 0;
+ int err;
+
+ while ((u32) (ring->prod - ring->cons) < ring->actual_size) {
+ err = mlx4_en_prepare_rx_desc(priv, ring, ring->prod &
+ ring->size_mask);
+ if (err) {
+ if (netif_msg_rx_err(priv))
+ mlx4_warn(priv->mdev,
+ "Failed preparing rx descriptor\n");
+ priv->port_stats.rx_alloc_failed++;
+ break;
+ }
+ ++num;
+ ++ring->prod;
+ }
+ if ((u32) (ring->prod - ring->cons) == ring->size)
+ ring->full = 1;
+
+ return num;
+}
+
+static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct skb_frag_struct *skb_frags;
+ struct mlx4_en_rx_desc *rx_desc;
+ dma_addr_t dma;
+ int index;
+ int nr;
+
+ mlx4_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n",
+ ring->cons, ring->prod);
+
+ /* Unmap and free Rx buffers */
+ BUG_ON((u32) (ring->prod - ring->cons) > ring->size);
+ while (ring->cons != ring->prod) {
+ index = ring->cons & ring->size_mask;
+ rx_desc = ring->buf + (index << ring->log_stride);
+ skb_frags = ring->rx_info + (index << priv->log_rx_info);
+ mlx4_dbg(DRV, priv, "Processing descriptor:%d\n", index);
+
+ for (nr = 0; nr < priv->num_frags; nr++) {
+ mlx4_dbg(DRV, priv, "Freeing fragment:%d\n", nr);
+ dma = be64_to_cpu(rx_desc->data[nr].addr);
+
+ mlx4_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma);
+ pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size,
+ PCI_DMA_FROMDEVICE);
+ put_page(skb_frags[nr].page);
+ }
+ ++ring->cons;
+ }
+}
+
+
+void mlx4_en_rx_refill(struct work_struct *work)
+{
+ struct delayed_work *delay = container_of(work, struct delayed_work, work);
+ struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
+ refill_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct net_device *dev = priv->dev;
+ struct mlx4_en_rx_ring *ring;
+ int need_refill = 0;
+ int i;
+
+ mutex_lock(&mdev->state_lock);
+ if (!mdev->device_up || !priv->port_up)
+ goto out;
+
+ /* We only get here if there are no receive buffers, so we can't race
+ * with Rx interrupts while filling buffers */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ ring = &priv->rx_ring[i];
+ if (ring->need_refill) {
+ if (mlx4_en_fill_rx_buf(dev, ring)) {
+ ring->need_refill = 0;
+ mlx4_en_update_rx_prod_db(ring);
+ } else
+ need_refill = 1;
+ }
+ }
+ if (need_refill)
+ queue_delayed_work(mdev->workqueue, &priv->refill_task, HZ);
+
+out:
+ mutex_unlock(&mdev->state_lock);
+}
+
+
+int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring, u32 size, u16 stride)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+ int tmp;
+
+ /* Sanity check SRQ size before proceeding */
+ if (size >= mdev->dev->caps.max_srq_wqes)
+ return -EINVAL;
+
+ ring->prod = 0;
+ ring->cons = 0;
+ ring->size = size;
+ ring->size_mask = size - 1;
+ ring->stride = stride;
+ ring->log_stride = ffs(ring->stride) - 1;
+ ring->buf_size = ring->size * ring->stride;
+
+ tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
+ sizeof(struct skb_frag_struct));
+ ring->rx_info = vmalloc(tmp);
+ if (!ring->rx_info) {
+ mlx4_err(mdev, "Failed allocating rx_info ring\n");
+ return -ENOMEM;
+ }
+ mlx4_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n",
+ ring->rx_info, tmp);
+
+ err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres,
+ ring->buf_size, 2 * PAGE_SIZE);
+ if (err)
+ goto err_ring;
+
+ err = mlx4_en_map_buffer(&ring->wqres.buf);
+ if (err) {
+ mlx4_err(mdev, "Failed to map RX buffer\n");
+ goto err_hwq;
+ }
+ ring->buf = ring->wqres.buf.direct.buf;
+
+ /* Configure lro mngr */
+ memset(&ring->lro, 0, sizeof(struct net_lro_mgr));
+ ring->lro.dev = priv->dev;
+ ring->lro.features = LRO_F_NAPI;
+ ring->lro.frag_align_pad = NET_IP_ALIGN;
+ ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
+ ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+ ring->lro.max_desc = mdev->profile.num_lro;
+ ring->lro.max_aggr = MAX_SKB_FRAGS;
+ ring->lro.lro_arr = kzalloc(mdev->profile.num_lro *
+ sizeof(struct net_lro_desc),
+ GFP_KERNEL);
+ if (!ring->lro.lro_arr) {
+ mlx4_err(mdev, "Failed to allocate lro array\n");
+ goto err_map;
+ }
+ ring->lro.get_frag_header = mlx4_en_get_frag_header;
+
+ return 0;
+
+err_map:
+ mlx4_en_unmap_buffer(&ring->wqres.buf);
+err_hwq:
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+err_ring:
+ vfree(ring->rx_info);
+ ring->rx_info = NULL;
+ return err;
+}
+
+int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_wqe_srq_next_seg *next;
+ struct mlx4_en_rx_ring *ring;
+ int i;
+ int ring_ind;
+ int err;
+ int stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
+ DS_SIZE * priv->num_frags);
+ int max_gs = (stride - sizeof(struct mlx4_wqe_srq_next_seg)) / DS_SIZE;
+
+ for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
+ ring = &priv->rx_ring[ring_ind];
+
+ ring->prod = 0;
+ ring->cons = 0;
+ ring->actual_size = 0;
+ ring->cqn = priv->rx_cq[ring_ind].mcq.cqn;
+
+ ring->stride = stride;
+ ring->log_stride = ffs(ring->stride) - 1;
+ ring->buf_size = ring->size * ring->stride;
+
+ memset(ring->buf, 0, ring->buf_size);
+ mlx4_en_update_rx_prod_db(ring);
+
+ /* Initailize all descriptors */
+ for (i = 0; i < ring->size; i++)
+ mlx4_en_init_rx_desc(priv, ring, i);
+
+ /* Initialize page allocators */
+ err = mlx4_en_init_allocator(priv, ring);
+ if (err) {
+ mlx4_err(mdev, "Failed initializing ring allocator\n");
+ goto err_allocator;
+ }
+
+ /* Fill Rx buffers */
+ ring->full = 0;
+ }
+ if (mlx4_en_fill_rx_buffers(priv))
+ goto err_buffers;
+
+ for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
+ ring = &priv->rx_ring[ring_ind];
+
+ mlx4_en_update_rx_prod_db(ring);
+
+ /* Configure SRQ representing the ring */
+ ring->srq.max = ring->size;
+ ring->srq.max_gs = max_gs;
+ ring->srq.wqe_shift = ilog2(ring->stride);
+
+ for (i = 0; i < ring->srq.max; ++i) {
+ next = get_wqe(ring, i);
+ next->next_wqe_index =
+ cpu_to_be16((i + 1) & (ring->srq.max - 1));
+ }
+
+ err = mlx4_srq_alloc(mdev->dev, mdev->priv_pdn, &ring->wqres.mtt,
+ ring->wqres.db.dma, &ring->srq);
+ if (err){
+ mlx4_err(mdev, "Failed to allocate srq\n");
+ goto err_srq;
+ }
+ ring->srq.event = mlx4_en_srq_event;
+ }
+
+ return 0;
+
+err_srq:
+ while (ring_ind >= 0) {
+ ring = &priv->rx_ring[ring_ind];
+ mlx4_srq_free(mdev->dev, &ring->srq);
+ ring_ind--;
+ }
+
+err_buffers:
+ for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++)
+ mlx4_en_free_rx_buf(priv, &priv->rx_ring[ring_ind]);
+
+ ring_ind = priv->rx_ring_num - 1;
+err_allocator:
+ while (ring_ind >= 0) {
+ mlx4_en_destroy_allocator(priv, &priv->rx_ring[ring_ind]);
+ ring_ind--;
+ }
+ return err;
+}
+
+void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ kfree(ring->lro.lro_arr);
+ mlx4_en_unmap_buffer(&ring->wqres.buf);
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ vfree(ring->rx_info);
+ ring->rx_info = NULL;
+}
+
+void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ mlx4_srq_free(mdev->dev, &ring->srq);
+ mlx4_en_free_rx_buf(priv, ring);
+ mlx4_en_destroy_allocator(priv, ring);
+}
+
+
+/* Unmap a completed descriptor and free unused pages */
+static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_desc *rx_desc,
+ struct skb_frag_struct *skb_frags,
+ struct skb_frag_struct *skb_frags_rx,
+ struct mlx4_en_rx_alloc *page_alloc,
+ int length)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_frag_info *frag_info;
+ int nr;
+ dma_addr_t dma;
+
+ /* Collect used fragments while replacing them in the HW descirptors */
+ for (nr = 0; nr < priv->num_frags; nr++) {
+ frag_info = &priv->frag_info[nr];
+ if (length <= frag_info->frag_prefix_size)
+ break;
+
+ /* Save page reference in skb */
+ skb_frags_rx[nr].page = skb_frags[nr].page;
+ skb_frags_rx[nr].size = skb_frags[nr].size;
+ skb_frags_rx[nr].page_offset = skb_frags[nr].page_offset;
+ dma = be64_to_cpu(rx_desc->data[nr].addr);
+
+ /* Allocate a replacement page */
+ if (mlx4_en_alloc_frag(priv, rx_desc, skb_frags, page_alloc, nr))
+ goto fail;
+
+ /* Unmap buffer */
+ pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size,
+ PCI_DMA_FROMDEVICE);
+ }
+ /* Adjust size of last fragment to match actual length */
+ skb_frags_rx[nr - 1].size = length -
+ priv->frag_info[nr - 1].frag_prefix_size;
+ return nr;
+
+fail:
+ /* Drop all accumulated fragments (which have already been replaced in
+ * the descriptor) of this packet; remaining fragments are reused... */
+ while (nr > 0) {
+ nr--;
+ put_page(skb_frags_rx[nr].page);
+ }
+ return 0;
+}
+
+
+static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_desc *rx_desc,
+ struct skb_frag_struct *skb_frags,
+ struct mlx4_en_rx_alloc *page_alloc,
+ unsigned int length)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct sk_buff *skb;
+ void *va;
+ int used_frags;
+ dma_addr_t dma;
+
+ skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN);
+ if (!skb) {
+ mlx4_dbg(RX_ERR, priv, "Failed allocating skb\n");
+ return NULL;
+ }
+ skb->dev = priv->dev;
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb->len = length;
+ skb->truesize = length + sizeof(struct sk_buff);
+
+ /* Get pointer to first fragment so we could copy the headers into the
+ * (linear part of the) skb */
+ va = page_address(skb_frags[0].page) + skb_frags[0].page_offset;
+
+ if (length <= SMALL_PACKET_SIZE) {
+ /* We are copying all relevant data to the skb - temporarily
+ * synch buffers for the copy */
+ dma = be64_to_cpu(rx_desc->data[0].addr);
+ dma_sync_single_range_for_cpu(&mdev->pdev->dev, dma, 0,
+ length, DMA_FROM_DEVICE);
+ skb_copy_to_linear_data(skb, va, length);
+ dma_sync_single_range_for_device(&mdev->pdev->dev, dma, 0,
+ length, DMA_FROM_DEVICE);
+ skb->tail += length;
+ } else {
+
+ /* Move relevant fragments to skb */
+ used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags,
+ skb_shinfo(skb)->frags,
+ page_alloc, length);
+ skb_shinfo(skb)->nr_frags = used_frags;
+
+ /* Copy headers into the skb linear buffer */
+ memcpy(skb->data, va, HEADER_COPY_SIZE);
+ skb->tail += HEADER_COPY_SIZE;
+
+ /* Skip headers in first fragment */
+ skb_shinfo(skb)->frags[0].page_offset += HEADER_COPY_SIZE;
+
+ /* Adjust size of first fragment */
+ skb_shinfo(skb)->frags[0].size -= HEADER_COPY_SIZE;
+ skb->data_len = length - HEADER_COPY_SIZE;
+ }
+ return skb;
+}
+
+static void mlx4_en_copy_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring,
+ int from, int to, int num)
+{
+ struct skb_frag_struct *skb_frags_from;
+ struct skb_frag_struct *skb_frags_to;
+ struct mlx4_en_rx_desc *rx_desc_from;
+ struct mlx4_en_rx_desc *rx_desc_to;
+ int from_index, to_index;
+ int nr, i;
+
+ for (i = 0; i < num; i++) {
+ from_index = (from + i) & ring->size_mask;
+ to_index = (to + i) & ring->size_mask;
+ skb_frags_from = ring->rx_info + (from_index << priv->log_rx_info);
+ skb_frags_to = ring->rx_info + (to_index << priv->log_rx_info);
+ rx_desc_from = ring->buf + (from_index << ring->log_stride);
+ rx_desc_to = ring->buf + (to_index << ring->log_stride);
+
+ for (nr = 0; nr < priv->num_frags; nr++) {
+ skb_frags_to[nr].page = skb_frags_from[nr].page;
+ skb_frags_to[nr].page_offset = skb_frags_from[nr].page_offset;
+ rx_desc_to->data[nr].addr = rx_desc_from->data[nr].addr;
+ }
+ }
+}
+
+
+int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_cqe *cqe;
+ struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
+ struct skb_frag_struct *skb_frags;
+ struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS];
+ struct mlx4_en_rx_desc *rx_desc;
+ struct sk_buff *skb;
+ int index;
+ int nr;
+ unsigned int length;
+ int polled = 0;
+ int ip_summed;
+
+ if (!priv->port_up)
+ return 0;
+
+ /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
+ * descriptor offset can be deduced from the CQE index instead of
+ * reading 'cqe->index' */
+ index = cq->mcq.cons_index & ring->size_mask;
+ cqe = &cq->buf[index];
+
+ /* Process all completed CQEs */
+ while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
+ cq->mcq.cons_index & cq->size)) {
+
+ skb_frags = ring->rx_info + (index << priv->log_rx_info);
+ rx_desc = ring->buf + (index << ring->log_stride);
+
+ /*
+ * make sure we read the CQE after we read the ownership bit
+ */
+ rmb();
+
+ /* Drop packet on bad receive or bad checksum */
+ if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
+ MLX4_CQE_OPCODE_ERROR)) {
+ mlx4_err(mdev, "CQE completed in error - vendor "
+ "syndrom:%d syndrom:%d\n",
+ ((struct mlx4_err_cqe *) cqe)->vendor_err_syndrome,
+ ((struct mlx4_err_cqe *) cqe)->syndrome);
+ goto next;
+ }
+ if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) {
+ mlx4_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n");
+ goto next;
+ }
+
+ /*
+ * Packet is OK - process it.
+ */
+ length = be32_to_cpu(cqe->byte_cnt);
+ ring->bytes += length;
+ ring->packets++;
+
+ if (likely(priv->rx_csum)) {
+ if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
+ (cqe->checksum == cpu_to_be16(0xffff))) {
+ priv->port_stats.rx_chksum_good++;
+ /* This packet is eligible for LRO if it is:
+ * - DIX Ethernet (type interpretation)
+ * - TCP/IP (v4)
+ * - without IP options
+ * - not an IP fragment */
+ if (mlx4_en_can_lro(cqe->status) &&
+ dev->features & NETIF_F_LRO) {
+
+ nr = mlx4_en_complete_rx_desc(
+ priv, rx_desc,
+ skb_frags, lro_frags,
+ ring->page_alloc, length);
+ if (!nr)
+ goto next;
+
+ if (priv->vlgrp && (cqe->vlan_my_qpn &
+ cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) {
+ lro_vlan_hwaccel_receive_frags(
+ &ring->lro, lro_frags,
+ length, length,
+ priv->vlgrp,
+ be16_to_cpu(cqe->sl_vid),
+ NULL, 0);
+ } else
+ lro_receive_frags(&ring->lro,
+ lro_frags,
+ length,
+ length,
+ NULL, 0);
+
+ goto next;
+ }
+
+ /* LRO not possible, complete processing here */
+ ip_summed = CHECKSUM_UNNECESSARY;
+ INC_PERF_COUNTER(priv->pstats.lro_misses);
+ } else {
+ ip_summed = CHECKSUM_NONE;
+ priv->port_stats.rx_chksum_none++;
+ }
+ } else {
+ ip_summed = CHECKSUM_NONE;
+ priv->port_stats.rx_chksum_none++;
+ }
+
+ skb = mlx4_en_rx_skb(priv, rx_desc, skb_frags,
+ ring->page_alloc, length);
+ if (!skb) {
+ priv->stats.rx_dropped++;
+ goto next;
+ }
+
+ skb->ip_summed = ip_summed;
+ skb->protocol = eth_type_trans(skb, dev);
+
+ /* Push it up the stack */
+ if (priv->vlgrp && (be32_to_cpu(cqe->vlan_my_qpn) &
+ MLX4_CQE_VLAN_PRESENT_MASK)) {
+ vlan_hwaccel_receive_skb(skb, priv->vlgrp,
+ be16_to_cpu(cqe->sl_vid));
+ } else
+ netif_receive_skb(skb);
+
+ dev->last_rx = jiffies;
+
+next:
+ ++cq->mcq.cons_index;
+ index = (cq->mcq.cons_index) & ring->size_mask;
+ cqe = &cq->buf[index];
+ if (++polled == budget) {
+ /* We are here because we reached the NAPI budget -
+ * flush only pending LRO sessions */
+ lro_flush_all(&ring->lro);
+ goto out;
+ }
+ }
+
+ /* If CQ is empty flush all LRO sessions unconditionally */
+ lro_flush_all(&ring->lro);
+
+out:
+ AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
+ mlx4_cq_set_ci(&cq->mcq);
+ wmb(); /* ensure HW sees CQ consumer before we post new buffers */
+ ring->cons = cq->mcq.cons_index;
+ ring->prod += polled; /* Polled descriptors were realocated in place */
+ if (unlikely(!ring->full)) {
+ mlx4_en_copy_desc(priv, ring, ring->cons - polled,
+ ring->prod - polled, polled);
+ mlx4_en_fill_rx_buf(dev, ring);
+ }
+ mlx4_en_update_rx_prod_db(ring);
+ return polled;
+}
+
+
+void mlx4_en_rx_irq(struct mlx4_cq *mcq)
+{
+ struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
+ struct mlx4_en_priv *priv = netdev_priv(cq->dev);
+
+ if (priv->port_up)
+ netif_rx_schedule(cq->dev, &cq->napi);
+ else
+ mlx4_en_arm_cq(priv, cq);
+}
+
+/* Rx CQ polling - called by NAPI */
+int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+{
+ struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi);
+ struct net_device *dev = cq->dev;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int done;
+
+ done = mlx4_en_process_rx_cq(dev, cq, budget);
+
+ /* If we used up all the quota - we're probably not done yet... */
+ if (done == budget)
+ INC_PERF_COUNTER(priv->pstats.napi_quota);
+ else {
+ /* Done for now */
+ netif_rx_complete(dev, napi);
+ mlx4_en_arm_cq(priv, cq);
+ }
+ return done;
+}
+
+
+/* Calculate the last offset position that accomodates a full fragment
+ * (assuming fagment size = stride-align) */
+static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align)
+{
+ u16 res = MLX4_EN_ALLOC_SIZE % stride;
+ u16 offset = MLX4_EN_ALLOC_SIZE - stride - res + align;
+
+ mlx4_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d "
+ "res:%d offset:%d\n", stride, align, res, offset);
+ return offset;
+}
+
+
+static int frag_sizes[] = {
+ FRAG_SZ0,
+ FRAG_SZ1,
+ FRAG_SZ2,
+ FRAG_SZ3
+};
+
+void mlx4_en_calc_rx_buf(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN + ETH_LLC_SNAP_SIZE;
+ int buf_size = 0;
+ int i = 0;
+
+ while (buf_size < eff_mtu) {
+ priv->frag_info[i].frag_size =
+ (eff_mtu > buf_size + frag_sizes[i]) ?
+ frag_sizes[i] : eff_mtu - buf_size;
+ priv->frag_info[i].frag_prefix_size = buf_size;
+ if (!i) {
+ priv->frag_info[i].frag_align = NET_IP_ALIGN;
+ priv->frag_info[i].frag_stride =
+ ALIGN(frag_sizes[i] + NET_IP_ALIGN, SMP_CACHE_BYTES);
+ } else {
+ priv->frag_info[i].frag_align = 0;
+ priv->frag_info[i].frag_stride =
+ ALIGN(frag_sizes[i], SMP_CACHE_BYTES);
+ }
+ priv->frag_info[i].last_offset = mlx4_en_last_alloc_offset(
+ priv, priv->frag_info[i].frag_stride,
+ priv->frag_info[i].frag_align);
+ buf_size += priv->frag_info[i].frag_size;
+ i++;
+ }
+
+ priv->num_frags = i;
+ priv->rx_skb_size = eff_mtu;
+ priv->log_rx_info = ROUNDUP_LOG2(i * sizeof(struct skb_frag_struct));
+
+ mlx4_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d "
+ "num_frags:%d):\n", eff_mtu, priv->num_frags);
+ for (i = 0; i < priv->num_frags; i++) {
+ mlx4_dbg(DRV, priv, " frag:%d - size:%d prefix:%d align:%d "
+ "stride:%d last_offset:%d\n", i,
+ priv->frag_info[i].frag_size,
+ priv->frag_info[i].frag_prefix_size,
+ priv->frag_info[i].frag_align,
+ priv->frag_info[i].frag_stride,
+ priv->frag_info[i].last_offset);
+ }
+}
+
+/* RSS related functions */
+
+/* Calculate rss size and map each entry in rss table to rx ring */
+void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
+ struct mlx4_en_rss_map *rss_map,
+ int num_entries, int num_rings)
+{
+ int i;
+
+ rss_map->size = roundup_pow_of_two(num_entries);
+ mlx4_dbg(DRV, priv, "Setting default RSS map of %d entires\n",
+ rss_map->size);
+
+ for (i = 0; i < rss_map->size; i++) {
+ rss_map->map[i] = i % num_rings;
+ mlx4_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]);
+ }
+}
+
+static void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event)
+{
+ return;
+}
+
+
+static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv,
+ int qpn, int srqn, int cqn,
+ enum mlx4_qp_state *state,
+ struct mlx4_qp *qp)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_qp_context *context;
+ int err = 0;
+
+ context = kmalloc(sizeof *context , GFP_KERNEL);
+ if (!context) {
+ mlx4_err(mdev, "Failed to allocate qp context\n");
+ return -ENOMEM;
+ }
+
+ err = mlx4_qp_alloc(mdev->dev, qpn, qp);
+ if (err) {
+ mlx4_err(mdev, "Failed to allocate qp #%d\n", qpn);
+ goto out;
+ return err;
+ }
+ qp->event = mlx4_en_sqp_event;
+
+ memset(context, 0, sizeof *context);
+ mlx4_en_fill_qp_context(priv, 0, 0, 0, 0, qpn, cqn, srqn, context);
+
+ err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, context, qp, state);
+ if (err) {
+ mlx4_qp_remove(mdev->dev, qp);
+ mlx4_qp_free(mdev->dev, qp);
+ }
+out:
+ kfree(context);
+ return err;
+}
+
+/* Allocate rx qp's and configure them according to rss map */
+int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+ struct mlx4_qp_context context;
+ struct mlx4_en_rss_context *rss_context;
+ void *ptr;
+ int rss_xor = mdev->profile.rss_xor;
+ u8 rss_mask = mdev->profile.rss_mask;
+ int i, srqn, qpn, cqn;
+ int err = 0;
+ int good_qps = 0;
+
+ mlx4_dbg(DRV, priv, "Configuring rss steering for port %u\n", priv->port);
+ err = mlx4_qp_reserve_range(mdev->dev, rss_map->size,
+ rss_map->size, &rss_map->base_qpn);
+ if (err) {
+ mlx4_err(mdev, "Failed reserving %d qps for port %u\n",
+ rss_map->size, priv->port);
+ return err;
+ }
+
+ for (i = 0; i < rss_map->size; i++) {
+ cqn = priv->rx_ring[rss_map->map[i]].cqn;
+ srqn = priv->rx_ring[rss_map->map[i]].srq.srqn;
+ qpn = rss_map->base_qpn + i;
+ err = mlx4_en_config_rss_qp(priv, qpn, srqn, cqn,
+ &rss_map->state[i],
+ &rss_map->qps[i]);
+ if (err)
+ goto rss_err;
+
+ ++good_qps;
+ }
+
+ /* Configure RSS indirection qp */
+ err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
+ if (err) {
+ mlx4_err(mdev, "Failed to reserve range for RSS "
+ "indirection qp\n");
+ goto rss_err;
+ }
+ err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
+ if (err) {
+ mlx4_err(mdev, "Failed to allocate RSS indirection QP\n");
+ goto reserve_err;
+ }
+ rss_map->indir_qp.event = mlx4_en_sqp_event;
+ mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
+ priv->rx_ring[0].cqn, 0, &context);
+
+ ptr = ((void *) &context) + 0x3c;
+ rss_context = (struct mlx4_en_rss_context *) ptr;
+ rss_context->base_qpn = cpu_to_be32(ilog2(rss_map->size) << 24 |
+ (rss_map->base_qpn));
+ rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
+ rss_context->hash_fn = rss_xor & 0x3;
+ rss_context->flags = rss_mask << 2;
+
+ err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
+ &rss_map->indir_qp, &rss_map->indir_state);
+ if (err)
+ goto indir_err;
+
+ return 0;
+
+indir_err:
+ mlx4_qp_modify(mdev->dev, NULL, rss_map->indir_state,
+ MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
+ mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
+ mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
+reserve_err:
+ mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
+rss_err:
+ for (i = 0; i < good_qps; i++) {
+ mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
+ MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]);
+ mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
+ mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
+ }
+ mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size);
+ return err;
+}
+
+void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+ int i;
+
+ mlx4_qp_modify(mdev->dev, NULL, rss_map->indir_state,
+ MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
+ mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
+ mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
+ mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
+
+ for (i = 0; i < rss_map->size; i++) {
+ mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
+ MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]);
+ mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
+ mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
+ }
+ mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size);
+}
+
+
+
+
+
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
new file mode 100644
index 00000000000..8592f8fb847
--- /dev/null
+++ b/drivers/net/mlx4/en_tx.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <asm/page.h>
+#include <linux/mlx4/cq.h>
+#include <linux/mlx4/qp.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
+
+#include "mlx4_en.h"
+
+enum {
+ MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
+};
+
+static int inline_thold __read_mostly = MAX_INLINE;
+
+module_param_named(inline_thold, inline_thold, int, 0444);
+MODULE_PARM_DESC(inline_thold, "treshold for using inline data");
+
+int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring, u32 size,
+ u16 stride)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int tmp;
+ int err;
+
+ ring->size = size;
+ ring->size_mask = size - 1;
+ ring->stride = stride;
+
+ inline_thold = min(inline_thold, MAX_INLINE);
+
+ spin_lock_init(&ring->comp_lock);
+
+ tmp = size * sizeof(struct mlx4_en_tx_info);
+ ring->tx_info = vmalloc(tmp);
+ if (!ring->tx_info) {
+ mlx4_err(mdev, "Failed allocating tx_info ring\n");
+ return -ENOMEM;
+ }
+ mlx4_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
+ ring->tx_info, tmp);
+
+ ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL);
+ if (!ring->bounce_buf) {
+ mlx4_err(mdev, "Failed allocating bounce buffer\n");
+ err = -ENOMEM;
+ goto err_tx;
+ }
+ ring->buf_size = ALIGN(size * ring->stride, MLX4_EN_PAGE_SIZE);
+
+ err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size,
+ 2 * PAGE_SIZE);
+ if (err) {
+ mlx4_err(mdev, "Failed allocating hwq resources\n");
+ goto err_bounce;
+ }
+
+ err = mlx4_en_map_buffer(&ring->wqres.buf);
+ if (err) {
+ mlx4_err(mdev, "Failed to map TX buffer\n");
+ goto err_hwq_res;
+ }
+
+ ring->buf = ring->wqres.buf.direct.buf;
+
+ mlx4_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d "
+ "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
+ ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
+
+ err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn);
+ if (err) {
+ mlx4_err(mdev, "Failed reserving qp for tx ring.\n");
+ goto err_map;
+ }
+
+ err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp);
+ if (err) {
+ mlx4_err(mdev, "Failed allocating qp %d\n", ring->qpn);
+ goto err_reserve;
+ }
+
+ return 0;
+
+err_reserve:
+ mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
+err_map:
+ mlx4_en_unmap_buffer(&ring->wqres.buf);
+err_hwq_res:
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+err_bounce:
+ kfree(ring->bounce_buf);
+ ring->bounce_buf = NULL;
+err_tx:
+ vfree(ring->tx_info);
+ ring->tx_info = NULL;
+ return err;
+}
+
+void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ mlx4_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
+
+ mlx4_qp_remove(mdev->dev, &ring->qp);
+ mlx4_qp_free(mdev->dev, &ring->qp);
+ mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
+ mlx4_en_unmap_buffer(&ring->wqres.buf);
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ kfree(ring->bounce_buf);
+ ring->bounce_buf = NULL;
+ vfree(ring->tx_info);
+ ring->tx_info = NULL;
+}
+
+int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring,
+ int cq, int srqn)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ ring->cqn = cq;
+ ring->prod = 0;
+ ring->cons = 0xffffffff;
+ ring->last_nr_txbb = 1;
+ ring->poll_cnt = 0;
+ ring->blocked = 0;
+ memset(ring->tx_info, 0, ring->size * sizeof(struct mlx4_en_tx_info));
+ memset(ring->buf, 0, ring->buf_size);
+
+ ring->qp_state = MLX4_QP_STATE_RST;
+ ring->doorbell_qpn = swab32(ring->qp.qpn << 8);
+
+ mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
+ ring->cqn, srqn, &ring->context);
+
+ err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
+ &ring->qp, &ring->qp_state);
+
+ return err;
+}
+
+void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ mlx4_qp_modify(mdev->dev, NULL, ring->qp_state,
+ MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
+}
+
+
+static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring,
+ int index, u8 owner)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
+ struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
+ struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset;
+ struct sk_buff *skb = tx_info->skb;
+ struct skb_frag_struct *frag;
+ void *end = ring->buf + ring->buf_size;
+ int frags = skb_shinfo(skb)->nr_frags;
+ int i;
+ __be32 *ptr = (__be32 *)tx_desc;
+ __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
+
+ /* Optimize the common case when there are no wraparounds */
+ if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
+ if (tx_info->linear) {
+ pci_unmap_single(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data->addr),
+ be32_to_cpu(data->byte_count),
+ PCI_DMA_TODEVICE);
+ ++data;
+ }
+
+ for (i = 0; i < frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i];
+ pci_unmap_page(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data[i].addr),
+ frag->size, PCI_DMA_TODEVICE);
+ }
+ /* Stamp the freed descriptor */
+ for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
+ *ptr = stamp;
+ ptr += STAMP_DWORDS;
+ }
+
+ } else {
+ if ((void *) data >= end) {
+ data = (struct mlx4_wqe_data_seg *)
+ (ring->buf + ((void *) data - end));
+ }
+
+ if (tx_info->linear) {
+ pci_unmap_single(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data->addr),
+ be32_to_cpu(data->byte_count),
+ PCI_DMA_TODEVICE);
+ ++data;
+ }
+
+ for (i = 0; i < frags; i++) {
+ /* Check for wraparound before unmapping */
+ if ((void *) data >= end)
+ data = (struct mlx4_wqe_data_seg *) ring->buf;
+ frag = &skb_shinfo(skb)->frags[i];
+ pci_unmap_page(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data->addr),
+ frag->size, PCI_DMA_TODEVICE);
+ }
+ /* Stamp the freed descriptor */
+ for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
+ *ptr = stamp;
+ ptr += STAMP_DWORDS;
+ if ((void *) ptr >= end) {
+ ptr = ring->buf;
+ stamp ^= cpu_to_be32(0x80000000);
+ }
+ }
+
+ }
+ dev_kfree_skb_any(skb);
+ return tx_info->nr_txbb;
+}
+
+
+int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int cnt = 0;
+
+ /* Skip last polled descriptor */
+ ring->cons += ring->last_nr_txbb;
+ mlx4_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n",
+ ring->cons, ring->prod);
+
+ if ((u32) (ring->prod - ring->cons) > ring->size) {
+ if (netif_msg_tx_err(priv))
+ mlx4_warn(priv->mdev, "Tx consumer passed producer!\n");
+ return 0;
+ }
+
+ while (ring->cons != ring->prod) {
+ ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring,
+ ring->cons & ring->size_mask,
+ !!(ring->cons & ring->size));
+ ring->cons += ring->last_nr_txbb;
+ cnt++;
+ }
+
+ if (cnt)
+ mlx4_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt);
+
+ return cnt;
+}
+
+void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num)
+{
+ int block = 8 / ring_num;
+ int extra = 8 - (block * ring_num);
+ int num = 0;
+ u16 ring = 1;
+ int prio;
+
+ if (ring_num == 1) {
+ for (prio = 0; prio < 8; prio++)
+ prio_map[prio] = 0;
+ return;
+ }
+
+ for (prio = 0; prio < 8; prio++) {
+ if (extra && (num == block + 1)) {
+ ring++;
+ num = 0;
+ extra--;
+ } else if (!extra && (num == block)) {
+ ring++;
+ num = 0;
+ }
+ prio_map[prio] = ring;
+ mlx4_dbg(DRV, priv, " prio:%d --> ring:%d\n", prio, ring);
+ num++;
+ }
+}
+
+static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_cq *mcq = &cq->mcq;
+ struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
+ struct mlx4_cqe *cqe = cq->buf;
+ u16 index;
+ u16 new_index;
+ u32 txbbs_skipped = 0;
+ u32 cq_last_sav;
+
+ /* index always points to the first TXBB of the last polled descriptor */
+ index = ring->cons & ring->size_mask;
+ new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask;
+ if (index == new_index)
+ return;
+
+ if (!priv->port_up)
+ return;
+
+ /*
+ * We use a two-stage loop:
+ * - the first samples the HW-updated CQE
+ * - the second frees TXBBs until the last sample
+ * This lets us amortize CQE cache misses, while still polling the CQ
+ * until is quiescent.
+ */
+ cq_last_sav = mcq->cons_index;
+ do {
+ do {
+ /* Skip over last polled CQE */
+ index = (index + ring->last_nr_txbb) & ring->size_mask;
+ txbbs_skipped += ring->last_nr_txbb;
+
+ /* Poll next CQE */
+ ring->last_nr_txbb = mlx4_en_free_tx_desc(
+ priv, ring, index,
+ !!((ring->cons + txbbs_skipped) &
+ ring->size));
+ ++mcq->cons_index;
+
+ } while (index != new_index);
+
+ new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask;
+ } while (index != new_index);
+ AVG_PERF_COUNTER(priv->pstats.tx_coal_avg,
+ (u32) (mcq->cons_index - cq_last_sav));
+
+ /*
+ * To prevent CQ overflow we first update CQ consumer and only then
+ * the ring consumer.
+ */
+ mlx4_cq_set_ci(mcq);
+ wmb();
+ ring->cons += txbbs_skipped;
+
+ /* Wakeup Tx queue if this ring stopped it */
+ if (unlikely(ring->blocked)) {
+ if (((u32) (ring->prod - ring->cons) <=
+ ring->size - HEADROOM - MAX_DESC_TXBBS) && !cq->armed) {
+
+ /* TODO: support multiqueue netdevs. Currently, we block
+ * when *any* ring is full. Note that:
+ * - 2 Tx rings can unblock at the same time and call
+ * netif_wake_queue(), which is OK since this
+ * operation is idempotent.
+ * - We might wake the queue just after another ring
+ * stopped it. This is no big deal because the next
+ * transmission on that ring would stop the queue.
+ */
+ ring->blocked = 0;
+ netif_wake_queue(dev);
+ priv->port_stats.wake_queue++;
+ }
+ }
+}
+
+void mlx4_en_tx_irq(struct mlx4_cq *mcq)
+{
+ struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
+ struct mlx4_en_priv *priv = netdev_priv(cq->dev);
+ struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
+
+ spin_lock_irq(&ring->comp_lock);
+ cq->armed = 0;
+ mlx4_en_process_tx_cq(cq->dev, cq);
+ if (ring->blocked)
+ mlx4_en_arm_cq(priv, cq);
+ else
+ mod_timer(&cq->timer, jiffies + 1);
+ spin_unlock_irq(&ring->comp_lock);
+}
+
+
+void mlx4_en_poll_tx_cq(unsigned long data)
+{
+ struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data;
+ struct mlx4_en_priv *priv = netdev_priv(cq->dev);
+ struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
+ u32 inflight;
+
+ INC_PERF_COUNTER(priv->pstats.tx_poll);
+
+ netif_tx_lock(priv->dev);
+ spin_lock_irq(&ring->comp_lock);
+ mlx4_en_process_tx_cq(cq->dev, cq);
+ inflight = (u32) (ring->prod - ring->cons - ring->last_nr_txbb);
+
+ /* If there are still packets in flight and the timer has not already
+ * been scheduled by the Tx routine then schedule it here to guarantee
+ * completion processing of these packets */
+ if (inflight && priv->port_up)
+ mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
+
+ spin_unlock_irq(&ring->comp_lock);
+ netif_tx_unlock(priv->dev);
+}
+
+static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring,
+ u32 index,
+ unsigned int desc_size)
+{
+ u32 copy = (ring->size - index) * TXBB_SIZE;
+ int i;
+
+ for (i = desc_size - copy - 4; i >= 0; i -= 4) {
+ if ((i & (TXBB_SIZE - 1)) == 0)
+ wmb();
+
+ *((u32 *) (ring->buf + i)) =
+ *((u32 *) (ring->bounce_buf + copy + i));
+ }
+
+ for (i = copy - 4; i >= 4 ; i -= 4) {
+ if ((i & (TXBB_SIZE - 1)) == 0)
+ wmb();
+
+ *((u32 *) (ring->buf + index * TXBB_SIZE + i)) =
+ *((u32 *) (ring->bounce_buf + i));
+ }
+
+ /* Return real descriptor location */
+ return ring->buf + index * TXBB_SIZE;
+}
+
+static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
+{
+ struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind];
+ struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind];
+
+ /* If we don't have a pending timer, set one up to catch our recent
+ post in case the interface becomes idle */
+ if (!timer_pending(&cq->timer))
+ mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
+
+ /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
+ if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
+ mlx4_en_process_tx_cq(priv->dev, cq);
+}
+
+static void *get_frag_ptr(struct sk_buff *skb)
+{
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
+ struct page *page = frag->page;
+ void *ptr;
+
+ ptr = page_address(page);
+ if (unlikely(!ptr))
+ return NULL;
+
+ return ptr + frag->page_offset;
+}
+
+static int is_inline(struct sk_buff *skb, void **pfrag)
+{
+ void *ptr;
+
+ if (inline_thold && !skb_is_gso(skb) && skb->len <= inline_thold) {
+ if (skb_shinfo(skb)->nr_frags == 1) {
+ ptr = get_frag_ptr(skb);
+ if (unlikely(!ptr))
+ return 0;
+
+ if (pfrag)
+ *pfrag = ptr;
+
+ return 1;
+ } else if (unlikely(skb_shinfo(skb)->nr_frags))
+ return 0;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+static int inline_size(struct sk_buff *skb)
+{
+ if (skb->len + CTRL_SIZE + sizeof(struct mlx4_wqe_inline_seg)
+ <= MLX4_INLINE_ALIGN)
+ return ALIGN(skb->len + CTRL_SIZE +
+ sizeof(struct mlx4_wqe_inline_seg), 16);
+ else
+ return ALIGN(skb->len + CTRL_SIZE + 2 *
+ sizeof(struct mlx4_wqe_inline_seg), 16);
+}
+
+static int get_real_size(struct sk_buff *skb, struct net_device *dev,
+ int *lso_header_size)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int real_size;
+
+ if (skb_is_gso(skb)) {
+ *lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ real_size = CTRL_SIZE + skb_shinfo(skb)->nr_frags * DS_SIZE +
+ ALIGN(*lso_header_size + 4, DS_SIZE);
+ if (unlikely(*lso_header_size != skb_headlen(skb))) {
+ /* We add a segment for the skb linear buffer only if
+ * it contains data */
+ if (*lso_header_size < skb_headlen(skb))
+ real_size += DS_SIZE;
+ else {
+ if (netif_msg_tx_err(priv))
+ mlx4_warn(mdev, "Non-linear headers\n");
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+ }
+ if (unlikely(*lso_header_size > MAX_LSO_HDR_SIZE)) {
+ if (netif_msg_tx_err(priv))
+ mlx4_warn(mdev, "LSO header size too big\n");
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+ } else {
+ *lso_header_size = 0;
+ if (!is_inline(skb, NULL))
+ real_size = CTRL_SIZE + (skb_shinfo(skb)->nr_frags + 1) * DS_SIZE;
+ else
+ real_size = inline_size(skb);
+ }
+
+ return real_size;
+}
+
+static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *skb,
+ int real_size, u16 *vlan_tag, int tx_ind, void *fragptr)
+{
+ struct mlx4_wqe_inline_seg *inl = &tx_desc->inl;
+ int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - sizeof *inl;
+
+ if (skb->len <= spc) {
+ inl->byte_count = cpu_to_be32(1 << 31 | skb->len);
+ skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb));
+ if (skb_shinfo(skb)->nr_frags)
+ memcpy(((void *)(inl + 1)) + skb_headlen(skb), fragptr,
+ skb_shinfo(skb)->frags[0].size);
+
+ } else {
+ inl->byte_count = cpu_to_be32(1 << 31 | spc);
+ if (skb_headlen(skb) <= spc) {
+ skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb));
+ if (skb_headlen(skb) < spc) {
+ memcpy(((void *)(inl + 1)) + skb_headlen(skb),
+ fragptr, spc - skb_headlen(skb));
+ fragptr += spc - skb_headlen(skb);
+ }
+ inl = (void *) (inl + 1) + spc;
+ memcpy(((void *)(inl + 1)), fragptr, skb->len - spc);
+ } else {
+ skb_copy_from_linear_data(skb, inl + 1, spc);
+ inl = (void *) (inl + 1) + spc;
+ skb_copy_from_linear_data_offset(skb, spc, inl + 1,
+ skb_headlen(skb) - spc);
+ if (skb_shinfo(skb)->nr_frags)
+ memcpy(((void *)(inl + 1)) + skb_headlen(skb) - spc,
+ fragptr, skb_shinfo(skb)->frags[0].size);
+ }
+
+ wmb();
+ inl->byte_count = cpu_to_be32(1 << 31 | (skb->len - spc));
+ }
+ tx_desc->ctrl.vlan_tag = cpu_to_be16(*vlan_tag);
+ tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN * !!(*vlan_tag);
+ tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
+}
+
+static int get_vlan_info(struct mlx4_en_priv *priv, struct sk_buff *skb,
+ u16 *vlan_tag)
+{
+ int tx_ind;
+
+ /* Obtain VLAN information if present */
+ if (priv->vlgrp && vlan_tx_tag_present(skb)) {
+ *vlan_tag = vlan_tx_tag_get(skb);
+ /* Set the Tx ring to use according to vlan priority */
+ tx_ind = priv->tx_prio_map[*vlan_tag >> 13];
+ } else {
+ *vlan_tag = 0;
+ tx_ind = 0;
+ }
+ return tx_ind;
+}
+
+int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_ring *ring;
+ struct mlx4_en_cq *cq;
+ struct mlx4_en_tx_desc *tx_desc;
+ struct mlx4_wqe_data_seg *data;
+ struct skb_frag_struct *frag;
+ struct mlx4_en_tx_info *tx_info;
+ int tx_ind = 0;
+ int nr_txbb;
+ int desc_size;
+ int real_size;
+ dma_addr_t dma;
+ u32 index;
+ __be32 op_own;
+ u16 vlan_tag;
+ int i;
+ int lso_header_size;
+ void *fragptr;
+
+ if (unlikely(!skb->len)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ real_size = get_real_size(skb, dev, &lso_header_size);
+ if (unlikely(!real_size))
+ return NETDEV_TX_OK;
+
+ /* Allign descriptor to TXBB size */
+ desc_size = ALIGN(real_size, TXBB_SIZE);
+ nr_txbb = desc_size / TXBB_SIZE;
+ if (unlikely(nr_txbb > MAX_DESC_TXBBS)) {
+ if (netif_msg_tx_err(priv))
+ mlx4_warn(mdev, "Oversized header or SG list\n");
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ tx_ind = get_vlan_info(priv, skb, &vlan_tag);
+ ring = &priv->tx_ring[tx_ind];
+
+ /* Check available TXBBs And 2K spare for prefetch */
+ if (unlikely(((int)(ring->prod - ring->cons)) >
+ ring->size - HEADROOM - MAX_DESC_TXBBS)) {
+ /* every full Tx ring stops queue.
+ * TODO: implement multi-queue support (per-queue stop) */
+ netif_stop_queue(dev);
+ ring->blocked = 1;
+ priv->port_stats.queue_stopped++;
+
+ /* Use interrupts to find out when queue opened */
+ cq = &priv->tx_cq[tx_ind];
+ mlx4_en_arm_cq(priv, cq);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* Now that we know what Tx ring to use */
+ if (unlikely(!priv->port_up)) {
+ if (netif_msg_tx_err(priv))
+ mlx4_warn(mdev, "xmit: port down!\n");
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ /* Track current inflight packets for performance analysis */
+ AVG_PERF_COUNTER(priv->pstats.inflight_avg,
+ (u32) (ring->prod - ring->cons - 1));
+
+ /* Packet is good - grab an index and transmit it */
+ index = ring->prod & ring->size_mask;
+
+ /* See if we have enough space for whole descriptor TXBB for setting
+ * SW ownership on next descriptor; if not, use a bounce buffer. */
+ if (likely(index + nr_txbb <= ring->size))
+ tx_desc = ring->buf + index * TXBB_SIZE;
+ else
+ tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf;
+
+ /* Save skb in tx_info ring */
+ tx_info = &ring->tx_info[index];
+ tx_info->skb = skb;
+ tx_info->nr_txbb = nr_txbb;
+
+ /* Prepare ctrl segement apart opcode+ownership, which depends on
+ * whether LSO is used */
+ tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag);
+ tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN * !!vlan_tag;
+ tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
+ tx_desc->ctrl.srcrb_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
+ MLX4_WQE_CTRL_SOLICITED);
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
+ MLX4_WQE_CTRL_TCP_UDP_CSUM);
+ priv->port_stats.tx_chksum_offload++;
+ }
+
+ /* Handle LSO (TSO) packets */
+ if (lso_header_size) {
+ /* Mark opcode as LSO */
+ op_own = cpu_to_be32(MLX4_OPCODE_LSO | (1 << 6)) |
+ ((ring->prod & ring->size) ?
+ cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
+
+ /* Fill in the LSO prefix */
+ tx_desc->lso.mss_hdr_size = cpu_to_be32(
+ skb_shinfo(skb)->gso_size << 16 | lso_header_size);
+
+ /* Copy headers;
+ * note that we already verified that it is linear */
+ memcpy(tx_desc->lso.header, skb->data, lso_header_size);
+ data = ((void *) &tx_desc->lso +
+ ALIGN(lso_header_size + 4, DS_SIZE));
+
+ priv->port_stats.tso_packets++;
+ i = ((skb->len - lso_header_size) / skb_shinfo(skb)->gso_size) +
+ !!((skb->len - lso_header_size) % skb_shinfo(skb)->gso_size);
+ ring->bytes += skb->len + (i - 1) * lso_header_size;
+ ring->packets += i;
+ } else {
+ /* Normal (Non LSO) packet */
+ op_own = cpu_to_be32(MLX4_OPCODE_SEND) |
+ ((ring->prod & ring->size) ?
+ cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
+ data = &tx_desc->data;
+ ring->bytes += max(skb->len, (unsigned int) ETH_ZLEN);
+ ring->packets++;
+
+ }
+ AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, skb->len);
+
+
+ /* valid only for none inline segments */
+ tx_info->data_offset = (void *) data - (void *) tx_desc;
+
+ tx_info->linear = (lso_header_size < skb_headlen(skb) && !is_inline(skb, NULL)) ? 1 : 0;
+ data += skb_shinfo(skb)->nr_frags + tx_info->linear - 1;
+
+ if (!is_inline(skb, &fragptr)) {
+ /* Map fragments */
+ for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) {
+ frag = &skb_shinfo(skb)->frags[i];
+ dma = pci_map_page(mdev->dev->pdev, frag->page, frag->page_offset,
+ frag->size, PCI_DMA_TODEVICE);
+ data->addr = cpu_to_be64(dma);
+ data->lkey = cpu_to_be32(mdev->mr.key);
+ wmb();
+ data->byte_count = cpu_to_be32(frag->size);
+ --data;
+ }
+
+ /* Map linear part */
+ if (tx_info->linear) {
+ dma = pci_map_single(mdev->dev->pdev, skb->data + lso_header_size,
+ skb_headlen(skb) - lso_header_size, PCI_DMA_TODEVICE);
+ data->addr = cpu_to_be64(dma);
+ data->lkey = cpu_to_be32(mdev->mr.key);
+ wmb();
+ data->byte_count = cpu_to_be32(skb_headlen(skb) - lso_header_size);
+ }
+ } else
+ build_inline_wqe(tx_desc, skb, real_size, &vlan_tag, tx_ind, fragptr);
+
+ ring->prod += nr_txbb;
+
+ /* If we used a bounce buffer then copy descriptor back into place */
+ if (tx_desc == (struct mlx4_en_tx_desc *) ring->bounce_buf)
+ tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
+
+ /* Run destructor before passing skb to HW */
+ if (likely(!skb_shared(skb)))
+ skb_orphan(skb);
+
+ /* Ensure new descirptor hits memory
+ * before setting ownership of this descriptor to HW */
+ wmb();
+ tx_desc->ctrl.owner_opcode = op_own;
+
+ /* Ring doorbell! */
+ wmb();
+ writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL);
+ dev->trans_start = jiffies;
+
+ /* Poll CQ here */
+ mlx4_en_xmit_poll(priv, tx_ind);
+
+ return 0;
+}
+
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 8a8b56135a5..de169338cd9 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -558,7 +558,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
int i;
err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs,
- dev->caps.num_eqs - 1, dev->caps.reserved_eqs);
+ dev->caps.num_eqs - 1, dev->caps.reserved_eqs, 0);
if (err)
return err;
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 7e32955da98..be09fdb79cb 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -88,6 +88,7 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
[ 8] = "P_Key violation counter",
[ 9] = "Q_Key violation counter",
[10] = "VMM",
+ [12] = "DPDP",
[16] = "MW support",
[17] = "APM support",
[18] = "Atomic ops support",
@@ -346,7 +347,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
dev_cap->max_vl[i] = field >> 4;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
- dev_cap->max_mtu[i] = field >> 4;
+ dev_cap->ib_mtu[i] = field >> 4;
dev_cap->max_port_width[i] = field & 0xf;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
dev_cap->max_gids[i] = 1 << (field & 0xf);
@@ -354,9 +355,13 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_pkeys[i] = 1 << (field & 0xf);
}
} else {
+#define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00
#define QUERY_PORT_MTU_OFFSET 0x01
+#define QUERY_PORT_ETH_MTU_OFFSET 0x02
#define QUERY_PORT_WIDTH_OFFSET 0x06
#define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07
+#define QUERY_PORT_MAC_OFFSET 0x08
+#define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a
#define QUERY_PORT_MAX_VL_OFFSET 0x0b
for (i = 1; i <= dev_cap->num_ports; ++i) {
@@ -365,8 +370,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
if (err)
goto out;
+ MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET);
+ dev_cap->supported_port_types[i] = field & 3;
MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
- dev_cap->max_mtu[i] = field & 0xf;
+ dev_cap->ib_mtu[i] = field & 0xf;
MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
dev_cap->max_port_width[i] = field & 0xf;
MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
@@ -374,6 +381,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_pkeys[i] = 1 << (field & 0xf);
MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
dev_cap->max_vl[i] = field & 0xf;
+ MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET);
+ dev_cap->log_max_macs[i] = field & 0xf;
+ dev_cap->log_max_vlans[i] = field >> 4;
+ MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET);
+ MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET);
}
}
@@ -407,7 +419,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
- dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1],
+ dev_cap->local_ca_ack_delay, 128 << dev_cap->ib_mtu[1],
dev_cap->max_port_width[1]);
mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
@@ -819,7 +831,7 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET);
- field = 128 << dev->caps.mtu_cap[port];
+ field = 128 << dev->caps.ib_mtu_cap[port];
MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
field = dev->caps.gid_table_len[port];
MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index decbb5c2ad4..526d7f30c04 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -66,11 +66,13 @@ struct mlx4_dev_cap {
int local_ca_ack_delay;
int num_ports;
u32 max_msg_sz;
- int max_mtu[MLX4_MAX_PORTS + 1];
+ int ib_mtu[MLX4_MAX_PORTS + 1];
int max_port_width[MLX4_MAX_PORTS + 1];
int max_vl[MLX4_MAX_PORTS + 1];
int max_gids[MLX4_MAX_PORTS + 1];
int max_pkeys[MLX4_MAX_PORTS + 1];
+ u64 def_mac[MLX4_MAX_PORTS + 1];
+ u16 eth_mtu[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
u32 flags;
int reserved_uars;
@@ -102,6 +104,9 @@ struct mlx4_dev_cap {
u32 reserved_lkey;
u64 max_icm_sz;
int max_gso_sz;
+ u8 supported_port_types[MLX4_MAX_PORTS + 1];
+ u8 log_max_macs[MLX4_MAX_PORTS + 1];
+ u8 log_max_vlans[MLX4_MAX_PORTS + 1];
};
struct mlx4_adapter {
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 1252a919de2..468921b8f4b 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -85,6 +85,57 @@ static struct mlx4_profile default_profile = {
.num_mtt = 1 << 20,
};
+static int log_num_mac = 2;
+module_param_named(log_num_mac, log_num_mac, int, 0444);
+MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
+
+static int log_num_vlan;
+module_param_named(log_num_vlan, log_num_vlan, int, 0444);
+MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)");
+
+static int use_prio;
+module_param_named(use_prio, use_prio, bool, 0444);
+MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports "
+ "(0/1, default 0)");
+
+static int mlx4_check_port_params(struct mlx4_dev *dev,
+ enum mlx4_port_type *port_type)
+{
+ int i;
+
+ for (i = 0; i < dev->caps.num_ports - 1; i++) {
+ if (port_type[i] != port_type[i+1] &&
+ !(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) {
+ mlx4_err(dev, "Only same port types supported "
+ "on this HCA, aborting.\n");
+ return -EINVAL;
+ }
+ }
+ if ((port_type[0] == MLX4_PORT_TYPE_ETH) &&
+ (port_type[1] == MLX4_PORT_TYPE_IB)) {
+ mlx4_err(dev, "eth-ib configuration is not supported.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < dev->caps.num_ports; i++) {
+ if (!(port_type[i] & dev->caps.supported_type[i+1])) {
+ mlx4_err(dev, "Requested port type for port %d is not "
+ "supported on this HCA\n", i + 1);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static void mlx4_set_port_mask(struct mlx4_dev *dev)
+{
+ int i;
+
+ dev->caps.port_mask = 0;
+ for (i = 1; i <= dev->caps.num_ports; ++i)
+ if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
+ dev->caps.port_mask |= 1 << (i - 1);
+}
static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
int err;
@@ -120,10 +171,13 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.num_ports = dev_cap->num_ports;
for (i = 1; i <= dev->caps.num_ports; ++i) {
dev->caps.vl_cap[i] = dev_cap->max_vl[i];
- dev->caps.mtu_cap[i] = dev_cap->max_mtu[i];
+ dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i];
dev->caps.gid_table_len[i] = dev_cap->max_gids[i];
dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i];
dev->caps.port_width_cap[i] = dev_cap->max_port_width[i];
+ dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i];
+ dev->caps.def_mac[i] = dev_cap->def_mac[i];
+ dev->caps.supported_type[i] = dev_cap->supported_port_types[i];
}
dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE;
@@ -134,7 +188,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_rq_sg = dev_cap->max_rq_sg;
dev->caps.max_wqes = dev_cap->max_qp_sz;
dev->caps.max_qp_init_rdma = dev_cap->max_requester_per_qp;
- dev->caps.reserved_qps = dev_cap->reserved_qps;
dev->caps.max_srq_wqes = dev_cap->max_srq_sz;
dev->caps.max_srq_sge = dev_cap->max_rq_sg - 1;
dev->caps.reserved_srqs = dev_cap->reserved_srqs;
@@ -163,9 +216,138 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
+ dev->caps.log_num_macs = log_num_mac;
+ dev->caps.log_num_vlans = log_num_vlan;
+ dev->caps.log_num_prios = use_prio ? 3 : 0;
+
+ for (i = 1; i <= dev->caps.num_ports; ++i) {
+ if (dev->caps.supported_type[i] != MLX4_PORT_TYPE_ETH)
+ dev->caps.port_type[i] = MLX4_PORT_TYPE_IB;
+ else
+ dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH;
+
+ if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) {
+ dev->caps.log_num_macs = dev_cap->log_max_macs[i];
+ mlx4_warn(dev, "Requested number of MACs is too much "
+ "for port %d, reducing to %d.\n",
+ i, 1 << dev->caps.log_num_macs);
+ }
+ if (dev->caps.log_num_vlans > dev_cap->log_max_vlans[i]) {
+ dev->caps.log_num_vlans = dev_cap->log_max_vlans[i];
+ mlx4_warn(dev, "Requested number of VLANs is too much "
+ "for port %d, reducing to %d.\n",
+ i, 1 << dev->caps.log_num_vlans);
+ }
+ }
+
+ mlx4_set_port_mask(dev);
+
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] =
+ (1 << dev->caps.log_num_macs) *
+ (1 << dev->caps.log_num_vlans) *
+ (1 << dev->caps.log_num_prios) *
+ dev->caps.num_ports;
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH;
+
+ dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] +
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] +
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] +
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH];
+
return 0;
}
+/*
+ * Change the port configuration of the device.
+ * Every user of this function must hold the port mutex.
+ */
+static int mlx4_change_port_types(struct mlx4_dev *dev,
+ enum mlx4_port_type *port_types)
+{
+ int err = 0;
+ int change = 0;
+ int port;
+
+ for (port = 0; port < dev->caps.num_ports; port++) {
+ if (port_types[port] != dev->caps.port_type[port + 1]) {
+ change = 1;
+ dev->caps.port_type[port + 1] = port_types[port];
+ }
+ }
+ if (change) {
+ mlx4_unregister_device(dev);
+ for (port = 1; port <= dev->caps.num_ports; port++) {
+ mlx4_CLOSE_PORT(dev, port);
+ err = mlx4_SET_PORT(dev, port);
+ if (err) {
+ mlx4_err(dev, "Failed to set port %d, "
+ "aborting\n", port);
+ goto out;
+ }
+ }
+ mlx4_set_port_mask(dev);
+ err = mlx4_register_device(dev);
+ }
+
+out:
+ return err;
+}
+
+static ssize_t show_port_type(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
+ port_attr);
+ struct mlx4_dev *mdev = info->dev;
+
+ return sprintf(buf, "%s\n",
+ mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB ?
+ "ib" : "eth");
+}
+
+static ssize_t set_port_type(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
+ port_attr);
+ struct mlx4_dev *mdev = info->dev;
+ struct mlx4_priv *priv = mlx4_priv(mdev);
+ enum mlx4_port_type types[MLX4_MAX_PORTS];
+ int i;
+ int err = 0;
+
+ if (!strcmp(buf, "ib\n"))
+ info->tmp_type = MLX4_PORT_TYPE_IB;
+ else if (!strcmp(buf, "eth\n"))
+ info->tmp_type = MLX4_PORT_TYPE_ETH;
+ else {
+ mlx4_err(mdev, "%s is not supported port type\n", buf);
+ return -EINVAL;
+ }
+
+ mutex_lock(&priv->port_mutex);
+ for (i = 0; i < mdev->caps.num_ports; i++)
+ types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type :
+ mdev->caps.port_type[i+1];
+
+ err = mlx4_check_port_params(mdev, types);
+ if (err)
+ goto out;
+
+ for (i = 1; i <= mdev->caps.num_ports; i++)
+ priv->port[i].tmp_type = 0;
+
+ err = mlx4_change_port_types(mdev, types);
+
+out:
+ mutex_unlock(&priv->port_mutex);
+ return err ? err : count;
+}
+
static int mlx4_load_fw(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -211,7 +393,8 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
((u64) (MLX4_CMPT_TYPE_QP *
cmpt_entry_sz) << MLX4_CMPT_SHIFT),
cmpt_entry_sz, dev->caps.num_qps,
- dev->caps.reserved_qps, 0, 0);
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
+ 0, 0);
if (err)
goto err;
@@ -336,7 +519,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
init_hca->qpc_base,
dev_cap->qpc_entry_sz,
dev->caps.num_qps,
- dev->caps.reserved_qps, 0, 0);
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
+ 0, 0);
if (err) {
mlx4_err(dev, "Failed to map QP context memory, aborting.\n");
goto err_unmap_dmpt;
@@ -346,7 +530,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
init_hca->auxc_base,
dev_cap->aux_entry_sz,
dev->caps.num_qps,
- dev->caps.reserved_qps, 0, 0);
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
+ 0, 0);
if (err) {
mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n");
goto err_unmap_qp;
@@ -356,7 +541,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
init_hca->altc_base,
dev_cap->altc_entry_sz,
dev->caps.num_qps,
- dev->caps.reserved_qps, 0, 0);
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
+ 0, 0);
if (err) {
mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n");
goto err_unmap_auxc;
@@ -366,7 +552,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
init_hca->rdmarc_base,
dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift,
dev->caps.num_qps,
- dev->caps.reserved_qps, 0, 0);
+ dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
+ 0, 0);
if (err) {
mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n");
goto err_unmap_altc;
@@ -565,6 +752,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
+ int port;
err = mlx4_init_uar_table(dev);
if (err) {
@@ -663,8 +851,20 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_qp_table_free;
}
+ for (port = 1; port <= dev->caps.num_ports; port++) {
+ err = mlx4_SET_PORT(dev, port);
+ if (err) {
+ mlx4_err(dev, "Failed to set port %d, aborting\n",
+ port);
+ goto err_mcg_table_free;
+ }
+ }
+
return 0;
+err_mcg_table_free:
+ mlx4_cleanup_mcg_table(dev);
+
err_qp_table_free:
mlx4_cleanup_qp_table(dev);
@@ -728,11 +928,45 @@ no_msi:
priv->eq_table.eq[i].irq = dev->pdev->irq;
}
+static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
+{
+ struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+ int err = 0;
+
+ info->dev = dev;
+ info->port = port;
+ mlx4_init_mac_table(dev, &info->mac_table);
+ mlx4_init_vlan_table(dev, &info->vlan_table);
+
+ sprintf(info->dev_name, "mlx4_port%d", port);
+ info->port_attr.attr.name = info->dev_name;
+ info->port_attr.attr.mode = S_IRUGO | S_IWUSR;
+ info->port_attr.show = show_port_type;
+ info->port_attr.store = set_port_type;
+
+ err = device_create_file(&dev->pdev->dev, &info->port_attr);
+ if (err) {
+ mlx4_err(dev, "Failed to create file for port %d\n", port);
+ info->port = -1;
+ }
+
+ return err;
+}
+
+static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
+{
+ if (info->port < 0)
+ return;
+
+ device_remove_file(&info->dev->pdev->dev, &info->port_attr);
+}
+
static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct mlx4_priv *priv;
struct mlx4_dev *dev;
int err;
+ int port;
printk(KERN_INFO PFX "Initializing %s\n",
pci_name(pdev));
@@ -807,6 +1041,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&priv->ctx_list);
spin_lock_init(&priv->ctx_lock);
+ mutex_init(&priv->port_mutex);
+
INIT_LIST_HEAD(&priv->pgdir_list);
mutex_init(&priv->pgdir_mutex);
@@ -842,15 +1078,24 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto err_close;
+ for (port = 1; port <= dev->caps.num_ports; port++) {
+ err = mlx4_init_port_info(dev, port);
+ if (err)
+ goto err_port;
+ }
+
err = mlx4_register_device(dev);
if (err)
- goto err_cleanup;
+ goto err_port;
pci_set_drvdata(pdev, dev);
return 0;
-err_cleanup:
+err_port:
+ for (port = 1; port <= dev->caps.num_ports; port++)
+ mlx4_cleanup_port_info(&priv->port[port]);
+
mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
@@ -907,8 +1152,10 @@ static void mlx4_remove_one(struct pci_dev *pdev)
if (dev) {
mlx4_unregister_device(dev);
- for (p = 1; p <= dev->caps.num_ports; ++p)
+ for (p = 1; p <= dev->caps.num_ports; p++) {
+ mlx4_cleanup_port_info(&priv->port[p]);
mlx4_CLOSE_PORT(dev, p);
+ }
mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
@@ -948,6 +1195,8 @@ static struct pci_device_id mlx4_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */
{ PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */
{ PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */
+ { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */
+ { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
{ 0, }
};
@@ -960,10 +1209,28 @@ static struct pci_driver mlx4_driver = {
.remove = __devexit_p(mlx4_remove_one)
};
+static int __init mlx4_verify_params(void)
+{
+ if ((log_num_mac < 0) || (log_num_mac > 7)) {
+ printk(KERN_WARNING "mlx4_core: bad num_mac: %d\n", log_num_mac);
+ return -1;
+ }
+
+ if ((log_num_vlan < 0) || (log_num_vlan > 7)) {
+ printk(KERN_WARNING "mlx4_core: bad num_vlan: %d\n", log_num_vlan);
+ return -1;
+ }
+
+ return 0;
+}
+
static int __init mlx4_init(void)
{
int ret;
+ if (mlx4_verify_params())
+ return -EINVAL;
+
ret = mlx4_catas_init();
if (ret)
return ret;
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index c83f88ce073..592c01ae2c5 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -368,8 +368,8 @@ int mlx4_init_mcg_table(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
- err = mlx4_bitmap_init(&priv->mcg_table.bitmap,
- dev->caps.num_amgms, dev->caps.num_amgms - 1, 0);
+ err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms,
+ dev->caps.num_amgms - 1, 0, 0);
if (err)
return err;
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 5337e3ac3e7..fa431fad0ee 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -111,6 +111,7 @@ struct mlx4_bitmap {
u32 last;
u32 top;
u32 max;
+ u32 reserved_top;
u32 mask;
spinlock_t lock;
unsigned long *table;
@@ -251,6 +252,38 @@ struct mlx4_catas_err {
struct list_head list;
};
+#define MLX4_MAX_MAC_NUM 128
+#define MLX4_MAC_TABLE_SIZE (MLX4_MAX_MAC_NUM << 3)
+
+struct mlx4_mac_table {
+ __be64 entries[MLX4_MAX_MAC_NUM];
+ int refs[MLX4_MAX_MAC_NUM];
+ struct mutex mutex;
+ int total;
+ int max;
+};
+
+#define MLX4_MAX_VLAN_NUM 128
+#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2)
+
+struct mlx4_vlan_table {
+ __be32 entries[MLX4_MAX_VLAN_NUM];
+ int refs[MLX4_MAX_VLAN_NUM];
+ struct mutex mutex;
+ int total;
+ int max;
+};
+
+struct mlx4_port_info {
+ struct mlx4_dev *dev;
+ int port;
+ char dev_name[16];
+ struct device_attribute port_attr;
+ enum mlx4_port_type tmp_type;
+ struct mlx4_mac_table mac_table;
+ struct mlx4_vlan_table vlan_table;
+};
+
struct mlx4_priv {
struct mlx4_dev dev;
@@ -279,6 +312,8 @@ struct mlx4_priv {
struct mlx4_uar driver_uar;
void __iomem *kar;
+ struct mlx4_port_info port[MLX4_MAX_PORTS + 1];
+ struct mutex port_mutex;
};
static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
@@ -288,7 +323,10 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap);
void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj);
-int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved);
+u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align);
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt);
+int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
+ u32 reserved_bot, u32 resetrved_top);
void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
int mlx4_reset(struct mlx4_dev *dev);
@@ -346,4 +384,9 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
void mlx4_handle_catas_err(struct mlx4_dev *dev);
+void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
+void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
+
+int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
+
#endif /* MLX4_H */
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
new file mode 100644
index 00000000000..11fb17c6e97
--- /dev/null
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _MLX4_EN_H_
+#define _MLX4_EN_H_
+
+#include <linux/compiler.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/inet_lro.h>
+
+#include <linux/mlx4/device.h>
+#include <linux/mlx4/qp.h>
+#include <linux/mlx4/cq.h>
+#include <linux/mlx4/srq.h>
+#include <linux/mlx4/doorbell.h>
+
+#include "en_port.h"
+
+#define DRV_NAME "mlx4_en"
+#define DRV_VERSION "1.4.0"
+#define DRV_RELDATE "Sep 2008"
+
+
+#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
+
+#define mlx4_dbg(mlevel, priv, format, arg...) \
+ if (NETIF_MSG_##mlevel & priv->msg_enable) \
+ printk(KERN_DEBUG "%s %s: " format , DRV_NAME ,\
+ (&priv->mdev->pdev->dev)->bus_id , ## arg)
+
+#define mlx4_err(mdev, format, arg...) \
+ printk(KERN_ERR "%s %s: " format , DRV_NAME ,\
+ (&mdev->pdev->dev)->bus_id , ## arg)
+#define mlx4_info(mdev, format, arg...) \
+ printk(KERN_INFO "%s %s: " format , DRV_NAME ,\
+ (&mdev->pdev->dev)->bus_id , ## arg)
+#define mlx4_warn(mdev, format, arg...) \
+ printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\
+ (&mdev->pdev->dev)->bus_id , ## arg)
+
+/*
+ * Device constants
+ */
+
+
+#define MLX4_EN_PAGE_SHIFT 12
+#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
+#define MAX_TX_RINGS 16
+#define MAX_RX_RINGS 16
+#define MAX_RSS_MAP_SIZE 64
+#define RSS_FACTOR 2
+#define TXBB_SIZE 64
+#define HEADROOM (2048 / TXBB_SIZE + 1)
+#define MAX_LSO_HDR_SIZE 92
+#define STAMP_STRIDE 64
+#define STAMP_DWORDS (STAMP_STRIDE / 4)
+#define STAMP_SHIFT 31
+#define STAMP_VAL 0x7fffffff
+#define STATS_DELAY (HZ / 4)
+
+/* Typical TSO descriptor with 16 gather entries is 352 bytes... */
+#define MAX_DESC_SIZE 512
+#define MAX_DESC_TXBBS (MAX_DESC_SIZE / TXBB_SIZE)
+
+/*
+ * OS related constants and tunables
+ */
+
+#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ)
+
+#define MLX4_EN_ALLOC_ORDER 2
+#define MLX4_EN_ALLOC_SIZE (PAGE_SIZE << MLX4_EN_ALLOC_ORDER)
+
+#define MLX4_EN_MAX_LRO_DESCRIPTORS 32
+
+/* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU
+ * and 4K allocations) */
+enum {
+ FRAG_SZ0 = 512 - NET_IP_ALIGN,
+ FRAG_SZ1 = 1024,
+ FRAG_SZ2 = 4096,
+ FRAG_SZ3 = MLX4_EN_ALLOC_SIZE
+};
+#define MLX4_EN_MAX_RX_FRAGS 4
+
+/* Minimum ring size for our page-allocation sceme to work */
+#define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES)
+#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
+
+#define MLX4_EN_TX_RING_NUM 9
+#define MLX4_EN_DEF_TX_RING_SIZE 1024
+#define MLX4_EN_DEF_RX_RING_SIZE 1024
+
+/* Target number of bytes to coalesce with interrupt moderation */
+#define MLX4_EN_RX_COAL_TARGET 0x20000
+#define MLX4_EN_RX_COAL_TIME 0x10
+
+#define MLX4_EN_TX_COAL_PKTS 5
+#define MLX4_EN_TX_COAL_TIME 0x80
+
+#define MLX4_EN_RX_RATE_LOW 400000
+#define MLX4_EN_RX_COAL_TIME_LOW 0
+#define MLX4_EN_RX_RATE_HIGH 450000
+#define MLX4_EN_RX_COAL_TIME_HIGH 128
+#define MLX4_EN_RX_SIZE_THRESH 1024
+#define MLX4_EN_RX_RATE_THRESH (1000000 / MLX4_EN_RX_COAL_TIME_HIGH)
+#define MLX4_EN_SAMPLE_INTERVAL 0
+
+#define MLX4_EN_AUTO_CONF 0xffff
+
+#define MLX4_EN_DEF_RX_PAUSE 1
+#define MLX4_EN_DEF_TX_PAUSE 1
+
+/* Interval between sucessive polls in the Tx routine when polling is used
+ instead of interrupts (in per-core Tx rings) - should be power of 2 */
+#define MLX4_EN_TX_POLL_MODER 16
+#define MLX4_EN_TX_POLL_TIMEOUT (HZ / 4)
+
+#define ETH_LLC_SNAP_SIZE 8
+
+#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN)
+#define HEADER_COPY_SIZE (128 - NET_IP_ALIGN)
+
+#define MLX4_EN_MIN_MTU 46
+#define ETH_BCAST 0xffffffffffffULL
+
+#ifdef MLX4_EN_PERF_STAT
+/* Number of samples to 'average' */
+#define AVG_SIZE 128
+#define AVG_FACTOR 1024
+#define NUM_PERF_STATS NUM_PERF_COUNTERS
+
+#define INC_PERF_COUNTER(cnt) (++(cnt))
+#define ADD_PERF_COUNTER(cnt, add) ((cnt) += (add))
+#define AVG_PERF_COUNTER(cnt, sample) \
+ ((cnt) = ((cnt) * (AVG_SIZE - 1) + (sample) * AVG_FACTOR) / AVG_SIZE)
+#define GET_PERF_COUNTER(cnt) (cnt)
+#define GET_AVG_PERF_COUNTER(cnt) ((cnt) / AVG_FACTOR)
+
+#else
+
+#define NUM_PERF_STATS 0
+#define INC_PERF_COUNTER(cnt) do {} while (0)
+#define ADD_PERF_COUNTER(cnt, add) do {} while (0)
+#define AVG_PERF_COUNTER(cnt, sample) do {} while (0)
+#define GET_PERF_COUNTER(cnt) (0)
+#define GET_AVG_PERF_COUNTER(cnt) (0)
+#endif /* MLX4_EN_PERF_STAT */
+
+/*
+ * Configurables
+ */
+
+enum cq_type {
+ RX = 0,
+ TX = 1,
+};
+
+
+/*
+ * Useful macros
+ */
+#define ROUNDUP_LOG2(x) ilog2(roundup_pow_of_two(x))
+#define XNOR(x, y) (!(x) == !(y))
+#define ILLEGAL_MAC(addr) (addr == 0xffffffffffffULL || addr == 0x0)
+
+
+struct mlx4_en_tx_info {
+ struct sk_buff *skb;
+ u32 nr_txbb;
+ u8 linear;
+ u8 data_offset;
+};
+
+
+#define MLX4_EN_BIT_DESC_OWN 0x80000000
+#define CTRL_SIZE sizeof(struct mlx4_wqe_ctrl_seg)
+#define MLX4_EN_MEMTYPE_PAD 0x100
+#define DS_SIZE sizeof(struct mlx4_wqe_data_seg)
+
+
+struct mlx4_en_tx_desc {
+ struct mlx4_wqe_ctrl_seg ctrl;
+ union {
+ struct mlx4_wqe_data_seg data; /* at least one data segment */
+ struct mlx4_wqe_lso_seg lso;
+ struct mlx4_wqe_inline_seg inl;
+ };
+};
+
+#define MLX4_EN_USE_SRQ 0x01000000
+
+struct mlx4_en_rx_alloc {
+ struct page *page;
+ u16 offset;
+};
+
+struct mlx4_en_tx_ring {
+ struct mlx4_hwq_resources wqres;
+ u32 size ; /* number of TXBBs */
+ u32 size_mask;
+ u16 stride;
+ u16 cqn; /* index of port CQ associated with this ring */
+ u32 prod;
+ u32 cons;
+ u32 buf_size;
+ u32 doorbell_qpn;
+ void *buf;
+ u16 poll_cnt;
+ int blocked;
+ struct mlx4_en_tx_info *tx_info;
+ u8 *bounce_buf;
+ u32 last_nr_txbb;
+ struct mlx4_qp qp;
+ struct mlx4_qp_context context;
+ int qpn;
+ enum mlx4_qp_state qp_state;
+ struct mlx4_srq dummy;
+ unsigned long bytes;
+ unsigned long packets;
+ spinlock_t comp_lock;
+};
+
+struct mlx4_en_rx_desc {
+ struct mlx4_wqe_srq_next_seg next;
+ /* actual number of entries depends on rx ring stride */
+ struct mlx4_wqe_data_seg data[0];
+};
+
+struct mlx4_en_rx_ring {
+ struct mlx4_srq srq;
+ struct mlx4_hwq_resources wqres;
+ struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
+ struct net_lro_mgr lro;
+ u32 size ; /* number of Rx descs*/
+ u32 actual_size;
+ u32 size_mask;
+ u16 stride;
+ u16 log_stride;
+ u16 cqn; /* index of port CQ associated with this ring */
+ u32 prod;
+ u32 cons;
+ u32 buf_size;
+ int need_refill;
+ int full;
+ void *buf;
+ void *rx_info;
+ unsigned long bytes;
+ unsigned long packets;
+};
+
+
+static inline int mlx4_en_can_lro(__be16 status)
+{
+ return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
+ MLX4_CQE_STATUS_IPV4F |
+ MLX4_CQE_STATUS_IPV6 |
+ MLX4_CQE_STATUS_IPV4OPT |
+ MLX4_CQE_STATUS_TCP |
+ MLX4_CQE_STATUS_UDP |
+ MLX4_CQE_STATUS_IPOK)) ==
+ cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
+ MLX4_CQE_STATUS_IPOK |
+ MLX4_CQE_STATUS_TCP);
+}
+
+struct mlx4_en_cq {
+ struct mlx4_cq mcq;
+ struct mlx4_hwq_resources wqres;
+ int ring;
+ spinlock_t lock;
+ struct net_device *dev;
+ struct napi_struct napi;
+ /* Per-core Tx cq processing support */
+ struct timer_list timer;
+ int size;
+ int buf_size;
+ unsigned vector;
+ enum cq_type is_tx;
+ u16 moder_time;
+ u16 moder_cnt;
+ int armed;
+ struct mlx4_cqe *buf;
+#define MLX4_EN_OPCODE_ERROR 0x1e
+};
+
+struct mlx4_en_port_profile {
+ u32 flags;
+ u32 tx_ring_num;
+ u32 rx_ring_num;
+ u32 tx_ring_size;
+ u32 rx_ring_size;
+};
+
+struct mlx4_en_profile {
+ int rss_xor;
+ int num_lro;
+ u8 rss_mask;
+ u32 active_ports;
+ u32 small_pkt_int;
+ int rx_moder_cnt;
+ int rx_moder_time;
+ int auto_moder;
+ u8 rx_pause;
+ u8 rx_ppp;
+ u8 tx_pause;
+ u8 tx_ppp;
+ u8 no_reset;
+ struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
+};
+
+struct mlx4_en_dev {
+ struct mlx4_dev *dev;
+ struct pci_dev *pdev;
+ struct mutex state_lock;
+ struct net_device *pndev[MLX4_MAX_PORTS + 1];
+ u32 port_cnt;
+ bool device_up;
+ struct mlx4_en_profile profile;
+ u32 LSO_support;
+ struct workqueue_struct *workqueue;
+ struct device *dma_device;
+ void __iomem *uar_map;
+ struct mlx4_uar priv_uar;
+ struct mlx4_mr mr;
+ u32 priv_pdn;
+ spinlock_t uar_lock;
+};
+
+
+struct mlx4_en_rss_map {
+ int size;
+ int base_qpn;
+ u16 map[MAX_RSS_MAP_SIZE];
+ struct mlx4_qp qps[MAX_RSS_MAP_SIZE];
+ enum mlx4_qp_state state[MAX_RSS_MAP_SIZE];
+ struct mlx4_qp indir_qp;
+ enum mlx4_qp_state indir_state;
+};
+
+struct mlx4_en_rss_context {
+ __be32 base_qpn;
+ __be32 default_qpn;
+ u16 reserved;
+ u8 hash_fn;
+ u8 flags;
+ __be32 rss_key[10];
+};
+
+struct mlx4_en_pkt_stats {
+ unsigned long broadcast;
+ unsigned long rx_prio[8];
+ unsigned long tx_prio[8];
+#define NUM_PKT_STATS 17
+};
+
+struct mlx4_en_port_stats {
+ unsigned long lro_aggregated;
+ unsigned long lro_flushed;
+ unsigned long lro_no_desc;
+ unsigned long tso_packets;
+ unsigned long queue_stopped;
+ unsigned long wake_queue;
+ unsigned long tx_timeout;
+ unsigned long rx_alloc_failed;
+ unsigned long rx_chksum_good;
+ unsigned long rx_chksum_none;
+ unsigned long tx_chksum_offload;
+#define NUM_PORT_STATS 11
+};
+
+struct mlx4_en_perf_stats {
+ u32 tx_poll;
+ u64 tx_pktsz_avg;
+ u32 inflight_avg;
+ u16 tx_coal_avg;
+ u16 rx_coal_avg;
+ u32 napi_quota;
+#define NUM_PERF_COUNTERS 6
+};
+
+struct mlx4_en_frag_info {
+ u16 frag_size;
+ u16 frag_prefix_size;
+ u16 frag_stride;
+ u16 frag_align;
+ u16 last_offset;
+
+};
+
+struct mlx4_en_priv {
+ struct mlx4_en_dev *mdev;
+ struct mlx4_en_port_profile *prof;
+ struct net_device *dev;
+ struct vlan_group *vlgrp;
+ struct net_device_stats stats;
+ struct net_device_stats ret_stats;
+ spinlock_t stats_lock;
+
+ unsigned long last_moder_packets;
+ unsigned long last_moder_tx_packets;
+ unsigned long last_moder_bytes;
+ unsigned long last_moder_jiffies;
+ int last_moder_time;
+ u16 rx_usecs;
+ u16 rx_frames;
+ u16 tx_usecs;
+ u16 tx_frames;
+ u32 pkt_rate_low;
+ u16 rx_usecs_low;
+ u32 pkt_rate_high;
+ u16 rx_usecs_high;
+ u16 sample_interval;
+ u16 adaptive_rx_coal;
+ u32 msg_enable;
+
+ struct mlx4_hwq_resources res;
+ int link_state;
+ int last_link_state;
+ bool port_up;
+ int port;
+ int registered;
+ int allocated;
+ int stride;
+ int rx_csum;
+ u64 mac;
+ int mac_index;
+ unsigned max_mtu;
+ int base_qpn;
+
+ struct mlx4_en_rss_map rss_map;
+ u16 tx_prio_map[8];
+ u32 flags;
+#define MLX4_EN_FLAG_PROMISC 0x1
+ u32 tx_ring_num;
+ u32 rx_ring_num;
+ u32 rx_skb_size;
+ struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS];
+ u16 num_frags;
+ u16 log_rx_info;
+
+ struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
+ struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
+ struct mlx4_en_cq tx_cq[MAX_TX_RINGS];
+ struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
+ struct work_struct mcast_task;
+ struct work_struct mac_task;
+ struct delayed_work refill_task;
+ struct work_struct watchdog_task;
+ struct work_struct linkstate_task;
+ struct delayed_work stats_task;
+ struct mlx4_en_perf_stats pstats;
+ struct mlx4_en_pkt_stats pkstats;
+ struct mlx4_en_port_stats port_stats;
+ struct dev_mc_list *mc_list;
+ struct mlx4_en_stat_out_mbox hw_stats;
+};
+
+
+void mlx4_en_destroy_netdev(struct net_device *dev);
+int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ struct mlx4_en_port_profile *prof);
+
+int mlx4_en_get_profile(struct mlx4_en_dev *mdev);
+
+int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+ int entries, int ring, enum cq_type mode);
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+
+void mlx4_en_poll_tx_cq(unsigned long data);
+void mlx4_en_tx_irq(struct mlx4_cq *mcq);
+int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
+
+int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring,
+ u32 size, u16 stride);
+void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring);
+int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring,
+ int cq, int srqn);
+void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring);
+
+int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring,
+ u32 size, u16 stride);
+void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring);
+int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv);
+void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring);
+int mlx4_en_process_rx_cq(struct net_device *dev,
+ struct mlx4_en_cq *cq,
+ int budget);
+int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget);
+void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
+ int is_tx, int rss, int qpn, int cqn, int srqn,
+ struct mlx4_qp_context *context);
+int mlx4_en_map_buffer(struct mlx4_buf *buf);
+void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
+
+void mlx4_en_calc_rx_buf(struct net_device *dev);
+void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
+ struct mlx4_en_rss_map *rss_map,
+ int num_entries, int num_rings);
+void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num);
+int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
+void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
+int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
+void mlx4_en_rx_refill(struct work_struct *work);
+void mlx4_en_rx_irq(struct mlx4_cq *mcq);
+
+int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp);
+int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
+ u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
+int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
+ u8 promisc);
+
+int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+
+/*
+ * Globals
+ */
+extern const struct ethtool_ops mlx4_en_ethtool_ops;
+#endif
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index d1dd5b48dbd..0caf74cae8b 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -461,7 +461,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev)
int err;
err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts,
- ~0, dev->caps.reserved_mrws);
+ ~0, dev->caps.reserved_mrws, 0);
if (err)
return err;
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c
index aa616892d09..26d1a7a9e37 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/mlx4/pd.c
@@ -62,7 +62,7 @@ int mlx4_init_pd_table(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds,
- (1 << 24) - 1, dev->caps.reserved_pds);
+ (1 << 24) - 1, dev->caps.reserved_pds, 0);
}
void mlx4_cleanup_pd_table(struct mlx4_dev *dev)
@@ -100,7 +100,7 @@ int mlx4_init_uar_table(struct mlx4_dev *dev)
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));
+ max(128, dev->caps.reserved_uars), 0);
}
void mlx4_cleanup_uar_table(struct mlx4_dev *dev)
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
new file mode 100644
index 00000000000..e2fdab42c4c
--- /dev/null
+++ b/drivers/net/mlx4/port.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/errno.h>
+#include <linux/if_ether.h>
+
+#include <linux/mlx4/cmd.h>
+
+#include "mlx4.h"
+
+#define MLX4_MAC_VALID (1ull << 63)
+#define MLX4_MAC_MASK 0xffffffffffffULL
+
+#define MLX4_VLAN_VALID (1u << 31)
+#define MLX4_VLAN_MASK 0xfff
+
+void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
+{
+ int i;
+
+ mutex_init(&table->mutex);
+ for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
+ table->entries[i] = 0;
+ table->refs[i] = 0;
+ }
+ table->max = 1 << dev->caps.log_num_macs;
+ table->total = 0;
+}
+
+void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
+{
+ int i;
+
+ mutex_init(&table->mutex);
+ for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
+ table->entries[i] = 0;
+ table->refs[i] = 0;
+ }
+ table->max = 1 << dev->caps.log_num_vlans;
+ table->total = 0;
+}
+
+static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
+ __be64 *entries)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ u32 in_mod;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE);
+
+ in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port;
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
+int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
+{
+ struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
+ int i, err = 0;
+ int free = -1;
+
+ mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
+ mutex_lock(&table->mutex);
+ for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
+ if (free < 0 && !table->refs[i]) {
+ free = i;
+ continue;
+ }
+
+ if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
+ /* MAC already registered, increase refernce count */
+ *index = i;
+ ++table->refs[i];
+ goto out;
+ }
+ }
+ mlx4_dbg(dev, "Free MAC index is %d\n", free);
+
+ if (table->total == table->max) {
+ /* No free mac entries */
+ err = -ENOSPC;
+ goto out;
+ }
+
+ /* Register new MAC */
+ table->refs[free] = 1;
+ table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID);
+
+ err = mlx4_set_port_mac_table(dev, port, table->entries);
+ if (unlikely(err)) {
+ mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac);
+ table->refs[free] = 0;
+ table->entries[free] = 0;
+ goto out;
+ }
+
+ *index = free;
+ ++table->total;
+out:
+ mutex_unlock(&table->mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_register_mac);
+
+void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index)
+{
+ struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
+
+ mutex_lock(&table->mutex);
+ if (!table->refs[index]) {
+ mlx4_warn(dev, "No MAC entry for index %d\n", index);
+ goto out;
+ }
+ if (--table->refs[index]) {
+ mlx4_warn(dev, "Have more references for index %d,"
+ "no need to modify MAC table\n", index);
+ goto out;
+ }
+ table->entries[index] = 0;
+ mlx4_set_port_mac_table(dev, port, table->entries);
+ --table->total;
+out:
+ mutex_unlock(&table->mutex);
+}
+EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
+
+static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
+ __be32 *entries)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ u32 in_mod;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE);
+ in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port;
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+
+ return err;
+}
+
+int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
+{
+ struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
+ int i, err = 0;
+ int free = -1;
+
+ mutex_lock(&table->mutex);
+ for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
+ if (free < 0 && (table->refs[i] == 0)) {
+ free = i;
+ continue;
+ }
+
+ if (table->refs[i] &&
+ (vlan == (MLX4_VLAN_MASK &
+ be32_to_cpu(table->entries[i])))) {
+ /* Vlan already registered, increase refernce count */
+ *index = i;
+ ++table->refs[i];
+ goto out;
+ }
+ }
+
+ if (table->total == table->max) {
+ /* No free vlan entries */
+ err = -ENOSPC;
+ goto out;
+ }
+
+ /* Register new MAC */
+ table->refs[free] = 1;
+ table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
+
+ err = mlx4_set_port_vlan_table(dev, port, table->entries);
+ if (unlikely(err)) {
+ mlx4_warn(dev, "Failed adding vlan: %u\n", vlan);
+ table->refs[free] = 0;
+ table->entries[free] = 0;
+ goto out;
+ }
+
+ *index = free;
+ ++table->total;
+out:
+ mutex_unlock(&table->mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_register_vlan);
+
+void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
+{
+ struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
+
+ if (index < MLX4_VLAN_REGULAR) {
+ mlx4_warn(dev, "Trying to free special vlan index %d\n", index);
+ return;
+ }
+
+ mutex_lock(&table->mutex);
+ if (!table->refs[index]) {
+ mlx4_warn(dev, "No vlan entry for index %d\n", index);
+ goto out;
+ }
+ if (--table->refs[index]) {
+ mlx4_dbg(dev, "Have more references for index %d,"
+ "no need to modify vlan table\n", index);
+ goto out;
+ }
+ table->entries[index] = 0;
+ mlx4_set_port_vlan_table(dev, port, table->entries);
+ --table->total;
+out:
+ mutex_unlock(&table->mutex);
+}
+EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
+
+int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+ u8 is_eth = dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ memset(mailbox->buf, 0, 256);
+ if (is_eth) {
+ ((u8 *) mailbox->buf)[3] = 6;
+ ((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15);
+ ((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15);
+ }
+ err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index c49a86044bf..1c565ef8d17 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -147,19 +147,42 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
}
EXPORT_SYMBOL_GPL(mlx4_qp_modify);
-int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp)
+int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_qp_table *qp_table = &priv->qp_table;
+ int qpn;
+
+ qpn = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align);
+ if (qpn == -1)
+ return -ENOMEM;
+
+ *base = qpn;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
+
+void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_qp_table *qp_table = &priv->qp_table;
+ if (base_qpn < dev->caps.sqp_start + 8)
+ return;
+
+ mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
+}
+EXPORT_SYMBOL_GPL(mlx4_qp_release_range);
+
+int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_qp_table *qp_table = &priv->qp_table;
int err;
- if (sqpn)
- qp->qpn = sqpn;
- else {
- qp->qpn = mlx4_bitmap_alloc(&qp_table->bitmap);
- if (qp->qpn == -1)
- return -ENOMEM;
- }
+ if (!qpn)
+ return -EINVAL;
+
+ qp->qpn = qpn;
err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn);
if (err)
@@ -208,9 +231,6 @@ err_put_qp:
mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
err_out:
- if (!sqpn)
- mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
-
return err;
}
EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
@@ -239,9 +259,6 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
-
- if (qp->qpn >= dev->caps.sqp_start + 8)
- mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
}
EXPORT_SYMBOL_GPL(mlx4_qp_free);
@@ -255,6 +272,7 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
{
struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
int err;
+ int reserved_from_top = 0;
spin_lock_init(&qp_table->lock);
INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC);
@@ -264,9 +282,40 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
* block of special QPs must be aligned to a multiple of 8, so
* round up.
*/
- dev->caps.sqp_start = ALIGN(dev->caps.reserved_qps, 8);
+ dev->caps.sqp_start =
+ ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
+
+ {
+ int sort[MLX4_NUM_QP_REGION];
+ int i, j, tmp;
+ int last_base = dev->caps.num_qps;
+
+ for (i = 1; i < MLX4_NUM_QP_REGION; ++i)
+ sort[i] = i;
+
+ for (i = MLX4_NUM_QP_REGION; i > 0; --i) {
+ for (j = 2; j < i; ++j) {
+ if (dev->caps.reserved_qps_cnt[sort[j]] >
+ dev->caps.reserved_qps_cnt[sort[j - 1]]) {
+ tmp = sort[j];
+ sort[j] = sort[j - 1];
+ sort[j - 1] = tmp;
+ }
+ }
+ }
+
+ for (i = 1; i < MLX4_NUM_QP_REGION; ++i) {
+ last_base -= dev->caps.reserved_qps_cnt[sort[i]];
+ dev->caps.reserved_qps_base[sort[i]] = last_base;
+ reserved_from_top +=
+ dev->caps.reserved_qps_cnt[sort[i]];
+ }
+
+ }
+
err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
- (1 << 24) - 1, dev->caps.sqp_start + 8);
+ (1 << 23) - 1, dev->caps.sqp_start + 8,
+ reserved_from_top);
if (err)
return err;
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c
index 533eb6db24b..fe9f218691f 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/mlx4/srq.c
@@ -245,7 +245,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev)
INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC);
err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs,
- dev->caps.num_srqs - 1, dev->caps.reserved_srqs);
+ dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0);
if (err)
return err;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index a9aebad5265..b1556b2e404 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.4.3-1.369"
+#define MYRI10GE_VERSION_STR "1.4.3-1.371"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -2497,6 +2497,10 @@ static int myri10ge_open(struct net_device *dev)
return 0;
abort_with_rings:
+ while (slice) {
+ slice--;
+ napi_disable(&mgp->ss[slice].napi);
+ }
for (i = 0; i < mgp->num_slices; i++)
myri10ge_free_rings(&mgp->ss[i]);
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 38116f9d416..ba2e1c5b6bc 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -1375,7 +1375,6 @@ struct ql_adapter {
spinlock_t adapter_lock;
spinlock_t hw_lock;
spinlock_t stats_lock;
- spinlock_t legacy_lock; /* used for maintaining legacy intr sync */
/* PCI Bus Relative Register Addresses */
void __iomem *reg_base;
@@ -1399,8 +1398,6 @@ struct ql_adapter {
struct msix_entry *msi_x_entry;
struct intr_context intr_context[MAX_RX_RINGS];
- int (*legacy_check) (struct ql_adapter *);
-
int tx_ring_count; /* One per online CPU. */
u32 rss_ring_first_cq_id;/* index of first inbound (rss) rx_ring */
u32 rss_ring_count; /* One per online CPU. */
@@ -1502,7 +1499,7 @@ void ql_mpi_work(struct work_struct *work);
void ql_mpi_reset_work(struct work_struct *work);
int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit);
void ql_queue_asic_error(struct ql_adapter *qdev);
-void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr);
+u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr);
void ql_set_ethtool_ops(struct net_device *ndev);
int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data);
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 4b2caa6b7ac..b83a9c9b6a9 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -577,41 +577,53 @@ static void ql_disable_interrupts(struct ql_adapter *qdev)
* incremented everytime we queue a worker and decremented everytime
* a worker finishes. Once it hits zero we enable the interrupt.
*/
-void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
+ u32 var = 0;
+ unsigned long hw_flags = 0;
+ struct intr_context *ctx = qdev->intr_context + intr;
+
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) {
+ /* Always enable if we're MSIX multi interrupts and
+ * it's not the default (zeroeth) interrupt.
+ */
ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_en_mask);
- else {
- if (qdev->legacy_check)
- spin_lock(&qdev->legacy_lock);
- if (atomic_dec_and_test(&qdev->intr_context[intr].irq_cnt)) {
- QPRINTK(qdev, INTR, ERR, "Enabling interrupt %d.\n",
- intr);
- ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_en_mask);
- } else {
- QPRINTK(qdev, INTR, ERR,
- "Skip enable, other queue(s) are active.\n");
- }
- if (qdev->legacy_check)
- spin_unlock(&qdev->legacy_lock);
+ ctx->intr_en_mask);
+ var = ql_read32(qdev, STS);
+ return var;
}
+
+ spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ if (atomic_dec_and_test(&ctx->irq_cnt)) {
+ ql_write32(qdev, INTR_EN,
+ ctx->intr_en_mask);
+ var = ql_read32(qdev, STS);
+ }
+ spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+ return var;
}
static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
u32 var = 0;
+ unsigned long hw_flags;
+ struct intr_context *ctx;
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
- goto exit;
- else if (!atomic_read(&qdev->intr_context[intr].irq_cnt)) {
+ /* HW disables for us if we're MSIX multi interrupts and
+ * it's not the default (zeroeth) interrupt.
+ */
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr))
+ return 0;
+
+ ctx = qdev->intr_context + intr;
+ spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ if (!atomic_read(&ctx->irq_cnt)) {
ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_dis_mask);
+ ctx->intr_dis_mask);
var = ql_read32(qdev, STS);
}
- atomic_inc(&qdev->intr_context[intr].irq_cnt);
-exit:
+ atomic_inc(&ctx->irq_cnt);
+ spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
return var;
}
@@ -623,7 +635,9 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
* and enables only if the result is zero.
* So we precharge it here.
*/
- atomic_set(&qdev->intr_context[i].irq_cnt, 1);
+ if (unlikely(!test_bit(QL_MSIX_ENABLED, &qdev->flags) ||
+ i == 0))
+ atomic_set(&qdev->intr_context[i].irq_cnt, 1);
ql_enable_completion_interrupt(qdev, i);
}
@@ -1725,19 +1739,6 @@ static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-/* We check here to see if we're already handling a legacy
- * interrupt. If we are, then it must belong to another
- * chip with which we're sharing the interrupt line.
- */
-int ql_legacy_check(struct ql_adapter *qdev)
-{
- int err;
- spin_lock(&qdev->legacy_lock);
- err = atomic_read(&qdev->intr_context[0].irq_cnt);
- spin_unlock(&qdev->legacy_lock);
- return err;
-}
-
/* This handles a fatal error, MPI activity, and the default
* rx_ring in an MSI-X multiple vector environment.
* In MSI/Legacy environment it also process the rest of
@@ -1752,12 +1753,15 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
int i;
int work_done = 0;
- if (qdev->legacy_check && qdev->legacy_check(qdev)) {
- QPRINTK(qdev, INTR, INFO, "Already busy, not our interrupt.\n");
- return IRQ_NONE; /* Not our interrupt */
+ spin_lock(&qdev->hw_lock);
+ if (atomic_read(&qdev->intr_context[0].irq_cnt)) {
+ QPRINTK(qdev, INTR, DEBUG, "Shared Interrupt, Not ours!\n");
+ spin_unlock(&qdev->hw_lock);
+ return IRQ_NONE;
}
+ spin_unlock(&qdev->hw_lock);
- var = ql_read32(qdev, STS);
+ var = ql_disable_completion_interrupt(qdev, intr_context->intr);
/*
* Check for fatal error.
@@ -1823,6 +1827,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
}
}
}
+ ql_enable_completion_interrupt(qdev, intr_context->intr);
return work_done ? IRQ_HANDLED : IRQ_NONE;
}
@@ -2701,8 +2706,6 @@ msi:
}
}
irq_type = LEG_IRQ;
- spin_lock_init(&qdev->legacy_lock);
- qdev->legacy_check = ql_legacy_check;
QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n");
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index c821da21d8e..4b7cb389dc4 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -81,6 +81,10 @@ static const int multicast_filter_limit = 32;
#define RTL8169_TX_TIMEOUT (6*HZ)
#define RTL8169_PHY_TIMEOUT (10*HZ)
+#define RTL_EEPROM_SIG cpu_to_le32(0x8129)
+#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff)
+#define RTL_EEPROM_SIG_ADDR 0x0000
+
/* write/read MMIO register */
#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
@@ -1911,74 +1915,6 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
}
}
-static int rtl_eeprom_read(struct pci_dev *pdev, int cap, int addr, __le32 *val)
-{
- int ret, count = 100;
- u16 status = 0;
- u32 value;
-
- ret = pci_write_config_word(pdev, cap + PCI_VPD_ADDR, addr);
- if (ret < 0)
- return ret;
-
- do {
- udelay(10);
- ret = pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &status);
- if (ret < 0)
- return ret;
- } while (!(status & PCI_VPD_ADDR_F) && --count);
-
- if (!(status & PCI_VPD_ADDR_F))
- return -ETIMEDOUT;
-
- ret = pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &value);
- if (ret < 0)
- return ret;
-
- *val = cpu_to_le32(value);
-
- return 0;
-}
-
-static void rtl_init_mac_address(struct rtl8169_private *tp,
- void __iomem *ioaddr)
-{
- struct pci_dev *pdev = tp->pci_dev;
- u8 cfg1;
- int vpd_cap;
- u8 mac[8];
- DECLARE_MAC_BUF(buf);
-
- cfg1 = RTL_R8(Config1);
- if (!(cfg1 & VPD)) {
- dprintk("VPD access not enabled, enabling\n");
- RTL_W8(Cfg9346, Cfg9346_Unlock);
- RTL_W8(Config1, cfg1 | VPD);
- RTL_W8(Cfg9346, Cfg9346_Lock);
- }
-
- vpd_cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
- if (!vpd_cap)
- return;
-
- /* MAC address is stored in EEPROM at offset 0x0e
- * Realtek says: "The VPD address does not have to be a DWORD-aligned
- * address as defined in the PCI 2.2 Specifications, but the VPD data
- * is always consecutive 4-byte data starting from the VPD address
- * specified."
- */
- if (rtl_eeprom_read(pdev, vpd_cap, 0x000e, (__le32*)&mac[0]) < 0 ||
- rtl_eeprom_read(pdev, vpd_cap, 0x0012, (__le32*)&mac[4]) < 0) {
- dprintk("Reading MAC address from EEPROM failed\n");
- return;
- }
-
- dprintk("MAC address found in EEPROM: %s\n", print_mac(buf, mac));
-
- /* Write MAC address */
- rtl_rar_set(tp, mac);
-}
-
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -2156,8 +2092,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->mmio_addr = ioaddr;
- rtl_init_mac_address(tp, ioaddr);
-
/* Get MAC address */
for (i = 0; i < MAC_ADDR_LEN; i++)
dev->dev_addr[i] = RTL_R8(MAC0 + i);
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index b39d1cc1ef0..a24bb68887a 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1205,11 +1205,12 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
devno = 0;
ndev->dma = -1;
- ndev->irq = platform_get_irq(pdev, 0);
- if (ndev->irq < 0) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
ret = -ENODEV;
goto out_release;
}
+ ndev->irq = ret;
SET_NETDEV_DEV(ndev, &pdev->dev);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 3fe01763760..e6e3bf58a56 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -317,6 +317,7 @@ static struct mii_chip_info {
unsigned int type;
u32 feature;
} mii_chip_table[] = {
+ { "Atheros PHY AR8012", { 0x004d, 0xd020 }, LAN, 0 },
{ "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
{ "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 },
{ "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 8aa7460ef0e..f59c7772f34 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -155,23 +155,17 @@ static void PRINT_PKT(u_char *buf, int length)
/* this enables an interrupt in the interrupt mask register */
#define SMC_ENABLE_INT(lp, x) do { \
unsigned int __mask; \
- unsigned long __flags; \
- spin_lock_irqsave(&lp->lock, __flags); \
__mask = SMC_GET_INT_EN((lp)); \
__mask |= (x); \
SMC_SET_INT_EN((lp), __mask); \
- spin_unlock_irqrestore(&lp->lock, __flags); \
} while (0)
/* this disables an interrupt from the interrupt mask register */
#define SMC_DISABLE_INT(lp, x) do { \
unsigned int __mask; \
- unsigned long __flags; \
- spin_lock_irqsave(&lp->lock, __flags); \
__mask = SMC_GET_INT_EN((lp)); \
__mask &= ~(x); \
SMC_SET_INT_EN((lp), __mask); \
- spin_unlock_irqrestore(&lp->lock, __flags); \
} while (0)
/*
@@ -180,7 +174,7 @@ static void PRINT_PKT(u_char *buf, int length)
static void smc911x_reset(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
- unsigned int reg, timeout=0, resets=1;
+ unsigned int reg, timeout=0, resets=1, irq_cfg;
unsigned long flags;
DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
@@ -252,7 +246,12 @@ static void smc911x_reset(struct net_device *dev)
* Deassert IRQ for 1*10us for edge type interrupts
* and drive IRQ pin push-pull
*/
- SMC_SET_IRQ_CFG(lp, (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_);
+ irq_cfg = (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_;
+#ifdef SMC_DYNAMIC_BUS_CONFIG
+ if (lp->cfg.irq_polarity)
+ irq_cfg |= INT_CFG_IRQ_POL_;
+#endif
+ SMC_SET_IRQ_CFG(lp, irq_cfg);
/* clear anything saved */
if (lp->pending_tx_skb != NULL) {
@@ -274,6 +273,8 @@ static void smc911x_enable(struct net_device *dev)
DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
+ spin_lock_irqsave(&lp->lock, flags);
+
SMC_SET_MAC_ADDR(lp, dev->dev_addr);
/* Enable TX */
@@ -286,12 +287,10 @@ static void smc911x_enable(struct net_device *dev)
SMC_SET_FIFO_TSL(lp, 64);
SMC_SET_GPT_CFG(lp, GPT_CFG_TIMER_EN_ | 10000);
- spin_lock_irqsave(&lp->lock, flags);
SMC_GET_MAC_CR(lp, cr);
cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_;
SMC_SET_MAC_CR(lp, cr);
SMC_SET_TX_CFG(lp, TX_CFG_TX_ON_);
- spin_unlock_irqrestore(&lp->lock, flags);
/* Add 2 byte padding to start of packets */
SMC_SET_RX_CFG(lp, (2<<8) & RX_CFG_RXDOFF_);
@@ -300,9 +299,7 @@ static void smc911x_enable(struct net_device *dev)
if (cr & MAC_CR_RXEN_)
DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name);
- spin_lock_irqsave(&lp->lock, flags);
SMC_SET_MAC_CR(lp, cr | MAC_CR_RXEN_);
- spin_unlock_irqrestore(&lp->lock, flags);
/* Interrupt on every received packet */
SMC_SET_FIFO_RSA(lp, 0x01);
@@ -318,6 +315,8 @@ static void smc911x_enable(struct net_device *dev)
mask|=INT_EN_RDFO_EN_;
}
SMC_ENABLE_INT(lp, mask);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
}
/*
@@ -458,7 +457,6 @@ static void smc911x_hardware_send_pkt(struct net_device *dev)
struct sk_buff *skb;
unsigned int cmdA, cmdB, len;
unsigned char *buf;
- unsigned long flags;
DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __func__);
BUG_ON(lp->pending_tx_skb == NULL);
@@ -503,11 +501,9 @@ static void smc911x_hardware_send_pkt(struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb(skb);
#endif
- spin_lock_irqsave(&lp->lock, flags);
if (!lp->tx_throttle) {
netif_wake_queue(dev);
}
- spin_unlock_irqrestore(&lp->lock, flags);
SMC_ENABLE_INT(lp, INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_);
}
@@ -526,6 +522,8 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
dev->name, __func__);
+ spin_lock_irqsave(&lp->lock, flags);
+
BUG_ON(lp->pending_tx_skb != NULL);
free = SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TDFREE_;
@@ -535,12 +533,10 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) {
DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n",
dev->name, free);
- spin_lock_irqsave(&lp->lock, flags);
/* Reenable when at least 1 packet of size MTU present */
SMC_SET_FIFO_TDA(lp, (SMC911X_TX_FIFO_LOW_THRESHOLD)/64);
lp->tx_throttle = 1;
netif_stop_queue(dev);
- spin_unlock_irqrestore(&lp->lock, flags);
}
/* Drop packets when we run out of space in TX FIFO
@@ -556,6 +552,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp->pending_tx_skb = NULL;
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
+ spin_unlock_irqrestore(&lp->lock, flags);
dev_kfree_skb(skb);
return 0;
}
@@ -565,7 +562,6 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* If the DMA is already running then defer this packet Tx until
* the DMA IRQ starts it
*/
- spin_lock_irqsave(&lp->lock, flags);
if (lp->txdma_active) {
DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name);
lp->pending_tx_skb = skb;
@@ -576,11 +572,11 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name);
lp->txdma_active = 1;
}
- spin_unlock_irqrestore(&lp->lock, flags);
}
#endif
lp->pending_tx_skb = skb;
smc911x_hardware_send_pkt(dev);
+ spin_unlock_irqrestore(&lp->lock, flags);
return 0;
}
@@ -1242,7 +1238,7 @@ smc911x_rx_dma_irq(int dma, void *data)
netif_rx(skb);
spin_lock_irqsave(&lp->lock, flags);
- pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16;
+ pkts = (SMC_GET_RX_FIFO_INF(lp) & RX_FIFO_INF_RXSUSED_) >> 16;
if (pkts != 0) {
smc911x_rcv(dev);
}else {
@@ -2054,7 +2050,7 @@ err_out:
*/
static int smc911x_drv_probe(struct platform_device *pdev)
{
- struct smc91x_platdata *pd = pdev->dev.platform_data;
+ struct smc911x_platdata *pd = pdev->dev.platform_data;
struct net_device *ndev;
struct resource *res;
struct smc911x_local *lp;
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
index bf6240f23f5..cc7d85bdfb3 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/smc911x.h
@@ -50,6 +50,10 @@
#define SMC_DYNAMIC_BUS_CONFIG
#endif
+#ifdef SMC_USE_PXA_DMA
+#define SMC_USE_DMA
+#endif
+
/* store this information for the driver.. */
struct smc911x_local {
/*
@@ -196,8 +200,6 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
#ifdef SMC_USE_PXA_DMA
-#define SMC_USE_DMA
-
/*
* Define the request and free functions
* These are unfortunately architecture specific as no generic allocation
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 38b90e7a7ed..7914867110e 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -168,7 +168,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
netif_device_detach(pegasus->net);
if (netif_msg_drv(pegasus) && printk_ratelimit())
dev_err(&pegasus->intf->dev, "%s, status %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
goto out;
}
@@ -192,7 +192,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
if (!buffer) {
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
- __FUNCTION__);
+ __func__);
return -ENOMEM;
}
memcpy(buffer, data, size);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index f972fef87c9..ee51b6a5e60 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -318,7 +318,7 @@ sbni_pci_probe( struct net_device *dev )
continue;
}
- if( pci_irq_line <= 0 || pci_irq_line >= NR_IRQS )
+ if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
printk( KERN_WARNING " WARNING: The PCI BIOS assigned "
"this PCI card to IRQ %d, which is unlikely "
"to work!.\n"
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 9b95c4049b3..0f1d6bdd51a 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -340,9 +340,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
}
/* Interrupt handling */
-static int ath5k_init(struct ath5k_softc *sc);
+static int ath5k_init(struct ath5k_softc *sc, bool is_resume);
static int ath5k_stop_locked(struct ath5k_softc *sc);
-static int ath5k_stop_hw(struct ath5k_softc *sc);
+static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
static irqreturn_t ath5k_intr(int irq, void *dev_id);
static void ath5k_tasklet_reset(unsigned long data);
@@ -646,7 +646,7 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
ath5k_led_off(sc);
- ath5k_stop_hw(sc);
+ ath5k_stop_hw(sc, true);
free_irq(pdev->irq, sc);
pci_save_state(pdev);
@@ -683,7 +683,7 @@ ath5k_pci_resume(struct pci_dev *pdev)
goto err_no_irq;
}
- err = ath5k_init(sc);
+ err = ath5k_init(sc, true);
if (err)
goto err_irq;
ath5k_led_enable(sc);
@@ -2200,12 +2200,17 @@ ath5k_beacon_config(struct ath5k_softc *sc)
\********************/
static int
-ath5k_init(struct ath5k_softc *sc)
+ath5k_init(struct ath5k_softc *sc, bool is_resume)
{
int ret;
mutex_lock(&sc->lock);
+ if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
+ goto out_ok;
+
+ __clear_bit(ATH_STAT_STARTED, sc->status);
+
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
/*
@@ -2230,12 +2235,15 @@ ath5k_init(struct ath5k_softc *sc)
if (ret)
goto done;
+ __set_bit(ATH_STAT_STARTED, sc->status);
+
/* Set ack to be sent at low bit-rates */
ath5k_hw_set_ack_bitrate_high(sc->ah, false);
mod_timer(&sc->calib_tim, round_jiffies(jiffies +
msecs_to_jiffies(ath5k_calinterval * 1000)));
+out_ok:
ret = 0;
done:
mmiowb();
@@ -2290,7 +2298,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
* stop is preempted).
*/
static int
-ath5k_stop_hw(struct ath5k_softc *sc)
+ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
{
int ret;
@@ -2321,6 +2329,9 @@ ath5k_stop_hw(struct ath5k_softc *sc)
}
}
ath5k_txbuf_free(sc, sc->bbuf);
+ if (!is_suspend)
+ __clear_bit(ATH_STAT_STARTED, sc->status);
+
mmiowb();
mutex_unlock(&sc->lock);
@@ -2718,12 +2729,12 @@ ath5k_reset_wake(struct ath5k_softc *sc)
static int ath5k_start(struct ieee80211_hw *hw)
{
- return ath5k_init(hw->priv);
+ return ath5k_init(hw->priv, false);
}
static void ath5k_stop(struct ieee80211_hw *hw)
{
- ath5k_stop_hw(hw->priv);
+ ath5k_stop_hw(hw->priv, false);
}
static int ath5k_add_interface(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
index 9d0b728928e..06d1054ca94 100644
--- a/drivers/net/wireless/ath5k/base.h
+++ b/drivers/net/wireless/ath5k/base.h
@@ -128,11 +128,12 @@ struct ath5k_softc {
size_t desc_len; /* size of TX/RX descriptors */
u16 cachelsz; /* cache line size */
- DECLARE_BITMAP(status, 4);
+ DECLARE_BITMAP(status, 5);
#define ATH_STAT_INVALID 0 /* disable hardware accesses */
#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
#define ATH_STAT_PROMISC 2
#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
+#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
unsigned int curmode; /* current phy mode */
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 50904771f29..e0512e49d6d 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -433,7 +433,7 @@ struct fw_info {
const static struct fw_info orinoco_fw[] = {
{ "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
{ "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
- { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 0x100 }
+ { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 512 }
};
/* Structure used to access fields in FW
@@ -458,7 +458,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
int ap)
{
/* Plug Data Area (PDA) */
- __le16 pda[512] = { 0 };
+ __le16 *pda;
hermes_t *hw = &priv->hw;
const struct firmware *fw_entry;
@@ -467,7 +467,11 @@ orinoco_dl_firmware(struct orinoco_private *priv,
const unsigned char *end;
const char *firmware;
struct net_device *dev = priv->ndev;
- int err;
+ int err = 0;
+
+ pda = kzalloc(fw->pda_size, GFP_KERNEL);
+ if (!pda)
+ return -ENOMEM;
if (ap)
firmware = fw->ap_fw;
@@ -478,17 +482,17 @@ orinoco_dl_firmware(struct orinoco_private *priv,
dev->name, firmware);
/* Read current plug data */
- err = hermes_read_pda(hw, pda, fw->pda_addr,
- min_t(u16, fw->pda_size, sizeof(pda)), 0);
+ err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
if (err)
- return err;
+ goto free;
err = request_firmware(&fw_entry, firmware, priv->dev);
if (err) {
printk(KERN_ERR "%s: Cannot find firmware %s\n",
dev->name, firmware);
- return -ENOENT;
+ err = -ENOENT;
+ goto free;
}
hdr = (const struct orinoco_fw_header *) fw_entry->data;
@@ -532,6 +536,9 @@ orinoco_dl_firmware(struct orinoco_private *priv,
abort:
release_firmware(fw_entry);
+
+free:
+ kfree(pda);
return err;
}
@@ -549,12 +556,12 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
int secondary)
{
hermes_t *hw = &priv->hw;
- int ret;
+ int ret = 0;
const unsigned char *ptr;
const unsigned char *first_block;
/* Plug Data Area (PDA) */
- __le16 pda[256];
+ __le16 *pda = NULL;
/* Binary block begins after the 0x1A marker */
ptr = image;
@@ -563,28 +570,33 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
/* Read the PDA from EEPROM */
if (secondary) {
- ret = hermes_read_pda(hw, pda, fw->pda_addr, sizeof(pda), 1);
+ pda = kzalloc(fw->pda_size, GFP_KERNEL);
+ if (!pda)
+ return -ENOMEM;
+
+ ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
if (ret)
- return ret;
+ goto free;
}
/* Stop the firmware, so that it can be safely rewritten */
if (priv->stop_fw) {
ret = priv->stop_fw(priv, 1);
if (ret)
- return ret;
+ goto free;
}
/* Program the adapter with new firmware */
ret = hermes_program(hw, first_block, end);
if (ret)
- return ret;
+ goto free;
/* Write the PDA to the adapter */
if (secondary) {
size_t len = hermes_blocks_length(first_block);
ptr = first_block + len;
ret = hermes_apply_pda(hw, ptr, pda);
+ kfree(pda);
if (ret)
return ret;
}
@@ -608,6 +620,10 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
return -ENODEV;
return 0;
+
+free:
+ kfree(pda);
+ return ret;
}
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 117c7d3a52b..2d022f83774 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -306,8 +306,8 @@ static int p54_convert_rev1(struct ieee80211_hw *dev,
return 0;
}
-static const char *p54_rf_chips[] = { "NULL", "Indigo?", "Duette",
- "Frisbee", "Xbow", "Longbow" };
+static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2",
+ "Frisbee", "Xbow", "Longbow", "NULL", "NULL" };
static int p54_init_xbow_synth(struct ieee80211_hw *dev);
static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
@@ -319,6 +319,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
void *tmp;
int err;
u8 *end = (u8 *)eeprom + len;
+ u16 synth;
DECLARE_MAC_BUF(mac);
wrap = (struct eeprom_pda_wrap *) eeprom;
@@ -400,8 +401,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
tmp = entry->data;
while ((u8 *)tmp < entry->data + data_len) {
struct bootrec_exp_if *exp_if = tmp;
- if (le16_to_cpu(exp_if->if_id) == 0xF)
- priv->rxhw = le16_to_cpu(exp_if->variant) & 0x07;
+ if (le16_to_cpu(exp_if->if_id) == 0xf)
+ synth = le16_to_cpu(exp_if->variant);
tmp += sizeof(struct bootrec_exp_if);
}
break;
@@ -427,22 +428,13 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
goto err;
}
- switch (priv->rxhw) {
- case 4: /* XBow */
+ priv->rxhw = synth & 0x07;
+ if (priv->rxhw == 4)
p54_init_xbow_synth(dev);
- case 1: /* Indigo? */
- case 2: /* Duette */
- dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
- case 3: /* Frisbee */
- case 5: /* Longbow */
+ if (!(synth & 0x40))
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
- break;
- default:
- printk(KERN_ERR "%s: unsupported RF-Chip\n",
- wiphy_name(dev->wiphy));
- err = -EINVAL;
- goto err;
- }
+ if (!(synth & 0x80))
+ dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
u8 perm_addr[ETH_ALEN];
diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c
new file mode 100644
index 00000000000..da42aa06a3b
--- /dev/null
+++ b/drivers/net/xtsonic.c
@@ -0,0 +1,319 @@
+/*
+ * xtsonic.c
+ *
+ * (C) 2001 - 2007 Tensilica Inc.
+ * Kevin Chea <kchea@yahoo.com>
+ * Marc Gauthier <marc@linux-xtensa.org>
+ * Chris Zankel <chris@zankel.net>
+ *
+ * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ *
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ *
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the onboard Sonic ethernet controller on the XT2000.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+
+static char xtsonic_string[] = "xtsonic";
+
+extern unsigned xtboard_nvram_valid(void);
+extern void xtboard_get_ether_addr(unsigned char *buf);
+
+#include "sonic.h"
+
+/*
+ * According to the documentation for the Sonic ethernet controller,
+ * EOBC should be 760 words (1520 bytes) for 32-bit applications, and,
+ * as such, 2 words less than the buffer size. The value for RBSIZE
+ * defined in sonic.h, however is only 1520.
+ *
+ * (Note that in 16-bit configurations, EOBC is 759 words (1518 bytes) and
+ * RBSIZE 1520 bytes)
+ */
+#undef SONIC_RBSIZE
+#define SONIC_RBSIZE 1524
+
+/*
+ * The chip provides 256 byte register space.
+ */
+#define SONIC_MEM_SIZE 0x100
+
+/*
+ * Macros to access SONIC registers
+ */
+#define SONIC_READ(reg) \
+ (0xffff & *((volatile unsigned int *)dev->base_addr+reg))
+
+#define SONIC_WRITE(reg,val) \
+ *((volatile unsigned int *)dev->base_addr+reg) = val
+
+
+/* Use 0 for production, 1 for verification, and >2 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else
+static unsigned int sonic_debug = 1;
+#endif
+
+/*
+ * We cannot use station (ethernet) address prefixes to detect the
+ * sonic controller since these are board manufacturer depended.
+ * So we check for known Silicon Revision IDs instead.
+ */
+static unsigned short known_revisions[] =
+{
+ 0x101, /* SONIC 83934 */
+ 0xffff /* end of list */
+};
+
+static int xtsonic_open(struct net_device *dev)
+{
+ if (request_irq(dev->irq,&sonic_interrupt,IRQF_DISABLED,"sonic",dev)) {
+ printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+ dev->name, dev->irq);
+ return -EAGAIN;
+ }
+ return sonic_open(dev);
+}
+
+static int xtsonic_close(struct net_device *dev)
+{
+ int err;
+ err = sonic_close(dev);
+ free_irq(dev->irq, dev);
+ return err;
+}
+
+static int __init sonic_probe1(struct net_device *dev)
+{
+ static unsigned version_printed = 0;
+ unsigned int silicon_revision;
+ struct sonic_local *lp = netdev_priv(dev);
+ unsigned int base_addr = dev->base_addr;
+ int i;
+ int err = 0;
+
+ if (!request_mem_region(base_addr, 0x100, xtsonic_string))
+ return -EBUSY;
+
+ /*
+ * get the Silicon Revision ID. If this is one of the known
+ * one assume that we found a SONIC ethernet controller at
+ * the expected location.
+ */
+ silicon_revision = SONIC_READ(SONIC_SR);
+ if (sonic_debug > 1)
+ printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
+
+ i = 0;
+ while ((known_revisions[i] != 0xffff) &&
+ (known_revisions[i] != silicon_revision))
+ i++;
+
+ if (known_revisions[i] == 0xffff) {
+ printk("SONIC ethernet controller not found (0x%4x)\n",
+ silicon_revision);
+ return -ENODEV;
+ }
+
+ if (sonic_debug && version_printed++ == 0)
+ printk(version);
+
+ /*
+ * Put the sonic into software reset, then retrieve ethernet address.
+ * Note: we are assuming that the boot-loader has initialized the cam.
+ */
+ SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+ SONIC_WRITE(SONIC_DCR,
+ SONIC_DCR_WC0|SONIC_DCR_DW|SONIC_DCR_LBR|SONIC_DCR_SBUS);
+ SONIC_WRITE(SONIC_CEP,0);
+ SONIC_WRITE(SONIC_IMR,0);
+
+ SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+ SONIC_WRITE(SONIC_CEP,0);
+
+ for (i=0; i<3; i++) {
+ unsigned int val = SONIC_READ(SONIC_CAP0-i);
+ dev->dev_addr[i*2] = val;
+ dev->dev_addr[i*2+1] = val >> 8;
+ }
+
+ /* Initialize the device structure. */
+
+ lp->dma_bitmode = SONIC_BITMODE32;
+
+ /*
+ * Allocate local private descriptor areas in uncached space.
+ * The entire structure must be located within the same 64kb segment.
+ * A simple way to ensure this is to allocate twice the
+ * size of the structure -- given that the structure is
+ * much less than 64 kB, at least one of the halves of
+ * the allocated area will be contained entirely in 64 kB.
+ * We also allocate extra space for a pointer to allow freeing
+ * this structure later on (in xtsonic_cleanup_module()).
+ */
+ lp->descriptors =
+ dma_alloc_coherent(lp->device,
+ SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ &lp->descriptors_laddr, GFP_KERNEL);
+
+ if (lp->descriptors == NULL) {
+ printk(KERN_ERR "%s: couldn't alloc DMA memory for "
+ " descriptors.\n", lp->device->bus_id);
+ goto out;
+ }
+
+ lp->cda = lp->descriptors;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+ /* get the virtual dma address */
+
+ lp->cda_laddr = lp->descriptors_laddr;
+ lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+ dev->open = xtsonic_open;
+ dev->stop = xtsonic_close;
+ dev->hard_start_xmit = sonic_send_packet;
+ dev->get_stats = sonic_get_stats;
+ dev->set_multicast_list = &sonic_multicast_list;
+ dev->tx_timeout = sonic_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ /*
+ * clear tally counter
+ */
+ SONIC_WRITE(SONIC_CRCT,0xffff);
+ SONIC_WRITE(SONIC_FAET,0xffff);
+ SONIC_WRITE(SONIC_MPT,0xffff);
+
+ return 0;
+out:
+ release_region(dev->base_addr, SONIC_MEM_SIZE);
+ return err;
+}
+
+
+/*
+ * Probe for a SONIC ethernet controller on an XT2000 board.
+ * Actually probing is superfluous but we're paranoid.
+ */
+
+int __init xtsonic_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct sonic_local *lp;
+ struct resource *resmem, *resirq;
+ int err = 0;
+
+ DECLARE_MAC_BUF(mac);
+
+ if ((resmem = platform_get_resource(pdev, IORESOURCE_MEM, 0)) == NULL)
+ return -ENODEV;
+
+ if ((resirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0)) == NULL)
+ return -ENODEV;
+
+ if ((dev = alloc_etherdev(sizeof(struct sonic_local))) == NULL)
+ return -ENOMEM;
+
+ lp = netdev_priv(dev);
+ lp->device = &pdev->dev;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ netdev_boot_setup_check(dev);
+
+ dev->base_addr = resmem->start;
+ dev->irq = resirq->start;
+
+ if ((err = sonic_probe1(dev)))
+ goto out;
+ if ((err = register_netdev(dev)))
+ goto out1;
+
+ printk("%s: SONIC ethernet @%08lx, MAC %s, IRQ %d\n", dev->name,
+ dev->base_addr, print_mac(mac, dev->dev_addr), dev->irq);
+
+ return 0;
+
+out1:
+ release_region(dev->base_addr, SONIC_MEM_SIZE);
+out:
+ free_netdev(dev);
+
+ return err;
+}
+
+MODULE_DESCRIPTION("Xtensa XT2000 SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
+MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)");
+
+#include "sonic.c"
+
+static int __devexit xtsonic_device_remove (struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct sonic_local *lp = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ dma_free_coherent(lp->device,
+ SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ lp->descriptors, lp->descriptors_laddr);
+ release_region (dev->base_addr, SONIC_MEM_SIZE);
+ free_netdev(dev);
+
+ return 0;
+}
+
+static struct platform_driver xtsonic_driver = {
+ .probe = xtsonic_probe,
+ .remove = __devexit_p(xtsonic_device_remove),
+ .driver = {
+ .name = xtsonic_string,
+ },
+};
+
+static int __init xtsonic_init(void)
+{
+ return platform_driver_register(&xtsonic_driver);
+}
+
+static void __exit xtsonic_cleanup(void)
+{
+ platform_driver_unregister(&xtsonic_driver);
+}
+
+module_init(xtsonic_init);
+module_exit(xtsonic_cleanup);
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 6a98dc8aa30..24bbef777c1 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -41,7 +41,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
info.addr = *addr;
- request_module(info.type);
+ request_module("%s", info.type);
result = i2c_new_device(adap, &info);
if (result == NULL) {
diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c
index b01eec026f6..bed0ed6dcdc 100644
--- a/drivers/of/of_spi.c
+++ b/drivers/of/of_spi.c
@@ -61,6 +61,8 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np)
spi->mode |= SPI_CPHA;
if (of_find_property(nc, "spi-cpol", NULL))
spi->mode |= SPI_CPOL;
+ if (of_find_property(nc, "spi-cs-high", NULL))
+ spi->mode |= SPI_CS_HIGH;
/* Device speed */
prop = of_get_property(nc, "spi-max-frequency", &len);
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index ed982273fb8..b55cd23ffde 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -41,7 +41,6 @@ static cpumask_t marked_cpus = CPU_MASK_NONE;
static DEFINE_SPINLOCK(task_mortuary);
static void process_task_mortuary(void);
-
/* Take ownership of the task struct and place it on the
* list for processing. Only after two full buffer syncs
* does the task eventually get freed, because by then
@@ -341,7 +340,7 @@ static void add_trace_begin(void)
* Add IBS fetch and op entries to event buffer
*/
static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,
- int in_kernel, struct mm_struct *mm)
+ struct mm_struct *mm)
{
unsigned long rip;
int i, count;
@@ -565,9 +564,11 @@ void sync_buffer(int cpu)
struct task_struct *new;
unsigned long cookie = 0;
int in_kernel = 1;
- unsigned int i;
sync_buffer_state state = sb_buffer_start;
+#ifndef CONFIG_OPROFILE_IBS
+ unsigned int i;
unsigned long available;
+#endif
mutex_lock(&buffer_mutex);
@@ -575,9 +576,13 @@ void sync_buffer(int cpu)
/* Remember, only we can modify tail_pos */
+#ifndef CONFIG_OPROFILE_IBS
available = get_slots(cpu_buf);
for (i = 0; i < available; ++i) {
+#else
+ while (get_slots(cpu_buf)) {
+#endif
struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos];
if (is_code(s->eip)) {
@@ -593,12 +598,10 @@ void sync_buffer(int cpu)
#ifdef CONFIG_OPROFILE_IBS
} else if (s->event == IBS_FETCH_BEGIN) {
state = sb_bt_start;
- add_ibs_begin(cpu_buf,
- IBS_FETCH_CODE, in_kernel, mm);
+ add_ibs_begin(cpu_buf, IBS_FETCH_CODE, mm);
} else if (s->event == IBS_OP_BEGIN) {
state = sb_bt_start;
- add_ibs_begin(cpu_buf,
- IBS_OP_CODE, in_kernel, mm);
+ add_ibs_begin(cpu_buf, IBS_OP_CODE, mm);
#endif
} else {
struct mm_struct *oldmm = mm;
@@ -628,3 +631,27 @@ void sync_buffer(int cpu)
mutex_unlock(&buffer_mutex);
}
+
+/* The function can be used to add a buffer worth of data directly to
+ * the kernel buffer. The buffer is assumed to be a circular buffer.
+ * Take the entries from index start and end at index end, wrapping
+ * at max_entries.
+ */
+void oprofile_put_buff(unsigned long *buf, unsigned int start,
+ unsigned int stop, unsigned int max)
+{
+ int i;
+
+ i = start;
+
+ mutex_lock(&buffer_mutex);
+ while (i != stop) {
+ add_event_entry(buf[i++]);
+
+ if (i >= max)
+ i = 0;
+ }
+
+ mutex_unlock(&buffer_mutex);
+}
+
diff --git a/drivers/oprofile/buffer_sync.h b/drivers/oprofile/buffer_sync.h
index 08866f6a96a..3110732c183 100644
--- a/drivers/oprofile/buffer_sync.h
+++ b/drivers/oprofile/buffer_sync.h
@@ -9,13 +9,13 @@
#ifndef OPROFILE_BUFFER_SYNC_H
#define OPROFILE_BUFFER_SYNC_H
-
+
/* add the necessary profiling hooks */
int sync_start(void);
/* remove the hooks */
void sync_stop(void);
-
+
/* sync the given CPU's buffer */
void sync_buffer(int cpu);
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index e1bd5a937f6..01d38e78cde 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -22,7 +22,7 @@
#include <linux/oprofile.h>
#include <linux/vmalloc.h>
#include <linux/errno.h>
-
+
#include "event_buffer.h"
#include "cpu_buffer.h"
#include "buffer_sync.h"
@@ -38,27 +38,40 @@ static int work_enabled;
void free_cpu_buffers(void)
{
int i;
-
- for_each_online_cpu(i) {
+
+ for_each_possible_cpu(i) {
vfree(per_cpu(cpu_buffer, i).buffer);
per_cpu(cpu_buffer, i).buffer = NULL;
}
}
+unsigned long oprofile_get_cpu_buffer_size(void)
+{
+ return fs_cpu_buffer_size;
+}
+
+void oprofile_cpu_buffer_inc_smpl_lost(void)
+{
+ struct oprofile_cpu_buffer *cpu_buf
+ = &__get_cpu_var(cpu_buffer);
+
+ cpu_buf->sample_lost_overflow++;
+}
+
int alloc_cpu_buffers(void)
{
int i;
-
+
unsigned long buffer_size = fs_cpu_buffer_size;
-
- for_each_online_cpu(i) {
+
+ for_each_possible_cpu(i) {
struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
-
+
b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size,
cpu_to_node(i));
if (!b->buffer)
goto fail;
-
+
b->last_task = NULL;
b->last_is_kernel = -1;
b->tracing = 0;
@@ -112,7 +125,7 @@ void end_cpu_work(void)
}
/* Resets the cpu buffer to a sane state. */
-void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf)
+void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf)
{
/* reset these to invalid values; the next sample
* collected will populate the buffer with proper
@@ -123,7 +136,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf)
}
/* compute number of available slots in cpu_buffer queue */
-static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
+static unsigned long nr_available_slots(struct oprofile_cpu_buffer const *b)
{
unsigned long head = b->head_pos;
unsigned long tail = b->tail_pos;
@@ -134,7 +147,7 @@ static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
return tail + (b->buffer_size - head) - 1;
}
-static void increment_head(struct oprofile_cpu_buffer * b)
+static void increment_head(struct oprofile_cpu_buffer *b)
{
unsigned long new_head = b->head_pos + 1;
@@ -149,17 +162,17 @@ static void increment_head(struct oprofile_cpu_buffer * b)
}
static inline void
-add_sample(struct oprofile_cpu_buffer * cpu_buf,
- unsigned long pc, unsigned long event)
+add_sample(struct oprofile_cpu_buffer *cpu_buf,
+ unsigned long pc, unsigned long event)
{
- struct op_sample * entry = &cpu_buf->buffer[cpu_buf->head_pos];
+ struct op_sample *entry = &cpu_buf->buffer[cpu_buf->head_pos];
entry->eip = pc;
entry->event = event;
increment_head(cpu_buf);
}
static inline void
-add_code(struct oprofile_cpu_buffer * buffer, unsigned long value)
+add_code(struct oprofile_cpu_buffer *buffer, unsigned long value)
{
add_sample(buffer, ESCAPE_CODE, value);
}
@@ -173,10 +186,10 @@ add_code(struct oprofile_cpu_buffer * buffer, unsigned long value)
* pc. We tag this in the buffer by generating kernel enter/exit
* events whenever is_kernel changes
*/
-static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
+static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
int is_kernel, unsigned long event)
{
- struct task_struct * task;
+ struct task_struct *task;
cpu_buf->sample_received++;
@@ -205,7 +218,7 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
cpu_buf->last_task = task;
add_code(cpu_buf, (unsigned long)task);
}
-
+
add_sample(cpu_buf, pc, event);
return 1;
}
@@ -222,7 +235,7 @@ static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)
return 1;
}
-static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf)
+static void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)
{
cpu_buf->tracing = 0;
}
@@ -257,21 +270,23 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
#ifdef CONFIG_OPROFILE_IBS
-#define MAX_IBS_SAMPLE_SIZE 14
-static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf,
- unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code)
+#define MAX_IBS_SAMPLE_SIZE 14
+
+void oprofile_add_ibs_sample(struct pt_regs *const regs,
+ unsigned int *const ibs_sample, int ibs_code)
{
+ int is_kernel = !user_mode(regs);
+ struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
struct task_struct *task;
cpu_buf->sample_received++;
if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) {
+ /* we can't backtrace since we lost the source of this event */
cpu_buf->sample_lost_overflow++;
- return 0;
+ return;
}
- is_kernel = !!is_kernel;
-
/* notice a switch from user->kernel or vice versa */
if (cpu_buf->last_is_kernel != is_kernel) {
cpu_buf->last_is_kernel = is_kernel;
@@ -281,7 +296,6 @@ static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf,
/* notice a task switch */
if (!is_kernel) {
task = current;
-
if (cpu_buf->last_task != task) {
cpu_buf->last_task = task;
add_code(cpu_buf, (unsigned long)task);
@@ -289,36 +303,17 @@ static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf,
}
add_code(cpu_buf, ibs_code);
- add_sample(cpu_buf, ibs[0], ibs[1]);
- add_sample(cpu_buf, ibs[2], ibs[3]);
- add_sample(cpu_buf, ibs[4], ibs[5]);
+ add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]);
+ add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]);
+ add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]);
if (ibs_code == IBS_OP_BEGIN) {
- add_sample(cpu_buf, ibs[6], ibs[7]);
- add_sample(cpu_buf, ibs[8], ibs[9]);
- add_sample(cpu_buf, ibs[10], ibs[11]);
- }
-
- return 1;
-}
-
-void oprofile_add_ibs_sample(struct pt_regs *const regs,
- unsigned int * const ibs_sample, u8 code)
-{
- int is_kernel = !user_mode(regs);
- unsigned long pc = profile_pc(regs);
-
- struct oprofile_cpu_buffer *cpu_buf =
- &per_cpu(cpu_buffer, smp_processor_id());
-
- if (!backtrace_depth) {
- log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code);
- return;
+ add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]);
+ add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]);
+ add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]);
}
- /* if log_sample() fails we can't backtrace since we lost the source
- * of this event */
- if (log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code))
+ if (backtrace_depth)
oprofile_ops.backtrace(regs, backtrace_depth);
}
@@ -363,11 +358,16 @@ void oprofile_add_trace(unsigned long pc)
*/
static void wq_sync_buffer(struct work_struct *work)
{
- struct oprofile_cpu_buffer * b =
+ struct oprofile_cpu_buffer *b =
container_of(work, struct oprofile_cpu_buffer, work.work);
if (b->cpu != smp_processor_id()) {
printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n",
smp_processor_id(), b->cpu);
+
+ if (!cpu_online(b->cpu)) {
+ cancel_delayed_work(&b->work);
+ return;
+ }
}
sync_buffer(b->cpu);
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index 9c44d004da6..d3cc26264db 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -15,9 +15,9 @@
#include <linux/workqueue.h>
#include <linux/cache.h>
#include <linux/sched.h>
-
+
struct task_struct;
-
+
int alloc_cpu_buffers(void);
void free_cpu_buffers(void);
@@ -31,15 +31,15 @@ struct op_sample {
unsigned long eip;
unsigned long event;
};
-
+
struct oprofile_cpu_buffer {
volatile unsigned long head_pos;
volatile unsigned long tail_pos;
unsigned long buffer_size;
- struct task_struct * last_task;
+ struct task_struct *last_task;
int last_is_kernel;
int tracing;
- struct op_sample * buffer;
+ struct op_sample *buffer;
unsigned long sample_received;
unsigned long sample_lost_overflow;
unsigned long backtrace_aborted;
@@ -50,7 +50,7 @@ struct oprofile_cpu_buffer {
DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
-void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
+void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf);
/* transient events for the CPU buffer -> event buffer */
#define CPU_IS_KERNEL 1
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 8d692a5c8e7..d962ba0dd87 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -19,16 +19,16 @@
#include <linux/dcookies.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
-
+
#include "oprof.h"
#include "event_buffer.h"
#include "oprofile_stats.h"
DEFINE_MUTEX(buffer_mutex);
-
+
static unsigned long buffer_opened;
static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
-static unsigned long * event_buffer;
+static unsigned long *event_buffer;
static unsigned long buffer_size;
static unsigned long buffer_watershed;
static size_t buffer_pos;
@@ -66,7 +66,7 @@ void wake_up_buffer_waiter(void)
mutex_unlock(&buffer_mutex);
}
-
+
int alloc_event_buffer(void)
{
int err = -ENOMEM;
@@ -76,13 +76,13 @@ int alloc_event_buffer(void)
buffer_size = fs_buffer_size;
buffer_watershed = fs_buffer_watershed;
spin_unlock_irqrestore(&oprofilefs_lock, flags);
-
+
if (buffer_watershed >= buffer_size)
return -EINVAL;
-
+
event_buffer = vmalloc(sizeof(unsigned long) * buffer_size);
if (!event_buffer)
- goto out;
+ goto out;
err = 0;
out:
@@ -97,8 +97,8 @@ void free_event_buffer(void)
event_buffer = NULL;
}
-
-static int event_buffer_open(struct inode * inode, struct file * file)
+
+static int event_buffer_open(struct inode *inode, struct file *file)
{
int err = -EPERM;
@@ -116,14 +116,14 @@ static int event_buffer_open(struct inode * inode, struct file * file)
file->private_data = dcookie_register();
if (!file->private_data)
goto out;
-
+
if ((err = oprofile_setup()))
goto fail;
/* NB: the actual start happens from userspace
* echo 1 >/dev/oprofile/enable
*/
-
+
return 0;
fail:
@@ -134,7 +134,7 @@ out:
}
-static int event_buffer_release(struct inode * inode, struct file * file)
+static int event_buffer_release(struct inode *inode, struct file *file)
{
oprofile_stop();
oprofile_shutdown();
@@ -146,8 +146,8 @@ static int event_buffer_release(struct inode * inode, struct file * file)
}
-static ssize_t event_buffer_read(struct file * file, char __user * buf,
- size_t count, loff_t * offset)
+static ssize_t event_buffer_read(struct file *file, char __user *buf,
+ size_t count, loff_t *offset)
{
int retval = -EINVAL;
size_t const max = buffer_size * sizeof(unsigned long);
@@ -172,18 +172,18 @@ static ssize_t event_buffer_read(struct file * file, char __user * buf,
retval = -EFAULT;
count = buffer_pos * sizeof(unsigned long);
-
+
if (copy_to_user(buf, event_buffer, count))
goto out;
retval = count;
buffer_pos = 0;
-
+
out:
mutex_unlock(&buffer_mutex);
return retval;
}
-
+
const struct file_operations event_buffer_fops = {
.open = event_buffer_open,
.release = event_buffer_release,
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 5076ed1ebd8..4e70749f8d1 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -10,13 +10,20 @@
#ifndef EVENT_BUFFER_H
#define EVENT_BUFFER_H
-#include <linux/types.h>
+#include <linux/types.h>
#include <asm/mutex.h>
-
+
int alloc_event_buffer(void);
void free_event_buffer(void);
-
+
+/**
+ * Add data to the event buffer.
+ * The data passed is free-form, but typically consists of
+ * file offsets, dcookies, context information, and ESCAPE codes.
+ */
+void add_event_entry(unsigned long data);
+
/* wake up the process sleeping on the event file */
void wake_up_buffer_waiter(void);
@@ -24,10 +31,10 @@ void wake_up_buffer_waiter(void);
#define NO_COOKIE 0UL
extern const struct file_operations event_buffer_fops;
-
+
/* mutex between sync_cpu_buffers() and the
* file reading code.
*/
extern struct mutex buffer_mutex;
-
+
#endif /* EVENT_BUFFER_H */
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index 2c645170f06..cd375907f26 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -19,7 +19,7 @@
#include "cpu_buffer.h"
#include "buffer_sync.h"
#include "oprofile_stats.h"
-
+
struct oprofile_operations oprofile_ops;
unsigned long oprofile_started;
@@ -36,7 +36,7 @@ static int timer = 0;
int oprofile_setup(void)
{
int err;
-
+
mutex_lock(&start_mutex);
if ((err = alloc_cpu_buffers()))
@@ -44,10 +44,10 @@ int oprofile_setup(void)
if ((err = alloc_event_buffer()))
goto out1;
-
+
if (oprofile_ops.setup && (err = oprofile_ops.setup()))
goto out2;
-
+
/* Note even though this starts part of the
* profiling overhead, it's necessary to prevent
* us missing task deaths and eventually oopsing
@@ -74,7 +74,7 @@ post_sync:
is_setup = 1;
mutex_unlock(&start_mutex);
return 0;
-
+
out3:
if (oprofile_ops.shutdown)
oprofile_ops.shutdown();
@@ -92,17 +92,17 @@ out:
int oprofile_start(void)
{
int err = -EINVAL;
-
+
mutex_lock(&start_mutex);
-
+
if (!is_setup)
goto out;
- err = 0;
-
+ err = 0;
+
if (oprofile_started)
goto out;
-
+
oprofile_reset_stats();
if ((err = oprofile_ops.start()))
@@ -114,7 +114,7 @@ out:
return err;
}
-
+
/* echo 0>/dev/oprofile/enable */
void oprofile_stop(void)
{
@@ -204,13 +204,13 @@ static void __exit oprofile_exit(void)
oprofile_arch_exit();
}
-
+
module_init(oprofile_init);
module_exit(oprofile_exit);
module_param_named(timer, timer, int, 0644);
MODULE_PARM_DESC(timer, "force use of timer interrupt");
-
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Levon <levon@movementarian.org>");
MODULE_DESCRIPTION("OProfile system profiler");
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h
index 18323650806..5df0c21a608 100644
--- a/drivers/oprofile/oprof.h
+++ b/drivers/oprofile/oprof.h
@@ -11,7 +11,7 @@
#define OPROF_H
int oprofile_setup(void);
-void oprofile_shutdown(void);
+void oprofile_shutdown(void);
int oprofilefs_register(void);
void oprofilefs_unregister(void);
@@ -20,20 +20,20 @@ int oprofile_start(void);
void oprofile_stop(void);
struct oprofile_operations;
-
+
extern unsigned long fs_buffer_size;
extern unsigned long fs_cpu_buffer_size;
extern unsigned long fs_buffer_watershed;
extern struct oprofile_operations oprofile_ops;
extern unsigned long oprofile_started;
extern unsigned long backtrace_depth;
-
+
struct super_block;
struct dentry;
-void oprofile_create_files(struct super_block * sb, struct dentry * root);
-void oprofile_timer_init(struct oprofile_operations * ops);
+void oprofile_create_files(struct super_block *sb, struct dentry *root);
+void oprofile_timer_init(struct oprofile_operations *ops);
int oprofile_set_backtrace(unsigned long depth);
-
+
#endif /* OPROF_H */
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index ef953ba5ab6..cc106d503ac 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -13,18 +13,18 @@
#include "event_buffer.h"
#include "oprofile_stats.h"
#include "oprof.h"
-
+
unsigned long fs_buffer_size = 131072;
unsigned long fs_cpu_buffer_size = 8192;
unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
-static ssize_t depth_read(struct file * file, char __user * buf, size_t count, loff_t * offset)
+static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
return oprofilefs_ulong_to_user(backtrace_depth, buf, count, offset);
}
-static ssize_t depth_write(struct file * file, char const __user * buf, size_t count, loff_t * offset)
+static ssize_t depth_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
{
unsigned long val;
int retval;
@@ -49,8 +49,8 @@ static const struct file_operations depth_fops = {
.write = depth_write
};
-
-static ssize_t pointer_size_read(struct file * file, char __user * buf, size_t count, loff_t * offset)
+
+static ssize_t pointer_size_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
return oprofilefs_ulong_to_user(sizeof(void *), buf, count, offset);
}
@@ -61,24 +61,24 @@ static const struct file_operations pointer_size_fops = {
};
-static ssize_t cpu_type_read(struct file * file, char __user * buf, size_t count, loff_t * offset)
+static ssize_t cpu_type_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
return oprofilefs_str_to_user(oprofile_ops.cpu_type, buf, count, offset);
}
-
-
+
+
static const struct file_operations cpu_type_fops = {
.read = cpu_type_read,
};
-
-
-static ssize_t enable_read(struct file * file, char __user * buf, size_t count, loff_t * offset)
+
+
+static ssize_t enable_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
return oprofilefs_ulong_to_user(oprofile_started, buf, count, offset);
}
-static ssize_t enable_write(struct file * file, char const __user * buf, size_t count, loff_t * offset)
+static ssize_t enable_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
{
unsigned long val;
int retval;
@@ -89,7 +89,7 @@ static ssize_t enable_write(struct file * file, char const __user * buf, size_t
retval = oprofilefs_ulong_from_user(&val, buf, count);
if (retval)
return retval;
-
+
if (val)
retval = oprofile_start();
else
@@ -100,14 +100,14 @@ static ssize_t enable_write(struct file * file, char const __user * buf, size_t
return count;
}
-
+
static const struct file_operations enable_fops = {
.read = enable_read,
.write = enable_write,
};
-static ssize_t dump_write(struct file * file, char const __user * buf, size_t count, loff_t * offset)
+static ssize_t dump_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
{
wake_up_buffer_waiter();
return count;
@@ -117,8 +117,8 @@ static ssize_t dump_write(struct file * file, char const __user * buf, size_t co
static const struct file_operations dump_fops = {
.write = dump_write,
};
-
-void oprofile_create_files(struct super_block * sb, struct dentry * root)
+
+void oprofile_create_files(struct super_block *sb, struct dentry *root)
{
oprofilefs_create_file(sb, root, "enable", &enable_fops);
oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
@@ -126,7 +126,7 @@ void oprofile_create_files(struct super_block * sb, struct dentry * root)
oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed);
oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &fs_cpu_buffer_size);
- oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops);
+ oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops);
oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops);
oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops);
oprofile_create_stats_files(sb, root);
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index f99b28e7b79..e1f6ce03705 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -11,17 +11,17 @@
#include <linux/smp.h>
#include <linux/cpumask.h>
#include <linux/threads.h>
-
+
#include "oprofile_stats.h"
#include "cpu_buffer.h"
-
+
struct oprofile_stat_struct oprofile_stats;
-
+
void oprofile_reset_stats(void)
{
- struct oprofile_cpu_buffer * cpu_buf;
+ struct oprofile_cpu_buffer *cpu_buf;
int i;
-
+
for_each_possible_cpu(i) {
cpu_buf = &per_cpu(cpu_buffer, i);
cpu_buf->sample_received = 0;
@@ -29,18 +29,18 @@ void oprofile_reset_stats(void)
cpu_buf->backtrace_aborted = 0;
cpu_buf->sample_invalid_eip = 0;
}
-
+
atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
atomic_set(&oprofile_stats.sample_lost_no_mapping, 0);
atomic_set(&oprofile_stats.event_lost_overflow, 0);
}
-void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
+void oprofile_create_stats_files(struct super_block *sb, struct dentry *root)
{
- struct oprofile_cpu_buffer * cpu_buf;
- struct dentry * cpudir;
- struct dentry * dir;
+ struct oprofile_cpu_buffer *cpu_buf;
+ struct dentry *cpudir;
+ struct dentry *dir;
char buf[10];
int i;
@@ -52,7 +52,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
cpu_buf = &per_cpu(cpu_buffer, i);
snprintf(buf, 10, "cpu%d", i);
cpudir = oprofilefs_mkdir(sb, dir, buf);
-
+
/* Strictly speaking access to these ulongs is racy,
* but we can't simply lock them, and they are
* informational only.
@@ -66,7 +66,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip",
&cpu_buf->sample_invalid_eip);
}
-
+
oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
&oprofile_stats.sample_lost_no_mm);
oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mapping",
diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h
index 6d755a633f1..3da0d08dc1f 100644
--- a/drivers/oprofile/oprofile_stats.h
+++ b/drivers/oprofile/oprofile_stats.h
@@ -11,7 +11,7 @@
#define OPROFILE_STATS_H
#include <asm/atomic.h>
-
+
struct oprofile_stat_struct {
atomic_t sample_lost_no_mm;
atomic_t sample_lost_no_mapping;
@@ -20,14 +20,14 @@ struct oprofile_stat_struct {
};
extern struct oprofile_stat_struct oprofile_stats;
-
+
/* reset all stats to zero */
void oprofile_reset_stats(void);
-
+
struct super_block;
struct dentry;
-
+
/* create the stats/ dir */
-void oprofile_create_stats_files(struct super_block * sb, struct dentry * root);
+void oprofile_create_stats_files(struct super_block *sb, struct dentry *root);
#endif /* OPROFILE_STATS_H */
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 8543cb26cf3..ddc4c59f02d 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -23,9 +23,9 @@
DEFINE_SPINLOCK(oprofilefs_lock);
-static struct inode * oprofilefs_get_inode(struct super_block * sb, int mode)
+static struct inode *oprofilefs_get_inode(struct super_block *sb, int mode)
{
- struct inode * inode = new_inode(sb);
+ struct inode *inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
@@ -44,7 +44,7 @@ static struct super_operations s_ops = {
};
-ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count, loff_t * offset)
+ssize_t oprofilefs_str_to_user(char const *str, char __user *buf, size_t count, loff_t *offset)
{
return simple_read_from_buffer(buf, count, offset, str, strlen(str));
}
@@ -52,7 +52,7 @@ ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count
#define TMPBUFSIZE 50
-ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t count, loff_t * offset)
+ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user *buf, size_t count, loff_t *offset)
{
char tmpbuf[TMPBUFSIZE];
size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
@@ -62,7 +62,7 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t co
}
-int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count)
+int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_t count)
{
char tmpbuf[TMPBUFSIZE];
unsigned long flags;
@@ -85,16 +85,16 @@ int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, siz
}
-static ssize_t ulong_read_file(struct file * file, char __user * buf, size_t count, loff_t * offset)
+static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
- unsigned long * val = file->private_data;
+ unsigned long *val = file->private_data;
return oprofilefs_ulong_to_user(*val, buf, count, offset);
}
-static ssize_t ulong_write_file(struct file * file, char const __user * buf, size_t count, loff_t * offset)
+static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset)
{
- unsigned long * value = file->private_data;
+ unsigned long *value = file->private_data;
int retval;
if (*offset)
@@ -108,7 +108,7 @@ static ssize_t ulong_write_file(struct file * file, char const __user * buf, siz
}
-static int default_open(struct inode * inode, struct file * filp)
+static int default_open(struct inode *inode, struct file *filp)
{
if (inode->i_private)
filp->private_data = inode->i_private;
@@ -129,12 +129,12 @@ static const struct file_operations ulong_ro_fops = {
};
-static struct dentry * __oprofilefs_create_file(struct super_block * sb,
- struct dentry * root, char const * name, const struct file_operations * fops,
+static struct dentry *__oprofilefs_create_file(struct super_block *sb,
+ struct dentry *root, char const *name, const struct file_operations *fops,
int perm)
{
- struct dentry * dentry;
- struct inode * inode;
+ struct dentry *dentry;
+ struct inode *inode;
dentry = d_alloc_name(root, name);
if (!dentry)
@@ -150,10 +150,10 @@ static struct dentry * __oprofilefs_create_file(struct super_block * sb,
}
-int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
- char const * name, unsigned long * val)
+int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root,
+ char const *name, unsigned long *val)
{
- struct dentry * d = __oprofilefs_create_file(sb, root, name,
+ struct dentry *d = __oprofilefs_create_file(sb, root, name,
&ulong_fops, 0644);
if (!d)
return -EFAULT;
@@ -163,10 +163,10 @@ int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
}
-int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
- char const * name, unsigned long * val)
+int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root,
+ char const *name, unsigned long *val)
{
- struct dentry * d = __oprofilefs_create_file(sb, root, name,
+ struct dentry *d = __oprofilefs_create_file(sb, root, name,
&ulong_ro_fops, 0444);
if (!d)
return -EFAULT;
@@ -176,23 +176,23 @@ int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
}
-static ssize_t atomic_read_file(struct file * file, char __user * buf, size_t count, loff_t * offset)
+static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
- atomic_t * val = file->private_data;
+ atomic_t *val = file->private_data;
return oprofilefs_ulong_to_user(atomic_read(val), buf, count, offset);
}
-
+
static const struct file_operations atomic_ro_fops = {
.read = atomic_read_file,
.open = default_open,
};
-
-int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
- char const * name, atomic_t * val)
+
+int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
+ char const *name, atomic_t *val)
{
- struct dentry * d = __oprofilefs_create_file(sb, root, name,
+ struct dentry *d = __oprofilefs_create_file(sb, root, name,
&atomic_ro_fops, 0444);
if (!d)
return -EFAULT;
@@ -201,9 +201,9 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
return 0;
}
-
-int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
- char const * name, const struct file_operations * fops)
+
+int oprofilefs_create_file(struct super_block *sb, struct dentry *root,
+ char const *name, const struct file_operations *fops)
{
if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
return -EFAULT;
@@ -211,8 +211,8 @@ int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
}
-int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
- char const * name, const struct file_operations * fops, int perm)
+int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root,
+ char const *name, const struct file_operations *fops, int perm)
{
if (!__oprofilefs_create_file(sb, root, name, fops, perm))
return -EFAULT;
@@ -220,11 +220,11 @@ int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
}
-struct dentry * oprofilefs_mkdir(struct super_block * sb,
- struct dentry * root, char const * name)
+struct dentry *oprofilefs_mkdir(struct super_block *sb,
+ struct dentry *root, char const *name)
{
- struct dentry * dentry;
- struct inode * inode;
+ struct dentry *dentry;
+ struct inode *inode;
dentry = d_alloc_name(root, name);
if (!dentry)
@@ -241,10 +241,10 @@ struct dentry * oprofilefs_mkdir(struct super_block * sb,
}
-static int oprofilefs_fill_super(struct super_block * sb, void * data, int silent)
+static int oprofilefs_fill_super(struct super_block *sb, void *data, int silent)
{
- struct inode * root_inode;
- struct dentry * root_dentry;
+ struct inode *root_inode;
+ struct dentry *root_dentry;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
index 710a45f0d73..333f915568c 100644
--- a/drivers/oprofile/timer_int.c
+++ b/drivers/oprofile/timer_int.c
@@ -19,7 +19,7 @@
static int timer_notify(struct pt_regs *regs)
{
- oprofile_add_sample(regs, 0);
+ oprofile_add_sample(regs, 0);
return 0;
}
@@ -35,7 +35,7 @@ static void timer_stop(void)
}
-void __init oprofile_timer_init(struct oprofile_operations * ops)
+void __init oprofile_timer_init(struct oprofile_operations *ops)
{
ops->create_files = NULL;
ops->setup = NULL;
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index b30e38f3a50..dcc1e9958d2 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -66,15 +66,8 @@
#undef DEBUG_CCIO_RUN_SG
#ifdef CONFIG_PROC_FS
-/*
- * CCIO_SEARCH_TIME can help measure how fast the bitmap search is.
- * impacts performance though - ditch it if you don't use it.
- */
-#define CCIO_SEARCH_TIME
-#undef CCIO_MAP_STATS
-#else
-#undef CCIO_SEARCH_TIME
-#undef CCIO_MAP_STATS
+/* depends on proc fs support. But costs CPU performance. */
+#undef CCIO_COLLECT_STATS
#endif
#include <linux/proc_fs.h>
@@ -239,12 +232,10 @@ struct ioc {
u32 res_size; /* size of resource map in bytes */
spinlock_t res_lock;
-#ifdef CCIO_SEARCH_TIME
+#ifdef CCIO_COLLECT_STATS
#define CCIO_SEARCH_SAMPLE 0x100
unsigned long avg_search[CCIO_SEARCH_SAMPLE];
unsigned long avg_idx; /* current index into avg_search */
-#endif
-#ifdef CCIO_MAP_STATS
unsigned long used_pages;
unsigned long msingle_calls;
unsigned long msingle_pages;
@@ -351,7 +342,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
unsigned int pages_needed = size >> IOVP_SHIFT;
unsigned int res_idx;
unsigned long boundary_size;
-#ifdef CCIO_SEARCH_TIME
+#ifdef CCIO_COLLECT_STATS
unsigned long cr_start = mfctl(16);
#endif
@@ -406,7 +397,7 @@ resource_found:
DBG_RES("%s() res_idx %d res_hint: %d\n",
__func__, res_idx, ioc->res_hint);
-#ifdef CCIO_SEARCH_TIME
+#ifdef CCIO_COLLECT_STATS
{
unsigned long cr_end = mfctl(16);
unsigned long tmp = cr_end - cr_start;
@@ -416,7 +407,7 @@ resource_found:
ioc->avg_search[ioc->avg_idx++] = cr_start;
ioc->avg_idx &= CCIO_SEARCH_SAMPLE - 1;
#endif
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->used_pages += pages_needed;
#endif
/*
@@ -452,7 +443,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
DBG_RES("%s(): res_idx: %d pages_mapped %d\n",
__func__, res_idx, pages_mapped);
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->used_pages -= pages_mapped;
#endif
@@ -764,7 +755,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
size = ALIGN(size + offset, IOVP_SIZE);
spin_lock_irqsave(&ioc->res_lock, flags);
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->msingle_calls++;
ioc->msingle_pages += size >> IOVP_SHIFT;
#endif
@@ -828,7 +819,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
spin_lock_irqsave(&ioc->res_lock, flags);
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->usingle_calls++;
ioc->usingle_pages += size >> IOVP_SHIFT;
#endif
@@ -894,7 +885,7 @@ ccio_free_consistent(struct device *dev, size_t size, void *cpu_addr,
*/
#define PIDE_FLAG 0x80000000UL
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
#define IOMMU_MAP_STATS
#endif
#include "iommu-helpers.h"
@@ -938,7 +929,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
spin_lock_irqsave(&ioc->res_lock, flags);
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->msg_calls++;
#endif
@@ -997,13 +988,13 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
DBG_RUN_SG("%s() START %d entries, %08lx,%x\n",
__func__, nents, sg_virt_addr(sglist), sglist->length);
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->usg_calls++;
#endif
while(sg_dma_len(sglist) && nents--) {
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
#endif
ccio_unmap_single(dev, sg_dma_address(sglist),
@@ -1048,7 +1039,7 @@ static int ccio_proc_info(struct seq_file *m, void *p)
len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n",
total_pages * 8, total_pages);
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n",
total_pages - ioc->used_pages, ioc->used_pages,
(int)(ioc->used_pages * 100 / total_pages));
@@ -1057,7 +1048,7 @@ static int ccio_proc_info(struct seq_file *m, void *p)
len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n",
ioc->res_size, total_pages);
-#ifdef CCIO_SEARCH_TIME
+#ifdef CCIO_COLLECT_STATS
min = max = ioc->avg_search[0];
for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) {
avg += ioc->avg_search[j];
@@ -1070,7 +1061,7 @@ static int ccio_proc_info(struct seq_file *m, void *p)
len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
min, avg, max);
#endif
-#ifdef CCIO_MAP_STATS
+#ifdef CCIO_COLLECT_STATS
len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
ioc->msingle_calls, ioc->msingle_pages,
(int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
@@ -1088,7 +1079,7 @@ static int ccio_proc_info(struct seq_file *m, void *p)
len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n",
ioc->usg_calls, ioc->usg_pages,
(int)((ioc->usg_pages * 1000)/ioc->usg_calls));
-#endif /* CCIO_MAP_STATS */
+#endif /* CCIO_COLLECT_STATS */
ioc = ioc->next;
}
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index fd56128525d..3bc54b30c3a 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -298,7 +298,8 @@ struct pci_port_ops dino_port_ops = {
static void dino_disable_irq(unsigned int irq)
{
- struct dino_device *dino_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct dino_device *dino_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
@@ -310,7 +311,8 @@ static void dino_disable_irq(unsigned int irq)
static void dino_enable_irq(unsigned int irq)
{
- struct dino_device *dino_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct dino_device *dino_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
u32 tmp;
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 771cef59254..7891db50c48 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -346,10 +346,10 @@ static int __init eisa_probe(struct parisc_device *dev)
}
/* Reserve IRQ2 */
- irq_desc[2].action = &irq2_action;
+ irq_to_desc(2)->action = &irq2_action;
for (i = 0; i < 16; i++) {
- irq_desc[i].chip = &eisa_interrupt_type;
+ irq_to_desc(i)->chip = &eisa_interrupt_type;
}
EISA_bus = 1;
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index 5ac207932fd..685d94e69d4 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -86,7 +86,7 @@ static int eisa_eeprom_open(struct inode *inode, struct file *file)
{
cycle_kernel_lock();
- if (file->f_mode & 2)
+ if (file->f_mode & FMODE_WRITE)
return -EINVAL;
return 0;
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index f7d088b897e..e76db9e4d50 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -108,7 +108,8 @@ int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit)
static void gsc_asic_disable_irq(unsigned int irq)
{
- struct gsc_asic *irq_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct gsc_asic *irq_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
u32 imr;
@@ -123,7 +124,8 @@ static void gsc_asic_disable_irq(unsigned int irq)
static void gsc_asic_enable_irq(unsigned int irq)
{
- struct gsc_asic *irq_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct gsc_asic *irq_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
u32 imr;
@@ -159,12 +161,14 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = {
int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
{
static int irq = GSC_IRQ_BASE;
+ struct irq_desc *desc;
if (irq > GSC_IRQ_MAX)
return NO_IRQ;
- irq_desc[irq].chip = type;
- irq_desc[irq].chip_data = data;
+ desc = irq_to_desc(irq);
+ desc->chip = type;
+ desc->chip_data = data;
return irq++;
}
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 6fb3f7979f2..7beffcab274 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -619,7 +619,9 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
static struct vector_info *iosapic_get_vector(unsigned int irq)
{
- return irq_desc[irq].chip_data;
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ return desc->chip_data;
}
static void iosapic_disable_irq(unsigned int irq)
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 1e8d2d17f04..1e93c837514 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -363,7 +363,9 @@ int superio_fixup_irq(struct pci_dev *pcidev)
#endif
for (i = 0; i < 16; i++) {
- irq_desc[i].chip = &superio_interrupt_type;
+ struct irq_desc *desc = irq_to_desc(i);
+
+ desc->chip = &superio_interrupt_type;
}
/*
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 8a846adf1dc..96f3bdf0ec4 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2791,6 +2791,7 @@ enum parport_pc_pci_cards {
oxsemi_952,
oxsemi_954,
oxsemi_840,
+ oxsemi_pcie_pport,
aks_0100,
mobility_pp,
netmos_9705,
@@ -2868,6 +2869,7 @@ static struct parport_pc_pci {
/* oxsemi_952 */ { 1, { { 0, 1 }, } },
/* oxsemi_954 */ { 1, { { 0, -1 }, } },
/* oxsemi_840 */ { 1, { { 0, 1 }, } },
+ /* oxsemi_pcie_pport */ { 1, { { 0, 1 }, } },
/* aks_0100 */ { 1, { { 0, -1 }, } },
/* mobility_pp */ { 1, { { 0, 1 }, } },
/* netmos_9705 */ { 1, { { 0, -1 }, } }, /* untested */
@@ -2928,7 +2930,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },
{ 0x1409, 0x7268, 0x1409, 0x0104, 0, 0, timedia_4018 },
{ 0x1409, 0x7268, 0x1409, 0x9018, 0, 0, timedia_9018a },
- { 0x14f2, 0x0121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, mobility_pp },
{ PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_2P_EPP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp },
{ PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP,
@@ -2946,8 +2947,25 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_954 },
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_12PCI840,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_840 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe840,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe840_G,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_0,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_0_G,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1_G,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1_U,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
{ PCI_VENDOR_ID_AKS, PCI_DEVICE_ID_AKS_ALADDINCARD,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, aks_0100 },
+ { 0x14f2, 0x0121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, mobility_pp },
/* NetMos communication controllers */
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9705,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9705 },
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 4b47f4ece5b..af3bfe22847 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -3,7 +3,8 @@
#
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
- pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
+ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
+ irq.o
obj-$(CONFIG_PROC_FS) += proc.o
# Build PCI Express stuff if needed
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 529d9d7727b..999cc4088b5 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -151,6 +151,13 @@ void pci_bus_add_devices(struct pci_bus *bus)
if (retval)
dev_err(&dev->dev, "Error creating cpuaffinity"
" file, continuing...\n");
+
+ retval = device_create_file(&child_bus->dev,
+ &dev_attr_cpulistaffinity);
+ if (retval)
+ dev_err(&dev->dev,
+ "Error creating cpulistaffinity"
+ " file, continuing...\n");
}
}
}
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index e842e756308..691b3adeb87 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -188,12 +188,11 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
return 0;
}
-static int __init
-dmar_parse_dev(struct dmar_drhd_unit *dmaru)
+static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
{
struct acpi_dmar_hardware_unit *drhd;
static int include_all;
- int ret;
+ int ret = 0;
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
@@ -212,7 +211,7 @@ dmar_parse_dev(struct dmar_drhd_unit *dmaru)
include_all = 1;
}
- if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
+ if (ret) {
list_del(&dmaru->list);
kfree(dmaru);
}
@@ -277,18 +276,37 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
drhd = (struct acpi_dmar_hardware_unit *)header;
printk (KERN_INFO PREFIX
"DRHD (flags: 0x%08x)base: 0x%016Lx\n",
- drhd->flags, drhd->address);
+ drhd->flags, (unsigned long long)drhd->address);
break;
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
rmrr = (struct acpi_dmar_reserved_memory *)header;
printk (KERN_INFO PREFIX
"RMRR base: 0x%016Lx end: 0x%016Lx\n",
- rmrr->base_address, rmrr->end_address);
+ (unsigned long long)rmrr->base_address,
+ (unsigned long long)rmrr->end_address);
break;
}
}
+/**
+ * dmar_table_detect - checks to see if the platform supports DMAR devices
+ */
+static int __init dmar_table_detect(void)
+{
+ acpi_status status = AE_OK;
+
+ /* if we could find DMAR table, then there are DMAR devices */
+ status = acpi_get_table(ACPI_SIG_DMAR, 0,
+ (struct acpi_table_header **)&dmar_tbl);
+
+ if (ACPI_SUCCESS(status) && !dmar_tbl) {
+ printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
+ status = AE_NOT_FOUND;
+ }
+
+ return (ACPI_SUCCESS(status) ? 1 : 0);
+}
/**
* parse_dmar_table - parses the DMA reporting table
@@ -300,11 +318,17 @@ parse_dmar_table(void)
struct acpi_dmar_header *entry_header;
int ret = 0;
+ /*
+ * Do it again, earlier dmar_tbl mapping could be mapped with
+ * fixed map.
+ */
+ dmar_table_detect();
+
dmar = (struct acpi_table_dmar *)dmar_tbl;
if (!dmar)
return -ENODEV;
- if (dmar->width < PAGE_SHIFT_4K - 1) {
+ if (dmar->width < PAGE_SHIFT - 1) {
printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
return -EINVAL;
}
@@ -373,10 +397,10 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
int __init dmar_dev_scope_init(void)
{
- struct dmar_drhd_unit *drhd;
+ struct dmar_drhd_unit *drhd, *drhd_n;
int ret = -ENODEV;
- for_each_drhd_unit(drhd) {
+ list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
ret = dmar_parse_dev(drhd);
if (ret)
return ret;
@@ -384,8 +408,8 @@ int __init dmar_dev_scope_init(void)
#ifdef CONFIG_DMAR
{
- struct dmar_rmrr_unit *rmrr;
- for_each_rmrr_units(rmrr) {
+ struct dmar_rmrr_unit *rmrr, *rmrr_n;
+ list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
ret = rmrr_parse_dev(rmrr);
if (ret)
return ret;
@@ -430,33 +454,14 @@ int __init dmar_table_init(void)
return 0;
}
-/**
- * early_dmar_detect - checks to see if the platform supports DMAR devices
- */
-int __init early_dmar_detect(void)
-{
- acpi_status status = AE_OK;
-
- /* if we could find DMAR table, then there are DMAR devices */
- status = acpi_get_table(ACPI_SIG_DMAR, 0,
- (struct acpi_table_header **)&dmar_tbl);
-
- if (ACPI_SUCCESS(status) && !dmar_tbl) {
- printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
- status = AE_NOT_FOUND;
- }
-
- return (ACPI_SUCCESS(status) ? 1 : 0);
-}
-
void __init detect_intel_iommu(void)
{
int ret;
- ret = early_dmar_detect();
+ ret = dmar_table_detect();
-#ifdef CONFIG_DMAR
{
+#ifdef CONFIG_INTR_REMAP
struct acpi_table_dmar *dmar;
/*
* for now we will disable dma-remapping when interrupt
@@ -465,28 +470,18 @@ void __init detect_intel_iommu(void)
* is added, we will not need this any more.
*/
dmar = (struct acpi_table_dmar *) dmar_tbl;
- if (ret && cpu_has_x2apic && dmar->flags & 0x1) {
+ if (ret && cpu_has_x2apic && dmar->flags & 0x1)
printk(KERN_INFO
"Queued invalidation will be enabled to support "
"x2apic and Intr-remapping.\n");
- printk(KERN_INFO
- "Disabling IOMMU detection, because of missing "
- "queued invalidation support for IOTLB "
- "invalidation\n");
- printk(KERN_INFO
- "Use \"nox2apic\", if you want to use Intel "
- " IOMMU for DMA-remapping and don't care about "
- " x2apic support\n");
-
- dmar_disabled = 1;
- return;
- }
-
+#endif
+#ifdef CONFIG_DMAR
if (ret && !no_iommu && !iommu_detected && !swiotlb &&
!dmar_disabled)
iommu_detected = 1;
- }
#endif
+ }
+ dmar_tbl = NULL;
}
@@ -503,7 +498,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
iommu->seq_id = iommu_allocated++;
- iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
+ iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
if (!iommu->reg) {
printk(KERN_ERR "IOMMU: can't map the region\n");
goto error;
@@ -514,8 +509,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
/* the registers might be more than one page */
map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
cap_max_fault_reg_offset(iommu->cap));
- map_size = PAGE_ALIGN_4K(map_size);
- if (map_size > PAGE_SIZE_4K) {
+ map_size = VTD_PAGE_ALIGN(map_size);
+ if (map_size > VTD_PAGE_SIZE) {
iounmap(iommu->reg);
iommu->reg = ioremap(drhd->reg_base_addr, map_size);
if (!iommu->reg) {
@@ -526,8 +521,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
ver = readl(iommu->reg + DMAR_VER_REG);
pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
- drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
- iommu->cap, iommu->ecap);
+ (unsigned long long)drhd->reg_base_addr,
+ DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
+ (unsigned long long)iommu->cap,
+ (unsigned long long)iommu->ecap);
spin_lock_init(&iommu->register_lock);
@@ -580,11 +577,11 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
hw = qi->desc;
- spin_lock(&qi->q_lock);
+ spin_lock_irqsave(&qi->q_lock, flags);
while (qi->free_cnt < 3) {
- spin_unlock(&qi->q_lock);
+ spin_unlock_irqrestore(&qi->q_lock, flags);
cpu_relax();
- spin_lock(&qi->q_lock);
+ spin_lock_irqsave(&qi->q_lock, flags);
}
index = qi->free_head;
@@ -605,15 +602,22 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
qi->free_head = (qi->free_head + 2) % QI_LENGTH;
qi->free_cnt -= 2;
- spin_lock_irqsave(&iommu->register_lock, flags);
+ spin_lock(&iommu->register_lock);
/*
* update the HW tail register indicating the presence of
* new descriptors.
*/
writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ spin_unlock(&iommu->register_lock);
while (qi->desc_status[wait_index] != QI_DONE) {
+ /*
+ * We will leave the interrupts disabled, to prevent interrupt
+ * context to queue another cmd while a cmd is already submitted
+ * and waiting for completion on this cpu. This is to avoid
+ * a deadlock where the interrupt context can wait indefinitely
+ * for free slots in the queue.
+ */
spin_unlock(&qi->q_lock);
cpu_relax();
spin_lock(&qi->q_lock);
@@ -622,7 +626,7 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
qi->desc_status[index] = QI_DONE;
reclaim_free_desc(qi);
- spin_unlock(&qi->q_lock);
+ spin_unlock_irqrestore(&qi->q_lock, flags);
}
/*
@@ -638,6 +642,62 @@ void qi_global_iec(struct intel_iommu *iommu)
qi_submit_sync(&desc, iommu);
}
+int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
+ u64 type, int non_present_entry_flush)
+{
+
+ struct qi_desc desc;
+
+ if (non_present_entry_flush) {
+ if (!cap_caching_mode(iommu->cap))
+ return 1;
+ else
+ did = 0;
+ }
+
+ desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did)
+ | QI_CC_GRAN(type) | QI_CC_TYPE;
+ desc.high = 0;
+
+ qi_submit_sync(&desc, iommu);
+
+ return 0;
+
+}
+
+int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
+ unsigned int size_order, u64 type,
+ int non_present_entry_flush)
+{
+ u8 dw = 0, dr = 0;
+
+ struct qi_desc desc;
+ int ih = 0;
+
+ if (non_present_entry_flush) {
+ if (!cap_caching_mode(iommu->cap))
+ return 1;
+ else
+ did = 0;
+ }
+
+ if (cap_write_drain(iommu->cap))
+ dw = 1;
+
+ if (cap_read_drain(iommu->cap))
+ dr = 1;
+
+ desc.low = QI_IOTLB_DID(did) | QI_IOTLB_DR(dr) | QI_IOTLB_DW(dw)
+ | QI_IOTLB_GRAN(type) | QI_IOTLB_TYPE;
+ desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
+ | QI_IOTLB_AM(size_order);
+
+ qi_submit_sync(&desc, iommu);
+
+ return 0;
+
+}
+
/*
* Enable Queued Invalidation interface. This is a must to support
* interrupt-remapping. Also used by DMA-remapping, which replaces
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 5a58b075dd8..f9e244da30a 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -50,9 +50,6 @@
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#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 20 /* {_SUN} */
-
struct acpiphp_bridge;
struct acpiphp_slot;
@@ -63,9 +60,13 @@ struct slot {
struct hotplug_slot *hotplug_slot;
struct acpiphp_slot *acpi_slot;
struct hotplug_slot_info info;
- char name[SLOT_NAME_SIZE];
};
+static inline const char *slot_name(struct slot *slot)
+{
+ return hotplug_slot_name(slot->hotplug_slot);
+}
+
/*
* struct acpiphp_bridge - PCI bridge information
*
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 0e496e866a8..95b536a23d2 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -44,6 +44,9 @@
#define MY_NAME "acpiphp"
+/* name size which is used for entries in pcihpfs */
+#define SLOT_NAME_SIZE 21 /* {_SUN} */
+
static int debug;
int acpiphp_debug;
@@ -84,7 +87,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
.get_adapter_status = get_adapter_status,
};
-
/**
* acpiphp_register_attention - set attention LED callback
* @info: must be completely filled with LED callbacks
@@ -136,7 +138,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
/* enable the specified slot */
return acpiphp_enable_slot(slot->acpi_slot);
@@ -154,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
/* disable the specified slot */
retval = acpiphp_disable_slot(slot->acpi_slot);
@@ -177,7 +179,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
{
int retval = -ENODEV;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
if (attention_info && try_module_get(attention_info->owner)) {
retval = attention_info->set_attn(hotplug_slot, status);
@@ -200,7 +202,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = acpiphp_get_power_status(slot->acpi_slot);
@@ -222,7 +224,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
int retval = -EINVAL;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
if (attention_info && try_module_get(attention_info->owner)) {
retval = attention_info->get_attn(hotplug_slot, value);
@@ -245,7 +247,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = acpiphp_get_latch_status(slot->acpi_slot);
@@ -265,7 +267,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = acpiphp_get_adapter_status(slot->acpi_slot);
@@ -299,7 +301,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
kfree(slot->hotplug_slot);
kfree(slot);
@@ -310,6 +312,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
{
struct slot *slot;
int retval = -ENOMEM;
+ char name[SLOT_NAME_SIZE];
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
@@ -321,8 +324,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
slot->hotplug_slot->info = &slot->info;
- slot->hotplug_slot->name = slot->name;
-
slot->hotplug_slot->private = slot;
slot->hotplug_slot->release = &release_slot;
slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
@@ -336,11 +337,12 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
acpiphp_slot->slot = slot;
- snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun);
+ snprintf(name, SLOT_NAME_SIZE, "%u", slot->acpi_slot->sun);
retval = pci_hp_register(slot->hotplug_slot,
acpiphp_slot->bridge->pci_bus,
- acpiphp_slot->device);
+ acpiphp_slot->device,
+ name);
if (retval == -EBUSY)
goto error_hpslot;
if (retval) {
@@ -348,7 +350,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
goto error_hpslot;
}
- info("Slot [%s] registered\n", slot->hotplug_slot->name);
+ info("Slot [%s] registered\n", slot_name(slot));
return 0;
error_hpslot:
@@ -365,7 +367,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
struct slot *slot = acpiphp_slot->slot;
int retval = 0;
- info ("Slot [%s] unregistered\n", slot->hotplug_slot->name);
+ info("Slot [%s] unregistered\n", slot_name(slot));
retval = pci_hp_deregister(slot->hotplug_slot);
if (retval)
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index a3e4705dd8f..955aae4071f 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -169,7 +169,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
}
-
+static struct acpi_dock_ops acpiphp_dock_ops = {
+ .handler = handle_hotplug_event_func,
+};
/* callback routine to register each ACPI PCI slot object */
static acpi_status
@@ -180,7 +182,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
struct acpiphp_func *newfunc;
acpi_handle tmp;
acpi_status status = AE_OK;
- unsigned long adr, sun;
+ unsigned long long adr, sun;
int device, function, retval;
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
@@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
*/
newfunc->flags &= ~FUNC_HAS_EJ0;
if (register_hotplug_dock_device(handle,
- handle_hotplug_event_func, newfunc))
+ &acpiphp_dock_ops, newfunc))
dbg("failed to register dock device\n");
/* we need to be notified when dock events happen
@@ -528,7 +530,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
acpi_handle dummy_handle;
- unsigned long tmp;
+ unsigned long long tmp;
int device, function;
struct pci_dev *dev;
struct pci_bus *pci_bus = context;
@@ -573,7 +575,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
static int add_bridge(acpi_handle handle)
{
acpi_status status;
- unsigned long tmp;
+ unsigned long long tmp;
int seg, bus;
acpi_handle dummy_handle;
struct pci_bus *pci_bus;
@@ -767,7 +769,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
{
acpi_status status;
int result = -1;
- unsigned long gsb;
+ unsigned long long gsb;
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *obj;
void *table;
@@ -808,7 +810,7 @@ static acpi_status
ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
- unsigned long sta;
+ unsigned long long sta;
acpi_handle tmp;
struct pci_dev *pdev;
u32 gsi_base;
@@ -872,7 +874,7 @@ static acpi_status
ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
- unsigned long sta;
+ unsigned long long sta;
acpi_handle tmp;
u32 gsi_base;
struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
@@ -1264,7 +1266,7 @@ static int disable_device(struct acpiphp_slot *slot)
static unsigned int get_slot_status(struct acpiphp_slot *slot)
{
acpi_status status;
- unsigned long sta = 0;
+ unsigned long long sta = 0;
u32 dvid;
struct list_head *l;
struct acpiphp_func *func;
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 2b7c45e3937..881fdd2b731 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -183,7 +183,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
union acpi_object args[2];
struct acpi_object_list params = { .pointer = args, .count = 2 };
acpi_status stat;
- unsigned long rc;
+ unsigned long long rc;
union apci_descriptor *ibm_slot;
ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
@@ -204,7 +204,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
err("APLS evaluation failed: 0x%08x\n", stat);
return -ENODEV;
} else if (!rc) {
- err("APLS method failed: 0x%08lx\n", rc);
+ err("APLS method failed: 0x%08llx\n", rc);
return -ERANGE;
}
return 0;
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
index d9769b30be9..9fff878cf02 100644
--- a/drivers/pci/hotplug/cpci_hotplug.h
+++ b/drivers/pci/hotplug/cpci_hotplug.h
@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
/* PICMG 2.1 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
@@ -69,6 +70,11 @@ struct cpci_hp_controller {
struct cpci_hp_controller_ops *ops;
};
+static inline const char *slot_name(struct slot *slot)
+{
+ return hotplug_slot_name(slot->hotplug_slot);
+}
+
extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 935947991dc..de94f4feef8 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -108,7 +108,7 @@ enable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
int retval = 0;
- dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s", __func__, slot_name(slot));
if (controller->ops->set_power)
retval = controller->ops->set_power(slot, 1);
@@ -121,25 +121,23 @@ disable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
int retval = 0;
- dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s", __func__, slot_name(slot));
down_write(&list_rwsem);
/* Unconfigure device */
- dbg("%s - unconfiguring slot %s",
- __func__, slot->hotplug_slot->name);
+ dbg("%s - unconfiguring slot %s", __func__, slot_name(slot));
if ((retval = cpci_unconfigure_slot(slot))) {
err("%s - could not unconfigure slot %s",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
goto disable_error;
}
- dbg("%s - finished unconfiguring slot %s",
- __func__, slot->hotplug_slot->name);
+ dbg("%s - finished unconfiguring slot %s", __func__, slot_name(slot));
/* Clear EXT (by setting it) */
if (cpci_clear_ext(slot)) {
err("%s - could not clear EXT for slot %s",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
retval = -ENODEV;
goto disable_error;
}
@@ -214,7 +212,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
if (slot->dev)
pci_dev_put(slot->dev);
@@ -222,12 +219,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
}
#define SLOT_NAME_SIZE 6
-static void
-make_slot_name(struct slot *slot)
-{
- snprintf(slot->hotplug_slot->name,
- SLOT_NAME_SIZE, "%02x:%02x", slot->bus->number, slot->number);
-}
int
cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
@@ -235,7 +226,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
- char *name;
+ char name[SLOT_NAME_SIZE];
int status = -ENOMEM;
int i;
@@ -262,34 +253,31 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
goto error_hpslot;
hotplug_slot->info = info;
- name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
- if (!name)
- goto error_info;
- hotplug_slot->name = name;
-
slot->bus = bus;
slot->number = i;
slot->devfn = PCI_DEVFN(i, 0);
+ snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i);
+
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
- make_slot_name(slot);
hotplug_slot->ops = &cpci_hotplug_slot_ops;
/*
* Initialize the slot info structure with some known
* good values.
*/
- dbg("initializing slot %s", slot->hotplug_slot->name);
+ dbg("initializing slot %s", name);
info->power_status = cpci_get_power_status(slot);
info->attention_status = cpci_get_attention_status(slot);
- dbg("registering slot %s", slot->hotplug_slot->name);
- status = pci_hp_register(slot->hotplug_slot, bus, i);
+ dbg("registering slot %s", name);
+ status = pci_hp_register(slot->hotplug_slot, bus, i, name);
if (status) {
err("pci_hp_register failed with error %d", status);
- goto error_name;
+ goto error_info;
}
+ dbg("slot registered with name: %s", slot_name(slot));
/* Add slot to our internal list */
down_write(&list_rwsem);
@@ -298,8 +286,6 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
up_write(&list_rwsem);
}
return 0;
-error_name:
- kfree(name);
error_info:
kfree(info);
error_hpslot:
@@ -327,7 +313,7 @@ cpci_hp_unregister_bus(struct pci_bus *bus)
list_del(&slot->slot_list);
slots--;
- dbg("deregistering slot %s", slot->hotplug_slot->name);
+ dbg("deregistering slot %s", slot_name(slot));
status = pci_hp_deregister(slot->hotplug_slot);
if (status) {
err("pci_hp_deregister failed with error %d",
@@ -379,11 +365,10 @@ init_slots(int clear_ins)
return -1;
}
list_for_each_entry(slot, &slot_list, slot_list) {
- dbg("%s - looking at slot %s",
- __func__, slot->hotplug_slot->name);
+ dbg("%s - looking at slot %s", __func__, slot_name(slot));
if (clear_ins && cpci_check_and_clear_ins(slot))
dbg("%s - cleared INS for slot %s",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
if (dev) {
if (update_adapter_status(slot->hotplug_slot, 1))
@@ -414,8 +399,7 @@ check_slots(void)
}
extracted = inserted = 0;
list_for_each_entry(slot, &slot_list, slot_list) {
- dbg("%s - looking at slot %s",
- __func__, slot->hotplug_slot->name);
+ dbg("%s - looking at slot %s", __func__, slot_name(slot));
if (cpci_check_and_clear_ins(slot)) {
/*
* Some broken hardware (e.g. PLX 9054AB) asserts
@@ -423,35 +407,34 @@ check_slots(void)
*/
if (slot->dev) {
warn("slot %s already inserted",
- slot->hotplug_slot->name);
+ slot_name(slot));
inserted++;
continue;
}
/* Process insertion */
- dbg("%s - slot %s inserted",
- __func__, slot->hotplug_slot->name);
+ dbg("%s - slot %s inserted", __func__, slot_name(slot));
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR (1) = %04x",
- __func__, slot->hotplug_slot->name, hs_csr);
+ __func__, slot_name(slot), hs_csr);
/* Configure device */
dbg("%s - configuring slot %s",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
if (cpci_configure_slot(slot)) {
err("%s - could not configure slot %s",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
continue;
}
dbg("%s - finished configuring slot %s",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR (2) = %04x",
- __func__, slot->hotplug_slot->name, hs_csr);
+ __func__, slot_name(slot), hs_csr);
if (update_latch_status(slot->hotplug_slot, 1))
warn("failure to update latch file");
@@ -464,18 +447,18 @@ check_slots(void)
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR (3) = %04x",
- __func__, slot->hotplug_slot->name, hs_csr);
+ __func__, slot_name(slot), hs_csr);
inserted++;
} else if (cpci_check_ext(slot)) {
/* Process extraction request */
dbg("%s - slot %s extracted",
- __func__, slot->hotplug_slot->name);
+ __func__, slot_name(slot));
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR = %04x",
- __func__, slot->hotplug_slot->name, hs_csr);
+ __func__, slot_name(slot), hs_csr);
if (!slot->extracting) {
if (update_latch_status(slot->hotplug_slot, 0)) {
@@ -493,7 +476,7 @@ check_slots(void)
* bother trying to tell the driver or not?
*/
err("card in slot %s was improperly removed",
- slot->hotplug_slot->name);
+ slot_name(slot));
if (update_adapter_status(slot->hotplug_slot, 0))
warn("failure to update adapter file");
slot->extracting = 0;
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index df82b95e287..829c327cfb5 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -209,7 +209,7 @@ int cpci_led_on(struct slot* slot)
hs_cap + 2,
hs_csr)) {
err("Could not set LOO for slot %s",
- slot->hotplug_slot->name);
+ hotplug_slot_name(slot->hotplug_slot));
return -ENODEV;
}
}
@@ -238,7 +238,7 @@ int cpci_led_off(struct slot* slot)
hs_cap + 2,
hs_csr)) {
err("Could not clear LOO for slot %s",
- slot->hotplug_slot->name);
+ hotplug_slot_name(slot->hotplug_slot));
return -ENODEV;
}
}
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index b1decfa88b7..afaf8f69f73 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -449,6 +449,11 @@ extern u8 cpqhp_disk_irq;
/* inline functions */
+static inline char *slot_name(struct slot *slot)
+{
+ return hotplug_slot_name(slot->hotplug_slot);
+}
+
/*
* return_resource
*
@@ -696,14 +701,6 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot
return presence_save;
}
-#define SLOT_NAME_SIZE 10
-
-static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
-{
- snprintf(buffer, buffer_size, "%d", slot->number);
-}
-
-
static inline int wait_for_ctrl_irq(struct controller *ctrl)
{
DECLARE_WAITQUEUE(wait, current);
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 54defec51d0..8514c3a1746 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -315,14 +315,15 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
kfree(slot);
}
+#define SLOT_NAME_SIZE 10
+
static int ctrl_slot_setup(struct controller *ctrl,
void __iomem *smbios_start,
void __iomem *smbios_table)
@@ -335,6 +336,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
u8 slot_number;
u8 ctrl_slot;
u32 tempdword;
+ char name[SLOT_NAME_SIZE];
void __iomem *slot_entry= NULL;
int result = -ENOMEM;
@@ -363,16 +365,12 @@ static int ctrl_slot_setup(struct controller *ctrl,
if (!hotplug_slot->info)
goto error_hpslot;
hotplug_slot_info = hotplug_slot->info;
- hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
-
- if (!hotplug_slot->name)
- goto error_info;
slot->ctrl = ctrl;
slot->bus = ctrl->bus;
slot->device = slot_device;
slot->number = slot_number;
- dbg("slot->number = %d\n", slot->number);
+ dbg("slot->number = %u\n", slot->number);
slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
slot_entry);
@@ -418,9 +416,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
/* register this slot with the hotplug pci core */
hotplug_slot->release = &release_slot;
hotplug_slot->private = slot;
- make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
+ snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
-
+
hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
hotplug_slot_info->attention_status =
cpq_get_attention_status(ctrl, slot);
@@ -435,11 +433,12 @@ static int ctrl_slot_setup(struct controller *ctrl,
slot->number, ctrl->slot_device_offset,
slot_number);
result = pci_hp_register(hotplug_slot,
- ctrl->pci_dev->subordinate,
- slot->device);
+ ctrl->pci_dev->bus,
+ slot->device,
+ name);
if (result) {
err("pci_hp_register failed with error %d\n", result);
- goto error_name;
+ goto error_info;
}
slot->next = ctrl->slot;
@@ -451,8 +450,6 @@ static int ctrl_slot_setup(struct controller *ctrl,
}
return 0;
-error_name:
- kfree(hotplug_slot->name);
error_info:
kfree(hotplug_slot_info);
error_hpslot:
@@ -638,7 +635,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
u8 device;
u8 function;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
return -ENODEV;
@@ -665,7 +662,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot)
u8 device;
u8 function;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
return -ENODEV;
@@ -697,7 +694,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
u8 device;
u8 function;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
return -ENODEV;
@@ -720,7 +717,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
return cpqhp_hardware_test(ctrl, value);
}
@@ -731,7 +728,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = get_slot_enabled(ctrl, slot);
return 0;
@@ -742,7 +739,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = cpq_get_attention_status(ctrl, slot);
return 0;
@@ -753,7 +750,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = cpq_get_latch_status(ctrl, slot);
@@ -765,7 +762,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = get_presence_status(ctrl, slot);
@@ -777,7 +774,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = ctrl->speed_capability;
@@ -789,7 +786,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = ctrl->speed;
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index ef041ca91c2..a60a2529099 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -1139,7 +1139,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
for(slot = ctrl->slot; slot; slot = slot->next) {
if (slot->device == (hp_slot + ctrl->slot_device_offset))
continue;
- if (!slot->hotplug_slot && !slot->hotplug_slot->info)
+ if (!slot->hotplug_slot || !slot->hotplug_slot->info)
continue;
if (slot->hotplug_slot->info->adapter_status == 0)
continue;
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 146ca9cd156..3a2637a0093 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -66,10 +66,10 @@ struct dummy_slot {
struct pci_dev *dev;
struct work_struct remove_work;
unsigned long removed;
- char name[8];
};
static int debug;
+static int dup_slots;
static LIST_HEAD(slot_list);
static struct workqueue_struct *dummyphp_wq;
@@ -96,10 +96,13 @@ static void dummy_release(struct hotplug_slot *slot)
kfree(dslot);
}
+#define SLOT_NAME_SIZE 8
+
static int add_slot(struct pci_dev *dev)
{
struct dummy_slot *dslot;
struct hotplug_slot *slot;
+ char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
static int count = 1;
@@ -119,19 +122,22 @@ static int add_slot(struct pci_dev *dev)
if (!dslot)
goto error_info;
- slot->name = dslot->name;
- snprintf(slot->name, sizeof(dslot->name), "fake%d", count++);
- dbg("slot->name = %s\n", slot->name);
+ if (dup_slots)
+ snprintf(name, SLOT_NAME_SIZE, "fake");
+ else
+ snprintf(name, SLOT_NAME_SIZE, "fake%d", count++);
+ dbg("slot->name = %s\n", name);
slot->ops = &dummy_hotplug_slot_ops;
slot->release = &dummy_release;
slot->private = dslot;
- retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
+ retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn), name);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
goto error_dslot;
}
+ dbg("slot->name = %s\n", hotplug_slot_name(slot));
dslot->slot = slot;
dslot->dev = pci_dev_get(dev);
list_add (&dslot->node, &slot_list);
@@ -167,10 +173,11 @@ static void remove_slot(struct dummy_slot *dslot)
{
int retval;
- dbg("removing slot %s\n", dslot->slot->name);
+ dbg("removing slot %s\n", hotplug_slot_name(dslot->slot));
retval = pci_hp_deregister(dslot->slot);
if (retval)
- err("Problem unregistering a slot %s\n", dslot->slot->name);
+ err("Problem unregistering a slot %s\n",
+ hotplug_slot_name(dslot->slot));
}
/* called from the single-threaded workqueue handler to remove a slot */
@@ -308,7 +315,7 @@ static int disable_slot(struct hotplug_slot *slot)
return -ENODEV;
dslot = slot->private;
- dbg("%s - physical_slot = %s\n", __func__, slot->name);
+ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(slot));
for (func = 7; func >= 0; func--) {
dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func);
@@ -373,4 +380,5 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-
+module_param(dup_slots, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dup_slots, "Force duplicate slot names for debugging");
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
index 612d9630150..a8d391a4957 100644
--- a/drivers/pci/hotplug/ibmphp.h
+++ b/drivers/pci/hotplug/ibmphp.h
@@ -707,17 +707,16 @@ struct slot {
u8 device;
u8 number;
u8 real_physical_slot_num;
- char name[100];
u32 capabilities;
u8 supported_speed;
u8 supported_bus_mode;
+ u8 flag; /* this is for disable slot and polling */
+ u8 ctlr_index;
struct hotplug_slot *hotplug_slot;
struct controller *ctrl;
struct pci_func *func;
u8 irq[4];
- u8 flag; /* this is for disable slot and polling */
int bit_mode; /* 0 = 32, 1 = 64 */
- u8 ctlr_index;
struct bus_info *bus_on;
struct list_head ibm_slot_list;
u8 status;
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 7d27631e6e6..c1abac8ab5c 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -123,10 +123,8 @@ static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)
static void __init print_bus_info (void)
{
struct bus_info *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &bus_info_head) {
- ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+ list_for_each_entry(ptr, &bus_info_head, bus_info_list) {
debug ("%s - slot_min = %x\n", __func__, ptr->slot_min);
debug ("%s - slot_max = %x\n", __func__, ptr->slot_max);
debug ("%s - slot_count = %x\n", __func__, ptr->slot_count);
@@ -146,10 +144,8 @@ static void __init print_bus_info (void)
static void print_lo_info (void)
{
struct rio_detail *ptr;
- struct list_head *ptr1;
debug ("print_lo_info ----\n");
- list_for_each (ptr1, &rio_lo_head) {
- ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+ list_for_each_entry(ptr, &rio_lo_head, rio_detail_list) {
debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
@@ -163,10 +159,8 @@ static void print_lo_info (void)
static void print_vg_info (void)
{
struct rio_detail *ptr;
- struct list_head *ptr1;
debug ("%s ---\n", __func__);
- list_for_each (ptr1, &rio_vg_head) {
- ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+ list_for_each_entry(ptr, &rio_vg_head, rio_detail_list) {
debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
@@ -180,10 +174,8 @@ static void print_vg_info (void)
static void __init print_ebda_pci_rsrc (void)
{
struct ebda_pci_rsrc *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) {
- ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
+ list_for_each_entry(ptr, &ibmphp_ebda_pci_rsrc_head, ebda_pci_rsrc_list) {
debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",
__func__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
}
@@ -192,10 +184,8 @@ static void __init print_ebda_pci_rsrc (void)
static void __init print_ibm_slot (void)
{
struct slot *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &ibmphp_slot_head) {
- ptr = list_entry (ptr1, struct slot, ibm_slot_list);
+ list_for_each_entry(ptr, &ibmphp_slot_head, ibm_slot_list) {
debug ("%s - slot_number: %x\n", __func__, ptr->number);
}
}
@@ -203,10 +193,8 @@ static void __init print_ibm_slot (void)
static void __init print_opt_vg (void)
{
struct opt_rio *ptr;
- struct list_head *ptr1;
debug ("%s ---\n", __func__);
- list_for_each (ptr1, &opt_vg_head) {
- ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
+ list_for_each_entry(ptr, &opt_vg_head, opt_rio_list) {
debug ("%s - rio_type %x\n", __func__, ptr->rio_type);
debug ("%s - chassis_num: %x\n", __func__, ptr->chassis_num);
debug ("%s - first_slot_num: %x\n", __func__, ptr->first_slot_num);
@@ -217,13 +205,9 @@ static void __init print_opt_vg (void)
static void __init print_ebda_hpc (void)
{
struct controller *hpc_ptr;
- struct list_head *ptr1;
u16 index;
- list_for_each (ptr1, &ebda_hpc_head) {
-
- hpc_ptr = list_entry (ptr1, struct controller, ebda_hpc_list);
-
+ list_for_each_entry(hpc_ptr, &ebda_hpc_head, ebda_hpc_list) {
for (index = 0; index < hpc_ptr->slot_count; index++) {
debug ("%s - physical slot#: %x\n", __func__, hpc_ptr->slots[index].slot_num);
debug ("%s - pci bus# of the slot: %x\n", __func__, hpc_ptr->slots[index].slot_bus_num);
@@ -460,9 +444,7 @@ static int __init ebda_rio_table (void)
static struct opt_rio *search_opt_vg (u8 chassis_num)
{
struct opt_rio *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &opt_vg_head) {
- ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
+ list_for_each_entry(ptr, &opt_vg_head, opt_rio_list) {
if (ptr->chassis_num == chassis_num)
return ptr;
}
@@ -473,10 +455,8 @@ static int __init combine_wpg_for_chassis (void)
{
struct opt_rio *opt_rio_ptr = NULL;
struct rio_detail *rio_detail_ptr = NULL;
- struct list_head *list_head_ptr = NULL;
- list_for_each (list_head_ptr, &rio_vg_head) {
- rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
+ list_for_each_entry(rio_detail_ptr, &rio_vg_head, rio_detail_list) {
opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);
if (!opt_rio_ptr) {
opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL);
@@ -497,14 +477,12 @@ static int __init combine_wpg_for_chassis (void)
}
/*
- * reorgnizing linked list of expansion box
+ * reorganizing linked list of expansion box
*/
static struct opt_rio_lo *search_opt_lo (u8 chassis_num)
{
struct opt_rio_lo *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &opt_lo_head) {
- ptr = list_entry (ptr1, struct opt_rio_lo, opt_rio_lo_list);
+ list_for_each_entry(ptr, &opt_lo_head, opt_rio_lo_list) {
if (ptr->chassis_num == chassis_num)
return ptr;
}
@@ -515,10 +493,8 @@ static int combine_wpg_for_expansion (void)
{
struct opt_rio_lo *opt_rio_lo_ptr = NULL;
struct rio_detail *rio_detail_ptr = NULL;
- struct list_head *list_head_ptr = NULL;
- list_for_each (list_head_ptr, &rio_lo_head) {
- rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list);
+ list_for_each_entry(rio_detail_ptr, &rio_lo_head, rio_detail_list) {
opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);
if (!opt_rio_lo_ptr) {
opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL);
@@ -550,20 +526,17 @@ static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)
{
struct opt_rio *opt_vg_ptr = NULL;
struct opt_rio_lo *opt_lo_ptr = NULL;
- struct list_head *ptr = NULL;
int rc = 0;
if (!var) {
- list_for_each (ptr, &opt_vg_head) {
- opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
+ list_for_each_entry(opt_vg_ptr, &opt_vg_head, opt_rio_list) {
if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) {
rc = -ENODEV;
break;
}
}
} else {
- list_for_each (ptr, &opt_lo_head) {
- opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
+ list_for_each_entry(opt_lo_ptr, &opt_lo_head, opt_rio_lo_list) {
if ((first_slot < opt_lo_ptr->first_slot_num) && (slot_num >= opt_lo_ptr->first_slot_num)) {
rc = -ENODEV;
break;
@@ -576,10 +549,8 @@ static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)
static struct opt_rio_lo * find_rxe_num (u8 slot_num)
{
struct opt_rio_lo *opt_lo_ptr;
- struct list_head *ptr;
- list_for_each (ptr, &opt_lo_head) {
- opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list);
+ list_for_each_entry(opt_lo_ptr, &opt_lo_head, opt_rio_lo_list) {
//check to see if this slot_num belongs to expansion box
if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1)))
return opt_lo_ptr;
@@ -590,10 +561,8 @@ static struct opt_rio_lo * find_rxe_num (u8 slot_num)
static struct opt_rio * find_chassis_num (u8 slot_num)
{
struct opt_rio *opt_vg_ptr;
- struct list_head *ptr;
- list_for_each (ptr, &opt_vg_head) {
- opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list);
+ list_for_each_entry(opt_vg_ptr, &opt_vg_head, opt_rio_list) {
//check to see if this slot_num belongs to chassis
if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0)))
return opt_vg_ptr;
@@ -607,11 +576,9 @@ static struct opt_rio * find_chassis_num (u8 slot_num)
static u8 calculate_first_slot (u8 slot_num)
{
u8 first_slot = 1;
- struct list_head * list;
struct slot * slot_cur;
- list_for_each (list, &ibmphp_slot_head) {
- slot_cur = list_entry (list, struct slot, ibm_slot_list);
+ list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {
if (slot_cur->ctrl) {
if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num))
first_slot = slot_cur->ctrl->ending_slot_num;
@@ -620,11 +587,14 @@ static u8 calculate_first_slot (u8 slot_num)
return first_slot + 1;
}
+
+#define SLOT_NAME_SIZE 30
+
static char *create_file_name (struct slot * slot_cur)
{
struct opt_rio *opt_vg_ptr = NULL;
struct opt_rio_lo *opt_lo_ptr = NULL;
- static char str[30];
+ static char str[SLOT_NAME_SIZE];
int which = 0; /* rxe = 1, chassis = 0 */
u8 number = 1; /* either chassis or rxe # */
u8 first_slot = 1;
@@ -736,7 +706,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
slot = hotplug_slot->private;
kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
slot->ctrl = NULL;
slot->bus_on = NULL;
@@ -767,7 +736,7 @@ static int __init ebda_rsrc_controller (void)
struct bus_info *bus_info_ptr1, *bus_info_ptr2;
int rc;
struct slot *tmp_slot;
- struct list_head *list;
+ char name[SLOT_NAME_SIZE];
addr = hpc_list_ptr->phys_addr;
for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) {
@@ -931,12 +900,6 @@ static int __init ebda_rsrc_controller (void)
goto error_no_hp_info;
}
- hp_slot_ptr->name = kmalloc(30, GFP_KERNEL);
- if (!hp_slot_ptr->name) {
- rc = -ENOMEM;
- goto error_no_hp_name;
- }
-
tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL);
if (!tmp_slot) {
rc = -ENOMEM;
@@ -997,12 +960,10 @@ static int __init ebda_rsrc_controller (void)
} /* each hpc */
- list_for_each (list, &ibmphp_slot_head) {
- tmp_slot = list_entry (list, struct slot, ibm_slot_list);
-
- snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
+ list_for_each_entry(tmp_slot, &ibmphp_slot_head, ibm_slot_list) {
+ snprintf(name, SLOT_NAME_SIZE, "%s", create_file_name(tmp_slot));
pci_hp_register(tmp_slot->hotplug_slot,
- pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
+ pci_find_bus(0, tmp_slot->bus), tmp_slot->device, name);
}
print_ebda_hpc ();
@@ -1012,8 +973,6 @@ static int __init ebda_rsrc_controller (void)
error:
kfree (hp_slot_ptr->private);
error_no_slot:
- kfree (hp_slot_ptr->name);
-error_no_hp_name:
kfree (hp_slot_ptr->info);
error_no_hp_info:
kfree (hp_slot_ptr);
@@ -1101,10 +1060,8 @@ u16 ibmphp_get_total_controllers (void)
struct slot *ibmphp_get_slot_from_physical_num (u8 physical_num)
{
struct slot *slot;
- struct list_head *list;
- list_for_each (list, &ibmphp_slot_head) {
- slot = list_entry (list, struct slot, ibm_slot_list);
+ list_for_each_entry(slot, &ibmphp_slot_head, ibm_slot_list) {
if (slot->number == physical_num)
return slot;
}
@@ -1120,10 +1077,8 @@ struct slot *ibmphp_get_slot_from_physical_num (u8 physical_num)
struct bus_info *ibmphp_find_same_bus_num (u32 num)
{
struct bus_info *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &bus_info_head) {
- ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+ list_for_each_entry(ptr, &bus_info_head, bus_info_list) {
if (ptr->busno == num)
return ptr;
}
@@ -1136,10 +1091,8 @@ struct bus_info *ibmphp_find_same_bus_num (u32 num)
int ibmphp_get_bus_index (u8 num)
{
struct bus_info *ptr;
- struct list_head *ptr1;
- list_for_each (ptr1, &bus_info_head) {
- ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+ list_for_each_entry(ptr, &bus_info_head, bus_info_list) {
if (ptr->busno == num)
return ptr->index;
}
@@ -1212,11 +1165,9 @@ static struct pci_driver ibmphp_driver = {
int ibmphp_register_pci (void)
{
struct controller *ctrl;
- struct list_head *tmp;
int rc = 0;
- list_for_each (tmp, &ebda_hpc_head) {
- ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
+ list_for_each_entry(ctrl, &ebda_hpc_head, ebda_hpc_list) {
if (ctrl->ctlr_type == 1) {
rc = pci_register_driver(&ibmphp_driver);
break;
@@ -1227,12 +1178,10 @@ int ibmphp_register_pci (void)
static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids)
{
struct controller *ctrl;
- struct list_head *tmp;
debug ("inside ibmphp_probe\n");
- list_for_each (tmp, &ebda_hpc_head) {
- ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
+ list_for_each_entry(ctrl, &ebda_hpc_head, ebda_hpc_list) {
if (ctrl->ctlr_type == 1) {
if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) {
ctrl->ctrl_dev = dev;
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 5f85b1b120e..535fce0f07f 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/namei.h>
+#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <asm/uaccess.h>
@@ -61,7 +62,7 @@ static int debug;
//////////////////////////////////////////////////////////////////
static LIST_HEAD(pci_hotplug_slot_list);
-static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock);
+static DEFINE_MUTEX(pci_hp_mutex);
/* these strings match up with the values in pci_bus_speed */
static char *pci_bus_speed_strings[] = {
@@ -102,13 +103,13 @@ static int get_##name (struct hotplug_slot *slot, type *value) \
{ \
struct hotplug_slot_ops *ops = slot->ops; \
int retval = 0; \
- if (try_module_get(ops->owner)) { \
- if (ops->get_##name) \
- retval = ops->get_##name(slot, value); \
- else \
- *value = slot->info->name; \
- module_put(ops->owner); \
- } \
+ if (!try_module_get(ops->owner)) \
+ return -ENODEV; \
+ if (ops->get_##name) \
+ retval = ops->get_##name(slot, value); \
+ else \
+ *value = slot->info->name; \
+ module_put(ops->owner); \
return retval; \
}
@@ -530,16 +531,12 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
struct hotplug_slot *slot;
struct list_head *tmp;
- spin_lock(&pci_hotplug_slot_list_lock);
list_for_each (tmp, &pci_hotplug_slot_list) {
slot = list_entry (tmp, struct hotplug_slot, slot_list);
- if (strcmp(slot->name, name) == 0)
- goto out;
+ if (strcmp(hotplug_slot_name(slot), name) == 0)
+ return slot;
}
- slot = NULL;
-out:
- spin_unlock(&pci_hotplug_slot_list_lock);
- return slot;
+ return NULL;
}
/**
@@ -547,13 +544,15 @@ out:
* @bus: bus this slot is on
* @slot: pointer to the &struct hotplug_slot to register
* @slot_nr: slot number
+ * @name: name registered with kobject core
*
* Registers a hotplug slot with the pci hotplug subsystem, which will allow
* userspace interaction to the slot.
*
* Returns 0 if successful, anything else for an error.
*/
-int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
+int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr,
+ const char *name)
{
int result;
struct pci_slot *pci_slot;
@@ -568,48 +567,29 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
return -EINVAL;
}
- /* Check if we have already registered a slot with the same name. */
- if (get_slot_from_name(slot->name))
- return -EEXIST;
+ mutex_lock(&pci_hp_mutex);
/*
* No problems if we call this interface from both ACPI_PCI_SLOT
* driver and call it here again. If we've already created the
* pci_slot, the interface will simply bump the refcount.
*/
- pci_slot = pci_create_slot(bus, slot_nr, slot->name);
- if (IS_ERR(pci_slot))
- return PTR_ERR(pci_slot);
-
- if (pci_slot->hotplug) {
- dbg("%s: already claimed\n", __func__);
- pci_destroy_slot(pci_slot);
- return -EBUSY;
+ pci_slot = pci_create_slot(bus, slot_nr, name, slot);
+ if (IS_ERR(pci_slot)) {
+ result = PTR_ERR(pci_slot);
+ goto out;
}
slot->pci_slot = pci_slot;
pci_slot->hotplug = slot;
- /*
- * Allow pcihp drivers to override the ACPI_PCI_SLOT name.
- */
- if (strcmp(kobject_name(&pci_slot->kobj), slot->name)) {
- result = kobject_rename(&pci_slot->kobj, slot->name);
- if (result) {
- pci_destroy_slot(pci_slot);
- return result;
- }
- }
-
- spin_lock(&pci_hotplug_slot_list_lock);
list_add(&slot->slot_list, &pci_hotplug_slot_list);
- spin_unlock(&pci_hotplug_slot_list_lock);
result = fs_add_slot(pci_slot);
kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
- dbg("Added slot %s to the list\n", slot->name);
-
-
+ dbg("Added slot %s to the list\n", name);
+out:
+ mutex_unlock(&pci_hp_mutex);
return result;
}
@@ -630,21 +610,23 @@ int pci_hp_deregister(struct hotplug_slot *hotplug)
if (!hotplug)
return -ENODEV;
- temp = get_slot_from_name(hotplug->name);
- if (temp != hotplug)
+ mutex_lock(&pci_hp_mutex);
+ temp = get_slot_from_name(hotplug_slot_name(hotplug));
+ if (temp != hotplug) {
+ mutex_unlock(&pci_hp_mutex);
return -ENODEV;
+ }
- spin_lock(&pci_hotplug_slot_list_lock);
list_del(&hotplug->slot_list);
- spin_unlock(&pci_hotplug_slot_list_lock);
slot = hotplug->pci_slot;
fs_remove_slot(slot);
- dbg("Removed slot %s from the list\n", hotplug->name);
+ dbg("Removed slot %s from the list\n", hotplug_slot_name(hotplug));
hotplug->release(hotplug);
slot->hotplug = NULL;
pci_destroy_slot(slot);
+ mutex_unlock(&pci_hp_mutex);
return 0;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 9e6cec67e1c..b2801a7ee37 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -57,19 +57,30 @@ extern struct workqueue_struct *pciehp_wq;
#define warn(format, arg...) \
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+#define ctrl_dbg(ctrl, format, arg...) \
+ do { \
+ if (pciehp_debug) \
+ dev_printk(, &ctrl->pcie->device, \
+ format, ## arg); \
+ } while (0)
+#define ctrl_err(ctrl, format, arg...) \
+ dev_err(&ctrl->pcie->device, format, ## arg)
+#define ctrl_info(ctrl, format, arg...) \
+ dev_info(&ctrl->pcie->device, format, ## arg)
+#define ctrl_warn(ctrl, format, arg...) \
+ dev_warn(&ctrl->pcie->device, format, ## arg)
+
#define SLOT_NAME_SIZE 10
struct slot {
u8 bus;
u8 device;
- u32 number;
u8 state;
- struct timer_list task_event;
u8 hp_slot;
+ u32 number;
struct controller *ctrl;
struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
- char name[SLOT_NAME_SIZE];
unsigned long last_emi_toggle;
struct delayed_work work; /* work for button event */
struct mutex lock;
@@ -87,6 +98,7 @@ struct controller {
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev;
+ struct pcie_device *pcie; /* PCI Express port service */
struct list_head slot_list;
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
@@ -98,6 +110,7 @@ struct controller {
struct timer_list poll_timer;
int cmd_busy;
unsigned int no_cmd_complete:1;
+ unsigned int link_active_reporting:1;
};
#define INT_BUTTON_IGNORE 0
@@ -161,6 +174,11 @@ int pciehp_enable_slot(struct slot *p_slot);
int pciehp_disable_slot(struct slot *p_slot);
int pcie_enable_notification(struct controller *ctrl);
+static inline const char *slot_name(struct slot *slot)
+{
+ return hotplug_slot_name(slot->hotplug_slot);
+}
+
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
struct slot *slot;
@@ -170,7 +188,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
return slot;
}
- err("%s: slot (device=0x%x) not found\n", __func__, device);
+ ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device);
return NULL;
}
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 4fd5355bc3b..4b23bc39b11 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -144,9 +144,10 @@ set_lock_exit:
* sysfs interface which allows the user to toggle the Electro Mechanical
* Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock
*/
-static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf,
- size_t count)
+static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot,
+ const char *buf, size_t count)
{
+ struct slot *slot = hotplug_slot->private;
unsigned long llock;
u8 lock;
int retval = 0;
@@ -157,10 +158,11 @@ static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf,
switch (lock) {
case 0:
case 1:
- retval = set_lock_status(slot, lock);
+ retval = set_lock_status(hotplug_slot, lock);
break;
default:
- err ("%d is an invalid lock value\n", lock);
+ ctrl_err(slot->ctrl, "%d is an invalid lock value\n",
+ lock);
retval = -EINVAL;
}
if (retval)
@@ -180,7 +182,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
*/
static void release_slot(struct hotplug_slot *hotplug_slot)
{
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ struct slot *slot = hotplug_slot->private;
+
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, hotplug_slot_name(hotplug_slot));
kfree(hotplug_slot->info);
kfree(hotplug_slot);
@@ -191,7 +196,7 @@ static int init_slots(struct controller *ctrl)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
- int len, dup = 1;
+ char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
@@ -205,46 +210,38 @@ static int init_slots(struct controller *ctrl)
/* register this slot with the hotplug pci core */
hotplug_slot->info = info;
- hotplug_slot->name = slot->name;
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
hotplug_slot->ops = &pciehp_hotplug_slot_ops;
- get_power_status(hotplug_slot, &info->power_status);
- get_attention_status(hotplug_slot, &info->attention_status);
- get_latch_status(hotplug_slot, &info->latch_status);
- get_adapter_status(hotplug_slot, &info->adapter_status);
slot->hotplug_slot = hotplug_slot;
+ snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
- dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
- "slot_device_offset=%x\n", slot->bus, slot->device,
- slot->hp_slot, slot->number, ctrl->slot_device_offset);
-duplicate_name:
+ ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x "
+ "hp_slot=%x sun=%x slot_device_offset=%x\n",
+ pci_domain_nr(ctrl->pci_dev->subordinate),
+ slot->bus, slot->device, slot->hp_slot, slot->number,
+ ctrl->slot_device_offset);
retval = pci_hp_register(hotplug_slot,
ctrl->pci_dev->subordinate,
- slot->device);
+ slot->device,
+ name);
if (retval) {
- /*
- * If slot N already exists, we'll try to create
- * slot N-1, N-2 ... N-M, until we overflow.
- */
- if (retval == -EEXIST) {
- len = snprintf(slot->name, SLOT_NAME_SIZE,
- "%d-%d", slot->number, dup++);
- if (len < SLOT_NAME_SIZE)
- goto duplicate_name;
- else
- err("duplicate slot name overflow\n");
- }
- err("pci_hp_register failed with error %d\n", retval);
+ ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
+ retval);
goto error_info;
}
+ get_power_status(hotplug_slot, &info->power_status);
+ get_attention_status(hotplug_slot, &info->attention_status);
+ get_latch_status(hotplug_slot, &info->latch_status);
+ get_adapter_status(hotplug_slot, &info->adapter_status);
/* create additional sysfs entries */
if (EMI(ctrl)) {
retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
if (retval) {
pci_hp_deregister(hotplug_slot);
- err("cannot create additional sysfs entries\n");
+ ctrl_err(ctrl, "Cannot create additional sysfs "
+ "entries\n");
goto error_info;
}
}
@@ -278,7 +275,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
hotplug_slot->info->attention_status = status;
@@ -293,7 +291,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
return pciehp_sysfs_enable_slot(slot);
}
@@ -303,7 +302,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
return pciehp_sysfs_disable_slot(slot);
}
@@ -313,7 +313,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_power_status(slot, value);
if (retval < 0)
@@ -327,7 +328,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_attention_status(slot, value);
if (retval < 0)
@@ -341,7 +343,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_latch_status(slot, value);
if (retval < 0)
@@ -355,7 +358,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_adapter_status(slot, value);
if (retval < 0)
@@ -370,7 +374,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_max_bus_speed(slot, value);
if (retval < 0)
@@ -384,7 +389,8 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
struct slot *slot = hotplug_slot->private;
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
if (retval < 0)
@@ -402,14 +408,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
struct pci_dev *pdev = dev->port;
if (pciehp_force)
- dbg("Bypassing BIOS check for pciehp use on %s\n",
- pci_name(pdev));
+ dev_info(&dev->device,
+ "Bypassing BIOS check for pciehp use on %s\n",
+ pci_name(pdev));
else if (pciehp_get_hp_hw_control_from_firmware(pdev))
goto err_out_none;
ctrl = pcie_init(dev);
if (!ctrl) {
- dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
+ dev_err(&dev->device, "Controller initialization failed\n");
goto err_out_none;
}
set_service_data(dev, ctrl);
@@ -418,11 +425,10 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
rc = init_slots(ctrl);
if (rc) {
if (rc == -EBUSY)
- warn("%s: slot already registered by another "
- "hotplug driver\n", PCIE_MODULE_NAME);
+ ctrl_warn(ctrl, "Slot already registered by another "
+ "hotplug driver\n");
else
- err("%s: slot initialization failed\n",
- PCIE_MODULE_NAME);
+ ctrl_err(ctrl, "Slot initialization failed\n");
goto err_out_release_ctlr;
}
@@ -461,13 +467,13 @@ static void pciehp_remove (struct pcie_device *dev)
#ifdef CONFIG_PM
static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
{
- printk("%s ENTRY\n", __func__);
+ dev_info(&dev->device, "%s ENTRY\n", __func__);
return 0;
}
static int pciehp_resume (struct pcie_device *dev)
{
- printk("%s ENTRY\n", __func__);
+ dev_info(&dev->device, "%s ENTRY\n", __func__);
if (pciehp_force) {
struct controller *ctrl = get_service_data(dev);
struct slot *t_slot;
@@ -497,10 +503,9 @@ static struct pcie_port_service_id port_pci_ids[] = { {
.driver_data = 0,
}, { /* end: all zeroes */ }
};
-static const char device_name[] = "hpdriver";
static struct pcie_port_service_driver hpdriver_portdrv = {
- .name = (char *)device_name,
+ .name = PCIE_MODULE_NAME,
.id_table = &port_pci_ids[0],
.probe = pciehp_probe,
@@ -520,7 +525,7 @@ static int __init pcied_init(void)
dbg("pcie_port_service_register = %d\n", retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
if (retval)
- dbg("%s: Failure to register service\n", __func__);
+ dbg("Failure to register service\n");
return retval;
}
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 96a5d55a498..fead63c6b49 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -58,14 +58,15 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
u8 pciehp_handle_attention_button(struct slot *p_slot)
{
u32 event_type;
+ struct controller *ctrl = p_slot->ctrl;
/* Attention Button Change */
- dbg("pciehp: Attention button interrupt received.\n");
+ ctrl_dbg(ctrl, "Attention button interrupt received\n");
/*
* Button pressed - See if need to TAKE ACTION!!!
*/
- info("Button pressed on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
event_type = INT_BUTTON_PRESS;
queue_interrupt_event(p_slot, event_type);
@@ -77,22 +78,23 @@ u8 pciehp_handle_switch_change(struct slot *p_slot)
{
u8 getstatus;
u32 event_type;
+ struct controller *ctrl = p_slot->ctrl;
/* Switch Change */
- dbg("pciehp: Switch interrupt received.\n");
+ ctrl_dbg(ctrl, "Switch interrupt received\n");
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (getstatus) {
/*
* Switch opened
*/
- info("Latch open on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_OPEN;
} else {
/*
* Switch closed
*/
- info("Latch close on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_CLOSE;
}
@@ -105,9 +107,10 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
{
u32 event_type;
u8 presence_save;
+ struct controller *ctrl = p_slot->ctrl;
/* Presence Change */
- dbg("pciehp: Presence/Notify input change.\n");
+ ctrl_dbg(ctrl, "Presence/Notify input change\n");
/* Switch is open, assume a presence change
* Save the presence state
@@ -117,13 +120,14 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
/*
* Card Present
*/
- info("Card present on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot));
event_type = INT_PRESENCE_ON;
} else {
/*
* Not Present
*/
- info("Card not present on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Card not present on Slot(%s)\n",
+ slot_name(p_slot));
event_type = INT_PRESENCE_OFF;
}
@@ -135,23 +139,25 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
u8 pciehp_handle_power_fault(struct slot *p_slot)
{
u32 event_type;
+ struct controller *ctrl = p_slot->ctrl;
/* power fault */
- dbg("pciehp: Power fault interrupt received.\n");
+ ctrl_dbg(ctrl, "Power fault interrupt received\n");
if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
/*
* power fault Cleared
*/
- info("Power fault cleared on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
+ slot_name(p_slot));
event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
* power fault
*/
- info("Power fault on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
- info("power fault bit %x set\n", 0);
+ ctrl_info(ctrl, "Power fault bit %x set\n", 0);
}
queue_interrupt_event(p_slot, event_type);
@@ -168,8 +174,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
if (POWER_CTRL(ctrl)) {
if (pslot->hpc_ops->power_off_slot(pslot)) {
- err("%s: Issue of Slot Power Off command failed\n",
- __func__);
+ ctrl_err(ctrl,
+ "Issue of Slot Power Off command failed\n");
return;
}
}
@@ -186,8 +192,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
if (ATTN_LED(ctrl)) {
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
- err("%s: Issue of Set Attention Led command failed\n",
- __func__);
+ ctrl_err(ctrl,
+ "Issue of Set Attention Led command failed\n");
return;
}
}
@@ -204,10 +210,11 @@ static int board_added(struct slot *p_slot)
{
int retval = 0;
struct controller *ctrl = p_slot->ctrl;
+ struct pci_bus *parent = ctrl->pci_dev->subordinate;
- dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
- __func__, p_slot->device,
- ctrl->slot_device_offset, p_slot->hp_slot);
+ ctrl_dbg(ctrl, "%s: slot device, slot offset, hp slot = %d, %d, %d\n",
+ __func__, p_slot->device, ctrl->slot_device_offset,
+ p_slot->hp_slot);
if (POWER_CTRL(ctrl)) {
/* Power on slot */
@@ -219,28 +226,25 @@ static int board_added(struct slot *p_slot)
if (PWR_LED(ctrl))
p_slot->hpc_ops->green_led_blink(p_slot);
- /* Wait for ~1 second */
- msleep(1000);
-
/* Check link training status */
retval = p_slot->hpc_ops->check_lnk_status(ctrl);
if (retval) {
- err("%s: Failed to check link status\n", __func__);
+ ctrl_err(ctrl, "Failed to check link status\n");
set_slot_off(ctrl, p_slot);
return retval;
}
/* Check for a power fault */
if (p_slot->hpc_ops->query_power_fault(p_slot)) {
- dbg("%s: power fault detected\n", __func__);
+ ctrl_dbg(ctrl, "Power fault detected\n");
retval = POWER_FAILURE;
goto err_exit;
}
retval = pciehp_configure_device(p_slot);
if (retval) {
- err("Cannot add device 0x%x:%x\n", p_slot->bus,
- p_slot->device);
+ ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n",
+ pci_domain_nr(parent), p_slot->bus, p_slot->device);
goto err_exit;
}
@@ -272,14 +276,14 @@ static int remove_board(struct slot *p_slot)
if (retval)
return retval;
- dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
+ ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, p_slot->hp_slot);
if (POWER_CTRL(ctrl)) {
/* power off slot */
retval = p_slot->hpc_ops->power_off_slot(p_slot);
if (retval) {
- err("%s: Issue of Slot Disable command failed\n",
- __func__);
+ ctrl_err(ctrl,
+ "Issue of Slot Disable command failed\n");
return retval;
}
}
@@ -320,8 +324,10 @@ static void pciehp_power_thread(struct work_struct *work)
switch (p_slot->state) {
case POWEROFF_STATE:
mutex_unlock(&p_slot->lock);
- dbg("%s: disabling bus:device(%x:%x)\n",
- __func__, p_slot->bus, p_slot->device);
+ ctrl_dbg(p_slot->ctrl,
+ "Disabling domain:bus:device=%04x:%02x:%02x\n",
+ pci_domain_nr(p_slot->ctrl->pci_dev->subordinate),
+ p_slot->bus, p_slot->device);
pciehp_disable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
@@ -349,7 +355,8 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
- err("%s: Cannot allocate memory\n", __func__);
+ ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
+ __func__);
return;
}
info->p_slot = p_slot;
@@ -403,12 +410,14 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = BLINKINGOFF_STATE;
- info("PCI slot #%s - powering off due to button "
- "press.\n", p_slot->name);
+ ctrl_info(ctrl,
+ "PCI slot #%s - powering off due to button "
+ "press.\n", slot_name(p_slot));
} else {
p_slot->state = BLINKINGON_STATE;
- info("PCI slot #%s - powering on due to button "
- "press.\n", p_slot->name);
+ ctrl_info(ctrl,
+ "PCI slot #%s - powering on due to button "
+ "press.\n", slot_name(p_slot));
}
/* blink green LED and turn off amber */
if (PWR_LED(ctrl))
@@ -425,8 +434,7 @@ static void handle_button_press_event(struct slot *p_slot)
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
- info("Button cancel on Slot(%s)\n", p_slot->name);
- dbg("%s: button cancel\n", __func__);
+ ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE) {
if (PWR_LED(ctrl))
@@ -437,8 +445,8 @@ static void handle_button_press_event(struct slot *p_slot)
}
if (ATTN_LED(ctrl))
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- info("PCI slot #%s - action canceled due to button press\n",
- p_slot->name);
+ ctrl_info(ctrl, "PCI slot #%s - action canceled "
+ "due to button press\n", slot_name(p_slot));
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
@@ -448,11 +456,11 @@ static void handle_button_press_event(struct slot *p_slot)
* this means that the previous attention button action
* to hot-add or hot-remove is undergoing
*/
- info("Button ignore on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
update_slot_info(p_slot);
break;
default:
- warn("Not a valid state\n");
+ ctrl_warn(ctrl, "Not a valid state\n");
break;
}
}
@@ -467,7 +475,8 @@ static void handle_surprise_event(struct slot *p_slot)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
- err("%s: Cannot allocate memory\n", __func__);
+ ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
+ __func__);
return;
}
info->p_slot = p_slot;
@@ -505,7 +514,7 @@ static void interrupt_event_handler(struct work_struct *work)
case INT_PRESENCE_OFF:
if (!HP_SUPR_RM(ctrl))
break;
- dbg("Surprise Removal\n");
+ ctrl_dbg(ctrl, "Surprise Removal\n");
update_slot_info(p_slot);
handle_surprise_event(p_slot);
break;
@@ -522,22 +531,22 @@ int pciehp_enable_slot(struct slot *p_slot)
{
u8 getstatus = 0;
int rc;
+ struct controller *ctrl = p_slot->ctrl;
/* Check to see if (latch closed, card present, power off) */
mutex_lock(&p_slot->ctrl->crit_sect);
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) {
- info("%s: no adapter on slot(%s)\n", __func__,
- p_slot->name);
+ ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
if (MRL_SENS(p_slot->ctrl)) {
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("%s: latch open on slot(%s)\n", __func__,
- p_slot->name);
+ ctrl_info(ctrl, "Latch open on slot(%s)\n",
+ slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
@@ -546,8 +555,8 @@ int pciehp_enable_slot(struct slot *p_slot)
if (POWER_CTRL(p_slot->ctrl)) {
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("%s: already enabled on slot(%s)\n", __func__,
- p_slot->name);
+ ctrl_info(ctrl, "Already enabled on slot(%s)\n",
+ slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
@@ -571,6 +580,7 @@ int pciehp_disable_slot(struct slot *p_slot)
{
u8 getstatus = 0;
int ret = 0;
+ struct controller *ctrl = p_slot->ctrl;
if (!p_slot->ctrl)
return 1;
@@ -581,8 +591,8 @@ int pciehp_disable_slot(struct slot *p_slot)
if (!HP_SUPR_RM(p_slot->ctrl)) {
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (ret || !getstatus) {
- info("%s: no adapter on slot(%s)\n", __func__,
- p_slot->name);
+ ctrl_info(ctrl, "No adapter on slot(%s)\n",
+ slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
@@ -591,8 +601,8 @@ int pciehp_disable_slot(struct slot *p_slot)
if (MRL_SENS(p_slot->ctrl)) {
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (ret || getstatus) {
- info("%s: latch open on slot(%s)\n", __func__,
- p_slot->name);
+ ctrl_info(ctrl, "Latch open on slot(%s)\n",
+ slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
@@ -601,8 +611,8 @@ int pciehp_disable_slot(struct slot *p_slot)
if (POWER_CTRL(p_slot->ctrl)) {
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (ret || !getstatus) {
- info("%s: already disabled slot(%s)\n", __func__,
- p_slot->name);
+ ctrl_info(ctrl, "Already disabled on slot(%s)\n",
+ slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
@@ -618,6 +628,7 @@ int pciehp_disable_slot(struct slot *p_slot)
int pciehp_sysfs_enable_slot(struct slot *p_slot)
{
int retval = -ENODEV;
+ struct controller *ctrl = p_slot->ctrl;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
@@ -631,15 +642,17 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
p_slot->state = STATIC_STATE;
break;
case POWERON_STATE:
- info("Slot %s is already in powering on state\n",
- p_slot->name);
+ ctrl_info(ctrl, "Slot %s is already in powering on state\n",
+ slot_name(p_slot));
break;
case BLINKINGOFF_STATE:
case POWEROFF_STATE:
- info("Already enabled on slot %s\n", p_slot->name);
+ ctrl_info(ctrl, "Already enabled on slot %s\n",
+ slot_name(p_slot));
break;
default:
- err("Not a valid state on slot %s\n", p_slot->name);
+ ctrl_err(ctrl, "Not a valid state on slot %s\n",
+ slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
@@ -650,6 +663,7 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
int pciehp_sysfs_disable_slot(struct slot *p_slot)
{
int retval = -ENODEV;
+ struct controller *ctrl = p_slot->ctrl;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
@@ -663,15 +677,17 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot)
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
- info("Slot %s is already in powering off state\n",
- p_slot->name);
+ ctrl_info(ctrl, "Slot %s is already in powering off state\n",
+ slot_name(p_slot));
break;
case BLINKINGON_STATE:
case POWERON_STATE:
- info("Already disabled on slot %s\n", p_slot->name);
+ ctrl_info(ctrl, "Already disabled on slot %s\n",
+ slot_name(p_slot));
break;
default:
- err("Not a valid state on slot %s\n", p_slot->name);
+ ctrl_err(ctrl, "Not a valid state on slot %s\n",
+ slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9d934ddee95..b643ca13e4f 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -125,6 +125,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
/* Field definitions in Link Capabilities Register */
#define MAX_LNK_SPEED 0x000F
#define MAX_LNK_WIDTH 0x03F0
+#define LINK_ACTIVE_REPORTING 0x00100000
/* Link Width Encoding */
#define LNK_X1 0x01
@@ -141,6 +142,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
#define LNK_TRN_ERR 0x0400
#define LNK_TRN 0x0800
#define SLOT_CLK_CONF 0x1000
+#define LINK_ACTIVE 0x2000
/* Field definitions in Slot Capabilities Register */
#define ATTN_BUTTN_PRSN 0x00000001
@@ -223,7 +225,7 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
static inline int pciehp_request_irq(struct controller *ctrl)
{
- int retval, irq = ctrl->pci_dev->irq;
+ int retval, irq = ctrl->pcie->irq;
/* Install interrupt polling timer. Start with 10 sec delay */
if (pciehp_poll_mode) {
@@ -235,7 +237,8 @@ static inline int pciehp_request_irq(struct controller *ctrl)
/* Installs the interrupt handler */
retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
if (retval)
- err("Cannot get irq %d for the hotplug controller\n", irq);
+ ctrl_err(ctrl, "Cannot get irq %d for the hotplug controller\n",
+ irq);
return retval;
}
@@ -244,7 +247,7 @@ static inline void pciehp_free_irq(struct controller *ctrl)
if (pciehp_poll_mode)
del_timer_sync(&ctrl->poll_timer);
else
- free_irq(ctrl->pci_dev->irq, ctrl);
+ free_irq(ctrl->pcie->irq, ctrl);
}
static int pcie_poll_cmd(struct controller *ctrl)
@@ -282,7 +285,7 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll)
else
rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
if (!rc)
- dbg("Command not completed in 1000 msec\n");
+ ctrl_dbg(ctrl, "Command not completed in 1000 msec\n");
}
/**
@@ -301,7 +304,8 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
- err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
+ __func__);
goto out;
}
@@ -312,26 +316,25 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
* proceed forward to issue the next command according
* to spec. Just print out the error message.
*/
- dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
- __func__);
+ ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n");
} else if (!NO_CMD_CMPL(ctrl)) {
/*
* This controller semms to notify of command completed
* event even though it supports none of power
* controller, attention led, power led and EMI.
*/
- dbg("%s: Unexpected CMD_COMPLETED. Need to wait for "
- "command completed event.\n", __func__);
+ ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to "
+ "wait for command completed event.\n");
ctrl->no_cmd_complete = 0;
} else {
- dbg("%s: Unexpected CMD_COMPLETED. Maybe the "
- "controller is broken.\n", __func__);
+ ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe "
+ "the controller is broken.\n");
}
}
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
- err("%s: Cannot read SLOTCTRL register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
goto out;
}
@@ -341,7 +344,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
smp_mb();
retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
if (retval)
- err("%s: Cannot write to SLOTCTRL register\n", __func__);
+ ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n");
/*
* Wait for command completion.
@@ -363,21 +366,62 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
return retval;
}
+static inline int check_link_active(struct controller *ctrl)
+{
+ u16 link_status;
+
+ if (pciehp_readw(ctrl, LNKSTATUS, &link_status))
+ return 0;
+ return !!(link_status & LINK_ACTIVE);
+}
+
+static void pcie_wait_link_active(struct controller *ctrl)
+{
+ int timeout = 1000;
+
+ if (check_link_active(ctrl))
+ return;
+ while (timeout > 0) {
+ msleep(10);
+ timeout -= 10;
+ if (check_link_active(ctrl))
+ return;
+ }
+ ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n");
+}
+
static int hpc_check_lnk_status(struct controller *ctrl)
{
u16 lnk_status;
int retval = 0;
+ /*
+ * Data Link Layer Link Active Reporting must be capable for
+ * hot-plug capable downstream port. But old controller might
+ * not implement it. In this case, we wait for 1000 ms.
+ */
+ if (ctrl->link_active_reporting){
+ /* Wait for Data Link Layer Link Active bit to be set */
+ pcie_wait_link_active(ctrl);
+ /*
+ * We must wait for 100 ms after the Data Link Layer
+ * Link Active bit reads 1b before initiating a
+ * configuration access to the hot added device.
+ */
+ msleep(100);
+ } else
+ msleep(1000);
+
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
if (retval) {
- err("%s: Cannot read LNKSTATUS register\n", __func__);
+ ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
return retval;
}
- dbg("%s: lnk_status = %x\n", __func__, lnk_status);
+ ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
!(lnk_status & NEG_LINK_WD)) {
- err("%s : Link Training Error occurs \n", __func__);
+ ctrl_err(ctrl, "Link Training Error occurs \n");
retval = -1;
return retval;
}
@@ -394,12 +438,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
- err("%s: Cannot read SLOTCTRL register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
return retval;
}
- dbg("%s: SLOTCTRL %x, value read %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
@@ -433,11 +477,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
- err("%s: Cannot read SLOTCTRL register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
return retval;
}
- dbg("%s: SLOTCTRL %x value read %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
@@ -464,7 +508,8 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
- err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
+ __func__);
return retval;
}
@@ -482,7 +527,8 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
- err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
+ __func__);
return retval;
}
card_state = (u8)((slot_status & PRSN_STATE) >> 6);
@@ -500,7 +546,7 @@ static int hpc_query_power_fault(struct slot *slot)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
- err("%s: Cannot check for power fault\n", __func__);
+ ctrl_err(ctrl, "Cannot check for power fault\n");
return retval;
}
pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
@@ -516,7 +562,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
- err("%s : Cannot check EMI status\n", __func__);
+ ctrl_err(ctrl, "Cannot check EMI status\n");
return retval;
}
*status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
@@ -560,8 +606,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
return -1;
}
rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- dbg("%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
return rc;
}
@@ -575,8 +621,8 @@ static void hpc_set_green_led_on(struct slot *slot)
slot_cmd = 0x0100;
cmd_mask = PWR_LED_CTRL;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- dbg("%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
}
static void hpc_set_green_led_off(struct slot *slot)
@@ -588,8 +634,8 @@ static void hpc_set_green_led_off(struct slot *slot)
slot_cmd = 0x0300;
cmd_mask = PWR_LED_CTRL;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- dbg("%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
}
static void hpc_set_green_led_blink(struct slot *slot)
@@ -601,8 +647,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
slot_cmd = 0x0200;
cmd_mask = PWR_LED_CTRL;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- dbg("%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
}
static int hpc_power_on_slot(struct slot * slot)
@@ -613,20 +659,22 @@ static int hpc_power_on_slot(struct slot * slot)
u16 slot_status;
int retval = 0;
- dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
+ ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
/* Clear sticky power-fault bit from previous power failures */
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (retval) {
- err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
+ __func__);
return retval;
}
slot_status &= PWR_FAULT_DETECTED;
if (slot_status) {
retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
if (retval) {
- err("%s: Cannot write to SLOTSTATUS register\n",
- __func__);
+ ctrl_err(ctrl,
+ "%s: Cannot write to SLOTSTATUS register\n",
+ __func__);
return retval;
}
}
@@ -644,11 +692,11 @@ static int hpc_power_on_slot(struct slot * slot)
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
- err("%s: Write %x command failed!\n", __func__, slot_cmd);
+ ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
return -1;
}
- dbg("%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
return retval;
}
@@ -694,7 +742,7 @@ static int hpc_power_off_slot(struct slot * slot)
int retval = 0;
int changed;
- dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
+ ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
/*
* Set Bad DLLP Mask bit in Correctable Error Mask
@@ -722,12 +770,12 @@ static int hpc_power_off_slot(struct slot * slot)
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
- err("%s: Write command failed!\n", __func__);
+ ctrl_err(ctrl, "Write command failed!\n");
retval = -1;
goto out;
}
- dbg("%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
+ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
out:
if (changed)
pcie_unmask_bad_dllp(ctrl);
@@ -749,7 +797,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
intr_loc = 0;
do {
if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
- err("%s: Cannot read SLOTSTATUS\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n",
+ __func__);
return IRQ_NONE;
}
@@ -760,12 +809,13 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
if (!intr_loc)
return IRQ_NONE;
if (detected && pciehp_writew(ctrl, SLOTSTATUS, detected)) {
- err("%s: Cannot write to SLOTSTATUS\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n",
+ __func__);
return IRQ_NONE;
}
} while (detected);
- dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
+ ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc);
/* Check Command Complete Interrupt Pending */
if (intr_loc & CMD_COMPLETED) {
@@ -807,7 +857,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
if (retval) {
- err("%s: Cannot read LNKCAP register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
return retval;
}
@@ -821,7 +871,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
}
*value = lnk_speed;
- dbg("Max link speed = %d\n", lnk_speed);
+ ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed);
return retval;
}
@@ -836,7 +886,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
if (retval) {
- err("%s: Cannot read LNKCAP register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
return retval;
}
@@ -871,7 +921,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
}
*value = lnk_wdth;
- dbg("Max link width = %d\n", lnk_wdth);
+ ctrl_dbg(ctrl, "Max link width = %d\n", lnk_wdth);
return retval;
}
@@ -885,7 +935,8 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
if (retval) {
- err("%s: Cannot read LNKSTATUS register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
+ __func__);
return retval;
}
@@ -899,7 +950,7 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
}
*value = lnk_speed;
- dbg("Current link speed = %d\n", lnk_speed);
+ ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed);
return retval;
}
@@ -914,7 +965,8 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
if (retval) {
- err("%s: Cannot read LNKSTATUS register\n", __func__);
+ ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
+ __func__);
return retval;
}
@@ -949,7 +1001,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
}
*value = lnk_wdth;
- dbg("Current link width = %d\n", lnk_wdth);
+ ctrl_dbg(ctrl, "Current link width = %d\n", lnk_wdth);
return retval;
}
@@ -998,7 +1050,7 @@ int pcie_enable_notification(struct controller *ctrl)
PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
if (pcie_write_cmd(ctrl, cmd, mask)) {
- err("%s: Cannot enable software notification\n", __func__);
+ ctrl_err(ctrl, "Cannot enable software notification\n");
return -1;
}
return 0;
@@ -1010,7 +1062,7 @@ static void pcie_disable_notification(struct controller *ctrl)
mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
if (pcie_write_cmd(ctrl, 0, mask))
- warn("%s: Cannot disable software notification\n", __func__);
+ ctrl_warn(ctrl, "Cannot disable software notification\n");
}
static int pcie_init_notification(struct controller *ctrl)
@@ -1044,7 +1096,6 @@ static int pcie_init_slot(struct controller *ctrl)
slot->device = ctrl->slot_device_offset + slot->hp_slot;
slot->hpc_ops = ctrl->hpc_ops;
slot->number = ctrl->first_slot;
- snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
mutex_init(&slot->lock);
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
list_add(&slot->slot_list, &ctrl->slot_list);
@@ -1071,58 +1122,70 @@ static inline void dbg_ctrl(struct controller *ctrl)
if (!pciehp_debug)
return;
- dbg("Hotplug Controller:\n");
- dbg(" Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq);
- dbg(" Vendor ID : 0x%04x\n", pdev->vendor);
- dbg(" Device ID : 0x%04x\n", pdev->device);
- dbg(" Subsystem ID : 0x%04x\n", pdev->subsystem_device);
- dbg(" Subsystem Vendor ID : 0x%04x\n", pdev->subsystem_vendor);
- dbg(" PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
+ ctrl_info(ctrl, "Hotplug Controller:\n");
+ ctrl_info(ctrl, " Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n",
+ pci_name(pdev), pdev->irq);
+ ctrl_info(ctrl, " Vendor ID : 0x%04x\n", pdev->vendor);
+ ctrl_info(ctrl, " Device ID : 0x%04x\n", pdev->device);
+ ctrl_info(ctrl, " Subsystem ID : 0x%04x\n",
+ pdev->subsystem_device);
+ ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n",
+ pdev->subsystem_vendor);
+ ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
if (!pci_resource_len(pdev, i))
continue;
- dbg(" PCI resource [%d] : 0x%llx@0x%llx\n", i,
- (unsigned long long)pci_resource_len(pdev, i),
- (unsigned long long)pci_resource_start(pdev, i));
+ ctrl_info(ctrl, " PCI resource [%d] : 0x%llx@0x%llx\n",
+ i, (unsigned long long)pci_resource_len(pdev, i),
+ (unsigned long long)pci_resource_start(pdev, i));
}
- dbg("Slot Capabilities : 0x%08x\n", ctrl->slot_cap);
- dbg(" Physical Slot Number : %d\n", ctrl->first_slot);
- dbg(" Attention Button : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no");
- dbg(" Power Controller : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no");
- dbg(" MRL Sensor : %3s\n", MRL_SENS(ctrl) ? "yes" : "no");
- dbg(" Attention Indicator : %3s\n", ATTN_LED(ctrl) ? "yes" : "no");
- dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
- dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
- dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
- dbg(" Command Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
+ ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap);
+ ctrl_info(ctrl, " Physical Slot Number : %d\n", ctrl->first_slot);
+ ctrl_info(ctrl, " Attention Button : %3s\n",
+ ATTN_BUTTN(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " Power Controller : %3s\n",
+ POWER_CTRL(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " MRL Sensor : %3s\n",
+ MRL_SENS(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " Attention Indicator : %3s\n",
+ ATTN_LED(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " Power Indicator : %3s\n",
+ PWR_LED(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " Hot-Plug Surprise : %3s\n",
+ HP_SUPR_RM(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " EMI Present : %3s\n",
+ EMI(ctrl) ? "yes" : "no");
+ ctrl_info(ctrl, " Command Completed : %3s\n",
+ NO_CMD_CMPL(ctrl) ? "no" : "yes");
pciehp_readw(ctrl, SLOTSTATUS, &reg16);
- dbg("Slot Status : 0x%04x\n", reg16);
+ ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16);
pciehp_readw(ctrl, SLOTCTRL, &reg16);
- dbg("Slot Control : 0x%04x\n", reg16);
+ ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16);
}
struct controller *pcie_init(struct pcie_device *dev)
{
struct controller *ctrl;
- u32 slot_cap;
+ u32 slot_cap, link_cap;
struct pci_dev *pdev = dev->port;
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl) {
- err("%s : out of memory\n", __func__);
+ dev_err(&dev->device, "%s: Out of memory\n", __func__);
goto abort;
}
INIT_LIST_HEAD(&ctrl->slot_list);
+ ctrl->pcie = dev;
ctrl->pci_dev = pdev;
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
if (!ctrl->cap_base) {
- err("%s: Cannot find PCI Express capability\n", __func__);
- goto abort;
+ ctrl_err(ctrl, "Cannot find PCI Express capability\n");
+ goto abort_ctrl;
}
if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
- err("%s: Cannot read SLOTCAP register\n", __func__);
- goto abort;
+ ctrl_err(ctrl, "Cannot read SLOTCAP register\n");
+ goto abort_ctrl;
}
ctrl->slot_cap = slot_cap;
@@ -1144,6 +1207,16 @@ struct controller *pcie_init(struct pcie_device *dev)
!(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
ctrl->no_cmd_complete = 1;
+ /* Check if Data Link Layer Link Active Reporting is implemented */
+ if (pciehp_readl(ctrl, LNKCAP, &link_cap)) {
+ ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
+ goto abort_ctrl;
+ }
+ if (link_cap & LINK_ACTIVE_REPORTING) {
+ ctrl_dbg(ctrl, "Link Active Reporting supported\n");
+ ctrl->link_active_reporting = 1;
+ }
+
/* Clear all remaining event bits in Slot Status register */
if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f))
goto abort_ctrl;
@@ -1161,9 +1234,9 @@ struct controller *pcie_init(struct pcie_device *dev)
goto abort_ctrl;
}
- info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
- pdev->vendor, pdev->device,
- pdev->subsystem_vendor, pdev->subsystem_device);
+ ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
+ pdev->vendor, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
if (pcie_init_slot(ctrl))
goto abort_ctrl;
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 6040dcceb25..10f9566ccee 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -39,8 +39,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
u16 pci_cmd, pci_bctl;
if (hpp->revision > 1) {
- printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n",
- __func__, hpp->revision);
+ warn("Rev.%d type0 record not supported\n", hpp->revision);
return;
}
@@ -81,8 +80,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
u32 reg32;
if (hpp->revision > 1) {
- printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n",
- __func__, hpp->revision);
+ warn("Rev.%d type2 record not supported\n", hpp->revision);
return;
}
@@ -149,8 +147,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
return;
if (pciehp_get_hp_params_from_firmware(dev, &hpp)) {
- printk(KERN_WARNING "%s: Could not get hotplug parameters\n",
- __func__);
+ warn("Could not get hotplug parameters\n");
return;
}
@@ -198,18 +195,20 @@ int pciehp_configure_device(struct slot *p_slot)
struct pci_dev *dev;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
int num, fn;
+ struct controller *ctrl = p_slot->ctrl;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) {
- err("Device %s already exists at %x:%x, cannot hot-add\n",
- pci_name(dev), p_slot->bus, p_slot->device);
+ ctrl_err(ctrl, "Device %s already exists "
+ "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev),
+ pci_domain_nr(parent), p_slot->bus, p_slot->device);
pci_dev_put(dev);
return -EINVAL;
}
num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (num == 0) {
- err("No new device found\n");
+ ctrl_err(ctrl, "No new device found\n");
return -ENODEV;
}
@@ -218,8 +217,8 @@ int pciehp_configure_device(struct slot *p_slot)
if (!dev)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- err("Cannot hot-add display device %s\n",
- pci_name(dev));
+ ctrl_err(ctrl, "Cannot hot-add display device %s\n",
+ pci_name(dev));
pci_dev_put(dev);
continue;
}
@@ -244,9 +243,10 @@ int pciehp_unconfigure_device(struct slot *p_slot)
u8 presence = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
u16 command;
+ struct controller *ctrl = p_slot->ctrl;
- dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus,
- p_slot->device);
+ ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
+ __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
if (ret)
presence = 0;
@@ -257,16 +257,17 @@ int pciehp_unconfigure_device(struct slot *p_slot)
if (!temp)
continue;
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- err("Cannot remove display device %s\n",
- pci_name(temp));
+ ctrl_err(ctrl, "Cannot remove display device %s\n",
+ pci_name(temp));
pci_dev_put(temp);
continue;
}
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
- err("Cannot remove display device %s\n",
- pci_name(temp));
+ ctrl_err(ctrl,
+ "Cannot remove display device %s\n",
+ pci_name(temp));
pci_dev_put(temp);
continue;
}
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 7d5921b1ee7..419919a87b0 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -46,10 +46,10 @@
#define PRESENT 1 /* Card in slot */
#define MY_NAME "rpaphp"
-extern int debug;
+extern int rpaphp_debug;
#define dbg(format, arg...) \
do { \
- if (debug) \
+ if (rpaphp_debug) \
printk(KERN_DEBUG "%s: " format, \
MY_NAME , ## arg); \
} while (0)
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 1f84f402acd..95d02a08fdc 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -37,7 +37,7 @@
/* and pci_do_scan_bus */
#include "rpaphp.h"
-int debug;
+int rpaphp_debug;
LIST_HEAD(rpaphp_slot_head);
#define DRIVER_VERSION "0.1"
@@ -50,7 +50,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(debug, bool, 0644);
+module_param_named(debug, rpaphp_debug, bool, 0644);
/**
* set_attention_status - set attention LED
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 5acfd4f3d4c..513e1e28239 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -123,7 +123,7 @@ int rpaphp_enable_slot(struct slot *slot)
slot->state = CONFIGURED;
}
- if (debug) {
+ if (rpaphp_debug) {
struct pci_dev *dev;
dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
list_for_each_entry (dev, &bus->devices, bus_list)
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 50884507b8b..2ea9cf1a8d0 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -43,7 +43,7 @@ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
void dealloc_slot_struct(struct slot *slot)
{
kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
+ kfree(slot->name);
kfree(slot->hotplug_slot);
kfree(slot);
}
@@ -63,11 +63,9 @@ struct slot *alloc_slot_struct(struct device_node *dn,
GFP_KERNEL);
if (!slot->hotplug_slot->info)
goto error_hpslot;
- slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
- if (!slot->hotplug_slot->name)
+ slot->name = kstrdup(drc_name, GFP_KERNEL);
+ if (!slot->name)
goto error_info;
- slot->name = slot->hotplug_slot->name;
- strcpy(slot->name, drc_name);
slot->dn = dn;
slot->index = drc_index;
slot->power_domain = power_domain;
@@ -137,7 +135,7 @@ int rpaphp_register_slot(struct slot *slot)
slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn);
else
slotno = -1;
- retval = pci_hp_register(php_slot, slot->bus, slotno);
+ retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
return retval;
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 410fe0394a8..3eee70928d4 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -161,7 +161,8 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus)
}
static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
- struct pci_bus *pci_bus, int device)
+ struct pci_bus *pci_bus, int device,
+ char *name)
{
struct pcibus_info *pcibus_info;
struct slot *slot;
@@ -173,15 +174,9 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
return -ENOMEM;
bss_hotplug_slot->private = slot;
- bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL);
- if (!bss_hotplug_slot->name) {
- kfree(bss_hotplug_slot->private);
- return -ENOMEM;
- }
-
slot->device_num = device;
slot->pci_bus = pci_bus;
- sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
+ sprintf(name, "%04x:%02x:%02x",
pci_domain_nr(pci_bus),
((u16)pcibus_info->pbi_buscommon.bs_persist_busnum),
device + 1);
@@ -418,7 +413,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
/*
* Add the slot's devices to the ACPI infrastructure */
if (SN_ACPI_BASE_SUPPORT() && ssdt) {
- unsigned long adr;
+ unsigned long long adr;
struct acpi_device *pdevice;
struct acpi_device *device;
acpi_handle phandle;
@@ -510,7 +505,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
/* free the ACPI resources for the slot */
if (SN_ACPI_BASE_SUPPORT() &&
PCI_CONTROLLER(slot->pci_bus)->acpi_handle) {
- unsigned long adr;
+ unsigned long long adr;
struct acpi_device *device;
acpi_handle phandle;
acpi_handle chandle = NULL;
@@ -608,7 +603,6 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
{
kfree(bss_hotplug_slot->info);
- kfree(bss_hotplug_slot->name);
kfree(bss_hotplug_slot->private);
kfree(bss_hotplug_slot);
}
@@ -618,6 +612,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
int device;
struct pci_slot *pci_slot;
struct hotplug_slot *bss_hotplug_slot;
+ char name[SN_SLOT_NAME_SIZE];
int rc = 0;
/*
@@ -645,15 +640,14 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
}
if (sn_hp_slot_private_alloc(bss_hotplug_slot,
- pci_bus, device)) {
+ pci_bus, device, name)) {
rc = -ENOMEM;
goto alloc_err;
}
-
bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
bss_hotplug_slot->release = &sn_release_slot;
- rc = pci_hp_register(bss_hotplug_slot, pci_bus, device);
+ rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name);
if (rc)
goto register_err;
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 8a026f750de..6aba0b6cf2e 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -59,6 +59,20 @@ extern struct workqueue_struct *shpchp_wq;
#define warn(format, arg...) \
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+#define ctrl_dbg(ctrl, format, arg...) \
+ do { \
+ if (shpchp_debug) \
+ dev_printk(, &ctrl->pci_dev->dev, \
+ format, ## arg); \
+ } while (0)
+#define ctrl_err(ctrl, format, arg...) \
+ dev_err(&ctrl->pci_dev->dev, format, ## arg)
+#define ctrl_info(ctrl, format, arg...) \
+ dev_info(&ctrl->pci_dev->dev, format, ## arg)
+#define ctrl_warn(ctrl, format, arg...) \
+ dev_warn(&ctrl->pci_dev->dev, format, ## arg)
+
+
#define SLOT_NAME_SIZE 10
struct slot {
u8 bus;
@@ -69,15 +83,13 @@ struct slot {
u8 state;
u8 presence_save;
u8 pwr_save;
- struct timer_list task_event;
- u8 hp_slot;
struct controller *ctrl;
struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
- char name[SLOT_NAME_SIZE];
struct delayed_work work; /* work for button event */
struct mutex lock;
+ u8 hp_slot;
};
struct event_info {
@@ -169,6 +181,11 @@ extern void cleanup_slots(struct controller *ctrl);
extern void shpchp_queue_pushbutton_work(struct work_struct *work);
extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
+static inline const char *slot_name(struct slot *slot)
+{
+ return hotplug_slot_name(slot->hotplug_slot);
+}
+
#ifdef CONFIG_ACPI
#include <linux/pci-acpi.h>
static inline int get_hp_params_from_firmware(struct pci_dev *dev,
@@ -236,7 +253,7 @@ static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device)
return slot;
}
- err("%s: slot (device=0x%x) not found\n", __func__, device);
+ ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device);
return NULL;
}
@@ -270,7 +287,9 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
if (perr_set) {
- dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__func__ , perr_set);
+ ctrl_dbg(p_slot->ctrl,
+ "Bridge_Errors[ PERR_OBSERVED = %08X] (W1C)\n",
+ perr_set);
pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
}
@@ -279,7 +298,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
rse_set = pcix_mem_base_reg & RSE_MASK;
if (rse_set) {
- dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__func__ );
+ ctrl_dbg(p_slot->ctrl, "Memory_Base_Limit[ RSE ] (W1C)\n");
pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
}
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index cc38615395f..fe8d149c229 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -89,7 +89,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot);
@@ -101,8 +102,9 @@ static int init_slots(struct controller *ctrl)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
+ char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
- int i, len, dup = 1;
+ int i;
for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
@@ -119,8 +121,6 @@ static int init_slots(struct controller *ctrl)
goto error_hpslot;
hotplug_slot->info = info;
- hotplug_slot->name = slot->name;
-
slot->hp_slot = i;
slot->ctrl = ctrl;
slot->bus = ctrl->pci_dev->subordinate->number;
@@ -133,37 +133,27 @@ static int init_slots(struct controller *ctrl)
/* register this slot with the hotplug pci core */
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
- snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
+ snprintf(name, SLOT_NAME_SIZE, "%d", slot->number);
hotplug_slot->ops = &shpchp_hotplug_slot_ops;
- get_power_status(hotplug_slot, &info->power_status);
- get_attention_status(hotplug_slot, &info->attention_status);
- get_latch_status(hotplug_slot, &info->latch_status);
- get_adapter_status(hotplug_slot, &info->adapter_status);
-
- dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
- "slot_device_offset=%x\n", slot->bus, slot->device,
- slot->hp_slot, slot->number, ctrl->slot_device_offset);
-duplicate_name:
+ ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x "
+ "hp_slot=%x sun=%x slot_device_offset=%x\n",
+ pci_domain_nr(ctrl->pci_dev->subordinate),
+ slot->bus, slot->device, slot->hp_slot, slot->number,
+ ctrl->slot_device_offset);
retval = pci_hp_register(slot->hotplug_slot,
- ctrl->pci_dev->subordinate, slot->device);
+ ctrl->pci_dev->subordinate, slot->device, name);
if (retval) {
- /*
- * If slot N already exists, we'll try to create
- * slot N-1, N-2 ... N-M, until we overflow.
- */
- if (retval == -EEXIST) {
- len = snprintf(slot->name, SLOT_NAME_SIZE,
- "%d-%d", slot->number, dup++);
- if (len < SLOT_NAME_SIZE)
- goto duplicate_name;
- else
- err("duplicate slot name overflow\n");
- }
- err("pci_hp_register failed with error %d\n", retval);
+ ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
+ retval);
goto error_info;
}
+ get_power_status(hotplug_slot, &info->power_status);
+ get_attention_status(hotplug_slot, &info->attention_status);
+ get_latch_status(hotplug_slot, &info->latch_status);
+ get_adapter_status(hotplug_slot, &info->adapter_status);
+
list_add(&slot->slot_list, &ctrl->slot_list);
}
@@ -201,7 +191,8 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = get_slot(hotplug_slot);
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
hotplug_slot->info->attention_status = status;
slot->hpc_ops->set_attention_status(slot, status);
@@ -213,7 +204,8 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
{
struct slot *slot = get_slot(hotplug_slot);
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
return shpchp_sysfs_enable_slot(slot);
}
@@ -222,7 +214,8 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
{
struct slot *slot = get_slot(hotplug_slot);
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
return shpchp_sysfs_disable_slot(slot);
}
@@ -232,7 +225,8 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_power_status(slot, value);
if (retval < 0)
@@ -246,7 +240,8 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_attention_status(slot, value);
if (retval < 0)
@@ -260,7 +255,8 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_latch_status(slot, value);
if (retval < 0)
@@ -274,7 +270,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_adapter_status(slot, value);
if (retval < 0)
@@ -289,7 +286,8 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
struct slot *slot = get_slot(hotplug_slot);
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_max_bus_speed(slot, value);
if (retval < 0)
@@ -303,7 +301,8 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
struct slot *slot = get_slot(hotplug_slot);
int retval;
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
+ __func__, slot_name(slot));
retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
if (retval < 0)
@@ -334,15 +333,14 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl) {
- err("%s : out of memory\n", __func__);
+ dev_err(&pdev->dev, "%s: Out of memory\n", __func__);
goto err_out_none;
}
INIT_LIST_HEAD(&ctrl->slot_list);
rc = shpc_init(ctrl, pdev);
if (rc) {
- dbg("%s: controller initialization failed\n",
- SHPC_MODULE_NAME);
+ ctrl_dbg(ctrl, "Controller initialization failed\n");
goto err_out_free_ctrl;
}
@@ -351,7 +349,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
- err("%s: slot initialization failed\n", SHPC_MODULE_NAME);
+ ctrl_err(ctrl, "Slot initialization failed\n");
goto err_out_release_ctlr;
}
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index dfb53932dfb..b8ab2796e66 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -62,7 +62,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
u32 event_type;
/* Attention Button Change */
- dbg("shpchp: Attention button interrupt received.\n");
+ ctrl_dbg(ctrl, "Attention button interrupt received\n");
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
@@ -70,7 +70,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
/*
* Button pressed - See if need to TAKE ACTION!!!
*/
- info("Button pressed on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
event_type = INT_BUTTON_PRESS;
queue_interrupt_event(p_slot, event_type);
@@ -86,29 +86,29 @@ u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
u32 event_type;
/* Switch Change */
- dbg("shpchp: Switch interrupt received.\n");
+ ctrl_dbg(ctrl, "Switch interrupt received\n");
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- dbg("%s: Card present %x Power status %x\n", __func__,
- p_slot->presence_save, p_slot->pwr_save);
+ ctrl_dbg(ctrl, "Card present %x Power status %x\n",
+ p_slot->presence_save, p_slot->pwr_save);
if (getstatus) {
/*
* Switch opened
*/
- info("Latch open on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_OPEN;
if (p_slot->pwr_save && p_slot->presence_save) {
event_type = INT_POWER_FAULT;
- err("Surprise Removal of card\n");
+ ctrl_err(ctrl, "Surprise Removal of card\n");
}
} else {
/*
* Switch closed
*/
- info("Latch close on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_CLOSE;
}
@@ -123,7 +123,7 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
u32 event_type;
/* Presence Change */
- dbg("shpchp: Presence/Notify input change.\n");
+ ctrl_dbg(ctrl, "Presence/Notify input change\n");
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
@@ -135,13 +135,15 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
/*
* Card Present
*/
- info("Card present on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Card present on Slot(%s)\n",
+ slot_name(p_slot));
event_type = INT_PRESENCE_ON;
} else {
/*
* Not Present
*/
- info("Card not present on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Card not present on Slot(%s)\n",
+ slot_name(p_slot));
event_type = INT_PRESENCE_OFF;
}
@@ -156,7 +158,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
u32 event_type;
/* Power fault */
- dbg("shpchp: Power fault interrupt received.\n");
+ ctrl_dbg(ctrl, "Power fault interrupt received\n");
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
@@ -164,18 +166,19 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
/*
* Power fault Cleared
*/
- info("Power fault cleared on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
+ slot_name(p_slot));
p_slot->status = 0x00;
event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
* Power fault
*/
- info("Power fault on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
/* set power fault status for this board */
p_slot->status = 0xFF;
- info("power fault bit %x set\n", hp_slot);
+ ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot);
}
queue_interrupt_event(p_slot, event_type);
@@ -191,10 +194,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
{
int rc = 0;
- dbg("%s: change to speed %d\n", __func__, speed);
+ ctrl_dbg(ctrl, "Change speed to %d\n", speed);
if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
- err("%s: Issue of set bus speed mode command failed\n",
- __func__);
+ ctrl_err(ctrl, "%s: Issue of set bus speed mode command "
+ "failed\n", __func__);
return WRONG_BUS_FREQUENCY;
}
return rc;
@@ -212,8 +215,8 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
*/
if (flag) {
if (asp < bsp) {
- err("%s: speed of bus %x and adapter %x mismatch\n",
- __func__, bsp, asp);
+ ctrl_err(ctrl, "Speed of bus %x and adapter %x "
+ "mismatch\n", bsp, asp);
rc = WRONG_BUS_FREQUENCY;
}
return rc;
@@ -243,17 +246,18 @@ static int board_added(struct slot *p_slot)
int rc = 0;
enum pci_bus_speed asp, bsp, msp;
struct controller *ctrl = p_slot->ctrl;
+ struct pci_bus *parent = ctrl->pci_dev->subordinate;
hp_slot = p_slot->device - ctrl->slot_device_offset;
- dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
- __func__, p_slot->device,
- ctrl->slot_device_offset, hp_slot);
+ ctrl_dbg(ctrl,
+ "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+ __func__, p_slot->device, ctrl->slot_device_offset, hp_slot);
/* Power on slot without connecting to bus */
rc = p_slot->hpc_ops->power_on_slot(p_slot);
if (rc) {
- err("%s: Failed to power on slot\n", __func__);
+ ctrl_err(ctrl, "Failed to power on slot\n");
return -1;
}
@@ -262,33 +266,34 @@ static int board_added(struct slot *p_slot)
return WRONG_BUS_FREQUENCY;
if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
- err("%s: Issue of set bus speed mode command failed\n", __func__);
+ ctrl_err(ctrl, "%s: Issue of set bus speed mode command"
+ " failed\n", __func__);
return WRONG_BUS_FREQUENCY;
}
/* turn on board, blink green LED, turn off Amber LED */
if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
- err("%s: Issue of Slot Enable command failed\n", __func__);
+ ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
return rc;
}
}
rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
if (rc) {
- err("%s: Can't get adapter speed or bus mode mismatch\n",
- __func__);
+ ctrl_err(ctrl, "Can't get adapter speed or "
+ "bus mode mismatch\n");
return WRONG_BUS_FREQUENCY;
}
rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp);
if (rc) {
- err("%s: Can't get bus operation speed\n", __func__);
+ ctrl_err(ctrl, "Can't get bus operation speed\n");
return WRONG_BUS_FREQUENCY;
}
rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp);
if (rc) {
- err("%s: Can't get max bus operation speed\n", __func__);
+ ctrl_err(ctrl, "Can't get max bus operation speed\n");
msp = bsp;
}
@@ -296,9 +301,9 @@ static int board_added(struct slot *p_slot)
if (!list_empty(&ctrl->pci_dev->subordinate->devices))
slots_not_empty = 1;
- dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, "
- "max_bus_speed %d\n", __func__, slots_not_empty, asp,
- bsp, msp);
+ ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d,"
+ " max_bus_speed %d\n", __func__, slots_not_empty, asp,
+ bsp, msp);
rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);
if (rc)
@@ -306,26 +311,26 @@ static int board_added(struct slot *p_slot)
/* turn on board, blink green LED, turn off Amber LED */
if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
- err("%s: Issue of Slot Enable command failed\n", __func__);
+ ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
return rc;
}
/* Wait for ~1 second */
msleep(1000);
- dbg("%s: slot status = %x\n", __func__, p_slot->status);
+ ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status);
/* Check for a power fault */
if (p_slot->status == 0xFF) {
/* power fault occurred, but it was benign */
- dbg("%s: power fault\n", __func__);
+ ctrl_dbg(ctrl, "%s: Power fault\n", __func__);
rc = POWER_FAILURE;
p_slot->status = 0;
goto err_exit;
}
if (shpchp_configure_device(p_slot)) {
- err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
- p_slot->device);
+ ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n",
+ pci_domain_nr(parent), p_slot->bus, p_slot->device);
goto err_exit;
}
@@ -341,7 +346,8 @@ err_exit:
/* turn off slot, turn on Amber LED, turn off Green LED */
rc = p_slot->hpc_ops->slot_disable(p_slot);
if (rc) {
- err("%s: Issue of Slot Disable command failed\n", __func__);
+ ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
+ __func__);
return rc;
}
@@ -365,7 +371,7 @@ static int remove_board(struct slot *p_slot)
hp_slot = p_slot->device - ctrl->slot_device_offset;
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- dbg("In %s, hp_slot = %d\n", __func__, hp_slot);
+ ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot);
/* Change status to shutdown */
if (p_slot->is_a_board)
@@ -374,13 +380,14 @@ static int remove_board(struct slot *p_slot)
/* turn off slot, turn on Amber LED, turn off Green LED */
rc = p_slot->hpc_ops->slot_disable(p_slot);
if (rc) {
- err("%s: Issue of Slot Disable command failed\n", __func__);
+ ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
+ __func__);
return rc;
}
rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
if (rc) {
- err("%s: Issue of Set Attention command failed\n", __func__);
+ ctrl_err(ctrl, "Issue of Set Attention command failed\n");
return rc;
}
@@ -439,7 +446,8 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
- err("%s: Cannot allocate memory\n", __func__);
+ ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
+ __func__);
return;
}
info->p_slot = p_slot;
@@ -486,18 +494,19 @@ static int update_slot_info (struct slot *slot)
static void handle_button_press_event(struct slot *p_slot)
{
u8 getstatus;
+ struct controller *ctrl = p_slot->ctrl;
switch (p_slot->state) {
case STATIC_STATE:
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = BLINKINGOFF_STATE;
- info("PCI slot #%s - powering off due to button "
- "press.\n", p_slot->name);
+ ctrl_info(ctrl, "PCI slot #%s - powering off due to "
+ "button press.\n", slot_name(p_slot));
} else {
p_slot->state = BLINKINGON_STATE;
- info("PCI slot #%s - powering on due to button "
- "press.\n", p_slot->name);
+ ctrl_info(ctrl, "PCI slot #%s - powering on due to "
+ "button press.\n", slot_name(p_slot));
}
/* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot);
@@ -512,16 +521,16 @@ static void handle_button_press_event(struct slot *p_slot)
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
- info("Button cancel on Slot(%s)\n", p_slot->name);
- dbg("%s: button cancel\n", __func__);
+ ctrl_info(ctrl, "Button cancel on Slot(%s)\n",
+ slot_name(p_slot));
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE)
p_slot->hpc_ops->green_led_on(p_slot);
else
p_slot->hpc_ops->green_led_off(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- info("PCI slot #%s - action canceled due to button press\n",
- p_slot->name);
+ ctrl_info(ctrl, "PCI slot #%s - action canceled due to "
+ "button press\n", slot_name(p_slot));
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
@@ -531,11 +540,12 @@ static void handle_button_press_event(struct slot *p_slot)
* this means that the previous attention button action
* to hot-add or hot-remove is undergoing
*/
- info("Button ignore on Slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Button ignore on Slot(%s)\n",
+ slot_name(p_slot));
update_slot_info(p_slot);
break;
default:
- warn("Not a valid state\n");
+ ctrl_warn(ctrl, "Not a valid state\n");
break;
}
}
@@ -551,7 +561,7 @@ static void interrupt_event_handler(struct work_struct *work)
handle_button_press_event(p_slot);
break;
case INT_POWER_FAULT:
- dbg("%s: power fault\n", __func__);
+ ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__);
p_slot->hpc_ops->set_attention_status(p_slot, 1);
p_slot->hpc_ops->green_led_off(p_slot);
break;
@@ -569,22 +579,24 @@ static int shpchp_enable_slot (struct slot *p_slot)
{
u8 getstatus = 0;
int rc, retval = -ENODEV;
+ struct controller *ctrl = p_slot->ctrl;
/* Check to see if (latch closed, card present, power off) */
mutex_lock(&p_slot->ctrl->crit_sect);
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) {
- info("No adapter on slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("Latch open on slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("Already enabled on slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Already enabled on slot(%s)\n",
+ slot_name(p_slot));
goto out;
}
@@ -593,7 +605,7 @@ static int shpchp_enable_slot (struct slot *p_slot)
/* We have to save the presence info for these slots */
p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
- dbg("%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
+ ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) ||
@@ -624,6 +636,7 @@ static int shpchp_disable_slot (struct slot *p_slot)
{
u8 getstatus = 0;
int rc, retval = -ENODEV;
+ struct controller *ctrl = p_slot->ctrl;
if (!p_slot->ctrl)
return -ENODEV;
@@ -633,17 +646,18 @@ static int shpchp_disable_slot (struct slot *p_slot)
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) {
- info("No adapter on slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
- info("Latch open on slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || !getstatus) {
- info("Already disabled slot(%s)\n", p_slot->name);
+ ctrl_info(ctrl, "Already disabled on slot(%s)\n",
+ slot_name(p_slot));
goto out;
}
@@ -657,6 +671,7 @@ static int shpchp_disable_slot (struct slot *p_slot)
int shpchp_sysfs_enable_slot(struct slot *p_slot)
{
int retval = -ENODEV;
+ struct controller *ctrl = p_slot->ctrl;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
@@ -670,15 +685,17 @@ int shpchp_sysfs_enable_slot(struct slot *p_slot)
p_slot->state = STATIC_STATE;
break;
case POWERON_STATE:
- info("Slot %s is already in powering on state\n",
- p_slot->name);
+ ctrl_info(ctrl, "Slot %s is already in powering on state\n",
+ slot_name(p_slot));
break;
case BLINKINGOFF_STATE:
case POWEROFF_STATE:
- info("Already enabled on slot %s\n", p_slot->name);
+ ctrl_info(ctrl, "Already enabled on slot %s\n",
+ slot_name(p_slot));
break;
default:
- err("Not a valid state on slot %s\n", p_slot->name);
+ ctrl_err(ctrl, "Not a valid state on slot %s\n",
+ slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
@@ -689,6 +706,7 @@ int shpchp_sysfs_enable_slot(struct slot *p_slot)
int shpchp_sysfs_disable_slot(struct slot *p_slot)
{
int retval = -ENODEV;
+ struct controller *ctrl = p_slot->ctrl;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
@@ -702,15 +720,17 @@ int shpchp_sysfs_disable_slot(struct slot *p_slot)
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
- info("Slot %s is already in powering off state\n",
- p_slot->name);
+ ctrl_info(ctrl, "Slot %s is already in powering off state\n",
+ slot_name(p_slot));
break;
case BLINKINGON_STATE:
case POWERON_STATE:
- info("Already disabled on slot %s\n", p_slot->name);
+ ctrl_info(ctrl, "Already disabled on slot %s\n",
+ slot_name(p_slot));
break;
default:
- err("Not a valid state on slot %s\n", p_slot->name);
+ ctrl_err(ctrl, "Not a valid state on slot %s\n",
+ slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 7a0bff364cd..86dc3984776 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -300,10 +300,10 @@ static inline int shpc_wait_cmd(struct controller *ctrl)
!is_ctrl_busy(ctrl), timeout);
if (!rc && is_ctrl_busy(ctrl)) {
retval = -EIO;
- err("Command not completed in 1000 msec\n");
+ ctrl_err(ctrl, "Command not completed in 1000 msec\n");
} else if (rc < 0) {
retval = -EINTR;
- info("Command was interrupted by a signal\n");
+ ctrl_info(ctrl, "Command was interrupted by a signal\n");
}
return retval;
@@ -320,15 +320,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
if (!shpc_poll_ctrl_busy(ctrl)) {
/* After 1 sec and and the controller is still busy */
- err("%s : Controller is still busy after 1 sec.\n",
- __func__);
+ ctrl_err(ctrl, "Controller is still busy after 1 sec\n");
retval = -EBUSY;
goto out;
}
++t_slot;
temp_word = (t_slot << 8) | (cmd & 0xFF);
- dbg("%s: t_slot %x cmd %x\n", __func__, t_slot, cmd);
+ ctrl_dbg(ctrl, "%s: t_slot %x cmd %x\n", __func__, t_slot, cmd);
/* To make sure the Controller Busy bit is 0 before we send out the
* command.
@@ -344,8 +343,9 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
cmd_status = hpc_check_cmd_status(slot->ctrl);
if (cmd_status) {
- err("%s: Failed to issued command 0x%x (error code = %d)\n",
- __func__, cmd, cmd_status);
+ ctrl_err(ctrl,
+ "Failed to issued command 0x%x (error code = %d)\n",
+ cmd, cmd_status);
retval = -EIO;
}
out:
@@ -364,15 +364,15 @@ static int hpc_check_cmd_status(struct controller *ctrl)
break;
case 1:
retval = SWITCH_OPEN;
- err("%s: Switch opened!\n", __func__);
+ ctrl_err(ctrl, "Switch opened!\n");
break;
case 2:
retval = INVALID_CMD;
- err("%s: Invalid HPC command!\n", __func__);
+ ctrl_err(ctrl, "Invalid HPC command!\n");
break;
case 4:
retval = INVALID_SPEED_MODE;
- err("%s: Invalid bus speed/mode!\n", __func__);
+ ctrl_err(ctrl, "Invalid bus speed/mode!\n");
break;
default:
retval = cmd_status;
@@ -483,8 +483,8 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
return -ENODEV;
}
- dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
- __func__, slot_reg, pcix_cap, m66_cap);
+ ctrl_dbg(ctrl, "%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
+ __func__, slot_reg, pcix_cap, m66_cap);
switch (pcix_cap) {
case 0x0:
@@ -509,7 +509,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
break;
}
- dbg("Adapter speed = %d\n", *value);
+ ctrl_dbg(ctrl, "Adapter speed = %d\n", *value);
return retval;
}
@@ -526,7 +526,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
retval = -1;
}
- dbg("Mode 1 ECC cap = %d\n", *mode);
+ ctrl_dbg(ctrl, "Mode 1 ECC cap = %d\n", *mode);
return retval;
}
@@ -629,7 +629,7 @@ static int hpc_power_on_slot(struct slot * slot)
retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
if (retval)
- err("%s: Write command failed!\n", __func__);
+ ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__);
return retval;
}
@@ -642,7 +642,7 @@ static int hpc_slot_enable(struct slot * slot)
retval = shpc_write_cmd(slot, slot->hp_slot,
SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
if (retval)
- err("%s: Write command failed!\n", __func__);
+ ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__);
return retval;
}
@@ -655,7 +655,7 @@ static int hpc_slot_disable(struct slot * slot)
retval = shpc_write_cmd(slot, slot->hp_slot,
SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
if (retval)
- err("%s: Write command failed!\n", __func__);
+ ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__);
return retval;
}
@@ -719,7 +719,7 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
retval = shpc_write_cmd(slot, 0, cmd);
if (retval)
- err("%s: Write command failed!\n", __func__);
+ ctrl_err(ctrl, "%s: Write command failed!\n", __func__);
return retval;
}
@@ -735,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
if (!intr_loc)
return IRQ_NONE;
- dbg("%s: intr_loc = %x\n",__func__, intr_loc);
+ ctrl_dbg(ctrl, "%s: intr_loc = %x\n", __func__, intr_loc);
if(!shpchp_poll_mode) {
/*
@@ -748,7 +748,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
intr_loc2 = shpc_readl(ctrl, INTR_LOC);
- dbg("%s: intr_loc2 = %x\n",__func__, intr_loc2);
+ ctrl_dbg(ctrl, "%s: intr_loc2 = %x\n", __func__, intr_loc2);
}
if (intr_loc & CMD_INTR_PENDING) {
@@ -773,8 +773,8 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
continue;
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
- dbg("%s: Slot %x with intr, slot register = %x\n",
- __func__, hp_slot, slot_reg);
+ ctrl_dbg(ctrl, "Slot %x with intr, slot register = %x\n",
+ hp_slot, slot_reg);
if (slot_reg & MRL_CHANGE_DETECTED)
shpchp_handle_switch_change(hp_slot, ctrl);
@@ -843,7 +843,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
}
*value = bus_speed;
- dbg("Max bus speed = %d\n", bus_speed);
+ ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed);
return retval;
}
@@ -911,7 +911,7 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
break;
}
- dbg("Current bus speed = %d\n", bus_speed);
+ ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed);
return retval;
}
@@ -949,6 +949,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
u8 i;
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
+ ctrl_dbg(ctrl, "Hotplug Controller:\n");
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450)) {
@@ -958,34 +959,33 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
} else {
ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
if (!ctrl->cap_offset) {
- err("%s : cap_offset == 0\n", __func__);
+ ctrl_err(ctrl, "Cannot find PCI capability\n");
goto abort;
}
- dbg("%s: cap_offset = %x\n", __func__, ctrl->cap_offset);
+ ctrl_dbg(ctrl, " cap_offset = %x\n", ctrl->cap_offset);
rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
if (rc) {
- err("%s: cannot read base_offset\n", __func__);
+ ctrl_err(ctrl, "Cannot read base_offset\n");
goto abort;
}
rc = shpc_indirect_read(ctrl, 3, &tempdword);
if (rc) {
- err("%s: cannot read slot config\n", __func__);
+ ctrl_err(ctrl, "Cannot read slot config\n");
goto abort;
}
num_slots = tempdword & SLOT_NUM;
- dbg("%s: num_slots (indirect) %x\n", __func__, num_slots);
+ ctrl_dbg(ctrl, " num_slots (indirect) %x\n", num_slots);
for (i = 0; i < 9 + num_slots; i++) {
rc = shpc_indirect_read(ctrl, i, &tempdword);
if (rc) {
- err("%s: cannot read creg (index = %d)\n",
- __func__, i);
+ ctrl_err(ctrl,
+ "Cannot read creg (index = %d)\n", i);
goto abort;
}
- dbg("%s: offset %d: value %x\n", __func__,i,
- tempdword);
+ ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword);
}
ctrl->mmio_base =
@@ -993,30 +993,31 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
ctrl->mmio_size = 0x24 + 0x4 * num_slots;
}
- info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
- pdev->subsystem_device);
+ ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
+ pdev->vendor, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
rc = pci_enable_device(pdev);
if (rc) {
- err("%s: pci_enable_device failed\n", __func__);
+ ctrl_err(ctrl, "pci_enable_device failed\n");
goto abort;
}
if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
- err("%s: cannot reserve MMIO region\n", __func__);
+ ctrl_err(ctrl, "Cannot reserve MMIO region\n");
rc = -1;
goto abort;
}
ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
if (!ctrl->creg) {
- err("%s: cannot remap MMIO region %lx @ %lx\n", __func__,
- ctrl->mmio_size, ctrl->mmio_base);
+ ctrl_err(ctrl, "Cannot remap MMIO region %lx @ %lx\n",
+ ctrl->mmio_size, ctrl->mmio_base);
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
rc = -1;
goto abort;
}
- dbg("%s: ctrl->creg %p\n", __func__, ctrl->creg);
+ ctrl_dbg(ctrl, "ctrl->creg %p\n", ctrl->creg);
mutex_init(&ctrl->crit_sect);
mutex_init(&ctrl->cmd_lock);
@@ -1035,21 +1036,21 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
- dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |
COMMAND_INTR_MASK | ARBITER_SERR_MASK);
tempdword &= ~SERR_INTR_RSVDZ_MASK;
shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
- dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
/* Mask the MRL sensor SERR Mask of individual slot in
* Slot SERR-INT Mask & clear all the existing event if any
*/
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
- dbg("%s: Default Logical Slot Register %d value %x\n", __func__,
- hp_slot, slot_reg);
+ ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n",
+ hp_slot, slot_reg);
slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK |
@@ -1066,24 +1067,24 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
/* Installs the interrupt handler */
rc = pci_enable_msi(pdev);
if (rc) {
- info("Can't get msi for the hotplug controller\n");
- info("Use INTx for the hotplug controller\n");
+ ctrl_info(ctrl,
+ "Can't get msi for the hotplug controller\n");
+ ctrl_info(ctrl,
+ "Use INTx for the hotplug controller\n");
}
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
MY_NAME, (void *)ctrl);
- dbg("%s: request_irq %d for hpc%d (returns %d)\n",
- __func__, ctrl->pci_dev->irq,
+ ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n",
+ ctrl->pci_dev->irq,
atomic_read(&shpchp_num_controllers), rc);
if (rc) {
- err("Can't get irq %d for the hotplug controller\n",
- ctrl->pci_dev->irq);
+ ctrl_err(ctrl, "Can't get irq %d for the hotplug "
+ "controller\n", ctrl->pci_dev->irq);
goto abort_iounmap;
}
}
- dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__,
- pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn), pdev->irq);
+ ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq);
/*
* If this is the first controller to be initialized,
@@ -1102,8 +1103,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
*/
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
- dbg("%s: Default Logical Slot Register %d value %x\n", __func__,
- hp_slot, slot_reg);
+ ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n",
+ hp_slot, slot_reg);
slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK);
@@ -1116,7 +1117,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
SERR_INTR_RSVDZ_MASK);
shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
- dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
}
return 0;
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 3fc4ec0eea0..138f161becc 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -49,9 +49,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
/* use default values if we can't get them from firmware */
if (get_hp_params_from_firmware(dev, &hpp) ||
!hpp.t0 || (hpp.t0->revision > 1)) {
- printk(KERN_WARNING
- "%s: Could not get hotplug parameters. Use defaults\n",
- __func__);
+ warn("Could not get hotplug parameters. Use defaults\n");
hpp.t0 = &hpp.type0_data;
hpp.t0->revision = 0;
hpp.t0->cache_line_size = 8;
@@ -101,18 +99,20 @@ int __ref shpchp_configure_device(struct slot *p_slot)
struct pci_dev *dev;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
int num, fn;
+ struct controller *ctrl = p_slot->ctrl;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) {
- err("Device %s already exists at %x:%x, cannot hot-add\n",
- pci_name(dev), p_slot->bus, p_slot->device);
+ ctrl_err(ctrl, "Device %s already exists "
+ "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev),
+ pci_domain_nr(parent), p_slot->bus, p_slot->device);
pci_dev_put(dev);
return -EINVAL;
}
num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (num == 0) {
- err("No new device found\n");
+ ctrl_err(ctrl, "No new device found\n");
return -ENODEV;
}
@@ -121,8 +121,8 @@ int __ref shpchp_configure_device(struct slot *p_slot)
if (!dev)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- err("Cannot hot-add display device %s\n",
- pci_name(dev));
+ ctrl_err(ctrl, "Cannot hot-add display device %s\n",
+ pci_name(dev));
pci_dev_put(dev);
continue;
}
@@ -138,14 +138,15 @@ int __ref shpchp_configure_device(struct slot *p_slot)
break;
}
if (busnr >= end) {
- err("No free bus for hot-added bridge\n");
+ ctrl_err(ctrl,
+ "No free bus for hot-added bridge\n");
pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
- err("Cannot add new bus for %s\n",
- pci_name(dev));
+ ctrl_err(ctrl, "Cannot add new bus for %s\n",
+ pci_name(dev));
pci_dev_put(dev);
continue;
}
@@ -168,8 +169,10 @@ int shpchp_unconfigure_device(struct slot *p_slot)
int j;
u8 bctl = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ struct controller *ctrl = p_slot->ctrl;
- dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus, p_slot->device);
+ ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
+ __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
for (j=0; j<8 ; j++) {
struct pci_dev* temp = pci_get_slot(parent,
@@ -177,16 +180,17 @@ int shpchp_unconfigure_device(struct slot *p_slot)
if (!temp)
continue;
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- err("Cannot remove display device %s\n",
- pci_name(temp));
+ ctrl_err(ctrl, "Cannot remove display device %s\n",
+ pci_name(temp));
pci_dev_put(temp);
continue;
}
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
- err("Cannot remove display device %s\n",
- pci_name(temp));
+ ctrl_err(ctrl,
+ "Cannot remove display device %s\n",
+ pci_name(temp));
pci_dev_put(temp);
continue;
}
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 279c940a003..bf7d6ce9bbb 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -126,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
cfg->msg.address_hi = 0xffffffff;
irq = create_irq();
- if (irq < 0) {
+
+ if (irq <= 0) {
kfree(cfg);
return -EBUSY;
}
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index fc5f2dbf532..a2692724b68 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -18,6 +18,7 @@
* Author: Ashok Raj <ashok.raj@intel.com>
* Author: Shaohua Li <shaohua.li@intel.com>
* Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ * Author: Fenghua Yu <fenghua.yu@intel.com>
*/
#include <linux/init.h>
@@ -35,11 +36,13 @@
#include <linux/timer.h>
#include <linux/iova.h>
#include <linux/intel-iommu.h>
-#include <asm/proto.h> /* force_iommu in this header in x86-64*/
#include <asm/cacheflush.h>
#include <asm/iommu.h>
#include "pci.h"
+#define ROOT_SIZE VTD_PAGE_SIZE
+#define CONTEXT_SIZE VTD_PAGE_SIZE
+
#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
@@ -199,7 +202,7 @@ static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
spin_unlock_irqrestore(&iommu->lock, flags);
return NULL;
}
- __iommu_flush_cache(iommu, (void *)context, PAGE_SIZE_4K);
+ __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
phy_addr = virt_to_phys((void *)context);
set_root_value(root, phy_addr);
set_root_present(root);
@@ -345,7 +348,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
return NULL;
}
__iommu_flush_cache(domain->iommu, tmp_page,
- PAGE_SIZE_4K);
+ PAGE_SIZE);
dma_set_pte_addr(*pte, virt_to_phys(tmp_page));
/*
* high level table always sets r/w, last level page
@@ -408,13 +411,13 @@ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end)
start &= (((u64)1) << addr_width) - 1;
end &= (((u64)1) << addr_width) - 1;
/* in case it's partial page */
- start = PAGE_ALIGN_4K(start);
- end &= PAGE_MASK_4K;
+ start = PAGE_ALIGN(start);
+ end &= PAGE_MASK;
/* we don't need lock here, nobody else touches the iova range */
while (start < end) {
dma_pte_clear_one(domain, start);
- start += PAGE_SIZE_4K;
+ start += VTD_PAGE_SIZE;
}
}
@@ -468,7 +471,7 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
if (!root)
return -ENOMEM;
- __iommu_flush_cache(iommu, root, PAGE_SIZE_4K);
+ __iommu_flush_cache(iommu, root, ROOT_SIZE);
spin_lock_irqsave(&iommu->lock, flags);
iommu->root_entry = root;
@@ -563,31 +566,10 @@ static int __iommu_flush_context(struct intel_iommu *iommu,
spin_unlock_irqrestore(&iommu->register_lock, flag);
- /* flush context entry will implictly flush write buffer */
+ /* flush context entry will implicitly flush write buffer */
return 0;
}
-static int inline iommu_flush_context_global(struct intel_iommu *iommu,
- int non_present_entry_flush)
-{
- return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL,
- non_present_entry_flush);
-}
-
-static int inline iommu_flush_context_domain(struct intel_iommu *iommu, u16 did,
- int non_present_entry_flush)
-{
- return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL,
- non_present_entry_flush);
-}
-
-static int inline iommu_flush_context_device(struct intel_iommu *iommu,
- u16 did, u16 source_id, u8 function_mask, int non_present_entry_flush)
-{
- return __iommu_flush_context(iommu, did, source_id, function_mask,
- DMA_CCMD_DEVICE_INVL, non_present_entry_flush);
-}
-
/* return value determine if we need a write buffer flush */
static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
u64 addr, unsigned int size_order, u64 type,
@@ -655,37 +637,25 @@ static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
- DMA_TLB_IIRG(type), DMA_TLB_IAIG(val));
- /* flush context entry will implictly flush write buffer */
+ (unsigned long long)DMA_TLB_IIRG(type),
+ (unsigned long long)DMA_TLB_IAIG(val));
+ /* flush iotlb entry will implicitly flush write buffer */
return 0;
}
-static int inline iommu_flush_iotlb_global(struct intel_iommu *iommu,
- int non_present_entry_flush)
-{
- return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH,
- non_present_entry_flush);
-}
-
-static int inline iommu_flush_iotlb_dsi(struct intel_iommu *iommu, u16 did,
- int non_present_entry_flush)
-{
- return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH,
- non_present_entry_flush);
-}
-
static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
u64 addr, unsigned int pages, int non_present_entry_flush)
{
unsigned int mask;
- BUG_ON(addr & (~PAGE_MASK_4K));
+ BUG_ON(addr & (~VTD_PAGE_MASK));
BUG_ON(pages == 0);
/* Fallback to domain selective flush if no PSI support */
if (!cap_pgsel_inv(iommu->cap))
- return iommu_flush_iotlb_dsi(iommu, did,
- non_present_entry_flush);
+ return iommu->flush.flush_iotlb(iommu, did, 0, 0,
+ DMA_TLB_DSI_FLUSH,
+ non_present_entry_flush);
/*
* PSI requires page size to be 2 ^ x, and the base address is naturally
@@ -694,11 +664,12 @@ static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
mask = ilog2(__roundup_pow_of_two(pages));
/* Fallback to domain selective flush if size is too big */
if (mask > cap_max_amask_val(iommu->cap))
- return iommu_flush_iotlb_dsi(iommu, did,
- non_present_entry_flush);
+ return iommu->flush.flush_iotlb(iommu, did, 0, 0,
+ DMA_TLB_DSI_FLUSH, non_present_entry_flush);
- return __iommu_flush_iotlb(iommu, did, addr, mask,
- DMA_TLB_PSI_FLUSH, non_present_entry_flush);
+ return iommu->flush.flush_iotlb(iommu, did, addr, mask,
+ DMA_TLB_PSI_FLUSH,
+ non_present_entry_flush);
}
static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
@@ -831,7 +802,7 @@ void dmar_msi_read(int irq, struct msi_msg *msg)
}
static int iommu_page_fault_do_one(struct intel_iommu *iommu, int type,
- u8 fault_reason, u16 source_id, u64 addr)
+ u8 fault_reason, u16 source_id, unsigned long long addr)
{
const char *reason;
@@ -1084,9 +1055,9 @@ static void dmar_init_reserved_ranges(void)
if (!r->flags || !(r->flags & IORESOURCE_MEM))
continue;
addr = r->start;
- addr &= PAGE_MASK_4K;
+ addr &= PAGE_MASK;
size = r->end - addr;
- size = PAGE_ALIGN_4K(size);
+ size = PAGE_ALIGN(size);
iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr),
IOVA_PFN(size + addr) - 1);
if (!iova)
@@ -1148,7 +1119,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
domain->pgd = (struct dma_pte *)alloc_pgtable_page();
if (!domain->pgd)
return -ENOMEM;
- __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE_4K);
+ __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
return 0;
}
@@ -1164,7 +1135,7 @@ static void domain_exit(struct dmar_domain *domain)
/* destroy iovas */
put_iova_domain(&domain->iovad);
end = DOMAIN_MAX_ADDR(domain->gaw);
- end = end & (~PAGE_MASK_4K);
+ end = end & (~PAGE_MASK);
/* clear ptes */
dma_pte_clear_range(domain, 0, end);
@@ -1204,11 +1175,13 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
__iommu_flush_cache(iommu, context, sizeof(*context));
/* it's a non-present to present mapping */
- if (iommu_flush_context_device(iommu, domain->id,
- (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1))
+ if (iommu->flush.flush_context(iommu, domain->id,
+ (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT,
+ DMA_CCMD_DEVICE_INVL, 1))
iommu_flush_write_buffer(iommu);
else
- iommu_flush_iotlb_dsi(iommu, 0, 0);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH, 0);
+
spin_unlock_irqrestore(&iommu->lock, flags);
return 0;
}
@@ -1283,22 +1256,25 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
u64 start_pfn, end_pfn;
struct dma_pte *pte;
int index;
+ int addr_width = agaw_to_width(domain->agaw);
+
+ hpa &= (((u64)1) << addr_width) - 1;
if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
return -EINVAL;
- iova &= PAGE_MASK_4K;
- start_pfn = ((u64)hpa) >> PAGE_SHIFT_4K;
- end_pfn = (PAGE_ALIGN_4K(((u64)hpa) + size)) >> PAGE_SHIFT_4K;
+ iova &= PAGE_MASK;
+ start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT;
+ end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT;
index = 0;
while (start_pfn < end_pfn) {
- pte = addr_to_dma_pte(domain, iova + PAGE_SIZE_4K * index);
+ pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index);
if (!pte)
return -ENOMEM;
/* We don't need lock here, nobody else
* touches the iova range
*/
BUG_ON(dma_pte_addr(*pte));
- dma_set_pte_addr(*pte, start_pfn << PAGE_SHIFT_4K);
+ dma_set_pte_addr(*pte, start_pfn << VTD_PAGE_SHIFT);
dma_set_pte_prot(*pte, prot);
__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
start_pfn++;
@@ -1310,8 +1286,10 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
{
clear_context_table(domain->iommu, bus, devfn);
- iommu_flush_context_global(domain->iommu, 0);
- iommu_flush_iotlb_global(domain->iommu, 0);
+ domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0,
+ DMA_CCMD_GLOBAL_INVL, 0);
+ domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0,
+ DMA_TLB_GLOBAL_FLUSH, 0);
}
static void domain_remove_dev_info(struct dmar_domain *domain)
@@ -1474,11 +1452,13 @@ error:
return find_domain(pdev);
}
-static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end)
+static int iommu_prepare_identity_map(struct pci_dev *pdev,
+ unsigned long long start,
+ unsigned long long end)
{
struct dmar_domain *domain;
unsigned long size;
- u64 base;
+ unsigned long long base;
int ret;
printk(KERN_INFO
@@ -1490,9 +1470,9 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end)
return -ENOMEM;
/* The address might not be aligned */
- base = start & PAGE_MASK_4K;
+ base = start & PAGE_MASK;
size = end - base;
- size = PAGE_ALIGN_4K(size);
+ size = PAGE_ALIGN(size);
if (!reserve_iova(&domain->iovad, IOVA_PFN(base),
IOVA_PFN(base + size) - 1)) {
printk(KERN_ERR "IOMMU: reserve iova failed\n");
@@ -1662,6 +1642,28 @@ int __init init_dmars(void)
}
}
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+
+ iommu = drhd->iommu;
+ if (dmar_enable_qi(iommu)) {
+ /*
+ * Queued Invalidate not enabled, use Register Based
+ * Invalidate
+ */
+ iommu->flush.flush_context = __iommu_flush_context;
+ iommu->flush.flush_iotlb = __iommu_flush_iotlb;
+ printk(KERN_INFO "IOMMU 0x%Lx: using Register based "
+ "invalidation\n", drhd->reg_base_addr);
+ } else {
+ iommu->flush.flush_context = qi_flush_context;
+ iommu->flush.flush_iotlb = qi_flush_iotlb;
+ printk(KERN_INFO "IOMMU 0x%Lx: using Queued "
+ "invalidation\n", drhd->reg_base_addr);
+ }
+ }
+
/*
* For each rmrr
* for each dev attached to rmrr
@@ -1714,9 +1716,10 @@ int __init init_dmars(void)
iommu_set_root_entry(iommu);
- iommu_flush_context_global(iommu, 0);
- iommu_flush_iotlb_global(iommu, 0);
-
+ iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL,
+ 0);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH,
+ 0);
iommu_disable_protect_mem_regions(iommu);
ret = iommu_enable_translation(iommu);
@@ -1738,8 +1741,8 @@ error:
static inline u64 aligned_size(u64 host_addr, size_t size)
{
u64 addr;
- addr = (host_addr & (~PAGE_MASK_4K)) + size;
- return PAGE_ALIGN_4K(addr);
+ addr = (host_addr & (~PAGE_MASK)) + size;
+ return PAGE_ALIGN(addr);
}
struct iova *
@@ -1753,20 +1756,20 @@ iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end)
return NULL;
piova = alloc_iova(&domain->iovad,
- size >> PAGE_SHIFT_4K, IOVA_PFN(end), 1);
+ size >> PAGE_SHIFT, IOVA_PFN(end), 1);
return piova;
}
static struct iova *
__intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
- size_t size)
+ size_t size, u64 dma_mask)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct iova *iova = NULL;
- if ((pdev->dma_mask <= DMA_32BIT_MASK) || (dmar_forcedac)) {
- iova = iommu_alloc_iova(domain, size, pdev->dma_mask);
- } else {
+ if (dma_mask <= DMA_32BIT_MASK || dmar_forcedac)
+ iova = iommu_alloc_iova(domain, size, dma_mask);
+ else {
/*
* First try to allocate an io virtual address in
* DMA_32BIT_MASK and if that fails then try allocating
@@ -1774,7 +1777,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
*/
iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
if (!iova)
- iova = iommu_alloc_iova(domain, size, pdev->dma_mask);
+ iova = iommu_alloc_iova(domain, size, dma_mask);
}
if (!iova) {
@@ -1813,12 +1816,12 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
return domain;
}
-static dma_addr_t
-intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
+static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
+ size_t size, int dir, u64 dma_mask)
{
struct pci_dev *pdev = to_pci_dev(hwdev);
struct dmar_domain *domain;
- unsigned long start_paddr;
+ phys_addr_t start_paddr;
struct iova *iova;
int prot = 0;
int ret;
@@ -1833,11 +1836,11 @@ intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
size = aligned_size((u64)paddr, size);
- iova = __intel_alloc_iova(hwdev, domain, size);
+ iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
if (!iova)
goto error;
- start_paddr = iova->pfn_lo << PAGE_SHIFT_4K;
+ start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
/*
* Check if DMAR supports zero-length reads on write only
@@ -1855,30 +1858,33 @@ intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
* is not a big problem
*/
ret = domain_page_mapping(domain, start_paddr,
- ((u64)paddr) & PAGE_MASK_4K, size, prot);
+ ((u64)paddr) & PAGE_MASK, size, prot);
if (ret)
goto error;
- pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n",
- pci_name(pdev), size, (u64)paddr,
- size, (u64)start_paddr, dir);
-
/* it's a non-present to present mapping */
ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
- start_paddr, size >> PAGE_SHIFT_4K, 1);
+ start_paddr, size >> VTD_PAGE_SHIFT, 1);
if (ret)
iommu_flush_write_buffer(domain->iommu);
- return (start_paddr + ((u64)paddr & (~PAGE_MASK_4K)));
+ return start_paddr + ((u64)paddr & (~PAGE_MASK));
error:
if (iova)
__free_iova(&domain->iovad, iova);
printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
- pci_name(pdev), size, (u64)paddr, dir);
+ pci_name(pdev), size, (unsigned long long)paddr, dir);
return 0;
}
+dma_addr_t intel_map_single(struct device *hwdev, phys_addr_t paddr,
+ size_t size, int dir)
+{
+ return __intel_map_single(hwdev, paddr, size, dir,
+ to_pci_dev(hwdev)->dma_mask);
+}
+
static void flush_unmaps(void)
{
int i, j;
@@ -1891,7 +1897,8 @@ static void flush_unmaps(void)
struct intel_iommu *iommu =
deferred_flush[i].domain[0]->iommu;
- iommu_flush_iotlb_global(iommu, 0);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0,
+ DMA_TLB_GLOBAL_FLUSH, 0);
for (j = 0; j < deferred_flush[i].next; j++) {
__free_iova(&deferred_flush[i].domain[j]->iovad,
deferred_flush[i].iova[j]);
@@ -1936,8 +1943,8 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
spin_unlock_irqrestore(&async_umap_flush_lock, flags);
}
-static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
- size_t size, int dir)
+void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
+ int dir)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct dmar_domain *domain;
@@ -1953,11 +1960,11 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
if (!iova)
return;
- start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+ start_addr = iova->pfn_lo << PAGE_SHIFT;
size = aligned_size((u64)dev_addr, size);
pr_debug("Device %s unmapping: %lx@%llx\n",
- pci_name(pdev), size, (u64)start_addr);
+ pci_name(pdev), size, (unsigned long long)start_addr);
/* clear the whole page */
dma_pte_clear_range(domain, start_addr, start_addr + size);
@@ -1965,7 +1972,7 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
dma_pte_free_pagetable(domain, start_addr, start_addr + size);
if (intel_iommu_strict) {
if (iommu_flush_iotlb_psi(domain->iommu,
- domain->id, start_addr, size >> PAGE_SHIFT_4K, 0))
+ domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
iommu_flush_write_buffer(domain->iommu);
/* free iova */
__free_iova(&domain->iovad, iova);
@@ -1978,13 +1985,13 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
}
}
-static void * intel_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags)
+void *intel_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flags)
{
void *vaddr;
int order;
- size = PAGE_ALIGN_4K(size);
+ size = PAGE_ALIGN(size);
order = get_order(size);
flags &= ~(GFP_DMA | GFP_DMA32);
@@ -1993,19 +2000,21 @@ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
return NULL;
memset(vaddr, 0, size);
- *dma_handle = intel_map_single(hwdev, virt_to_bus(vaddr), size, DMA_BIDIRECTIONAL);
+ *dma_handle = __intel_map_single(hwdev, virt_to_bus(vaddr), size,
+ DMA_BIDIRECTIONAL,
+ hwdev->coherent_dma_mask);
if (*dma_handle)
return vaddr;
free_pages((unsigned long)vaddr, order);
return NULL;
}
-static void intel_free_coherent(struct device *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
{
int order;
- size = PAGE_ALIGN_4K(size);
+ size = PAGE_ALIGN(size);
order = get_order(size);
intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL);
@@ -2013,8 +2022,9 @@ static void intel_free_coherent(struct device *hwdev, size_t size,
}
#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg)))
-static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
- int nelems, int dir)
+
+void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
+ int nelems, int dir)
{
int i;
struct pci_dev *pdev = to_pci_dev(hwdev);
@@ -2038,7 +2048,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
size += aligned_size((u64)addr, sg->length);
}
- start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+ start_addr = iova->pfn_lo << PAGE_SHIFT;
/* clear the whole page */
dma_pte_clear_range(domain, start_addr, start_addr + size);
@@ -2046,7 +2056,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
dma_pte_free_pagetable(domain, start_addr, start_addr + size);
if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
- size >> PAGE_SHIFT_4K, 0))
+ size >> VTD_PAGE_SHIFT, 0))
iommu_flush_write_buffer(domain->iommu);
/* free iova */
@@ -2067,8 +2077,8 @@ static int intel_nontranslate_map_sg(struct device *hddev,
return nelems;
}
-static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist,
- int nelems, int dir)
+int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
+ int dir)
{
void *addr;
int i;
@@ -2096,7 +2106,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist,
size += aligned_size((u64)addr, sg->length);
}
- iova = __intel_alloc_iova(hwdev, domain, size);
+ iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
if (!iova) {
sglist->dma_length = 0;
return 0;
@@ -2112,14 +2122,14 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist,
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
prot |= DMA_PTE_WRITE;
- start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+ start_addr = iova->pfn_lo << PAGE_SHIFT;
offset = 0;
for_each_sg(sglist, sg, nelems, i) {
addr = SG_ENT_VIRT_ADDRESS(sg);
addr = (void *)virt_to_phys(addr);
size = aligned_size((u64)addr, sg->length);
ret = domain_page_mapping(domain, start_addr + offset,
- ((u64)addr) & PAGE_MASK_4K,
+ ((u64)addr) & PAGE_MASK,
size, prot);
if (ret) {
/* clear the page */
@@ -2133,14 +2143,14 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist,
return 0;
}
sg->dma_address = start_addr + offset +
- ((u64)addr & (~PAGE_MASK_4K));
+ ((u64)addr & (~PAGE_MASK));
sg->dma_length = sg->length;
offset += size;
}
/* it's a non-present to present mapping */
if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
- start_addr, offset >> PAGE_SHIFT_4K, 1))
+ start_addr, offset >> VTD_PAGE_SHIFT, 1))
iommu_flush_write_buffer(domain->iommu);
return nelems;
}
@@ -2180,7 +2190,6 @@ static inline int iommu_devinfo_cache_init(void)
sizeof(struct device_domain_info),
0,
SLAB_HWCACHE_ALIGN,
-
NULL);
if (!iommu_devinfo_cache) {
printk(KERN_ERR "Couldn't create devinfo cache\n");
@@ -2198,7 +2207,6 @@ static inline int iommu_iova_cache_init(void)
sizeof(struct iova),
0,
SLAB_HWCACHE_ALIGN,
-
NULL);
if (!iommu_iova_cache) {
printk(KERN_ERR "Couldn't create iova cache\n");
@@ -2327,7 +2335,7 @@ void intel_iommu_domain_exit(struct dmar_domain *domain)
return;
end = DOMAIN_MAX_ADDR(domain->gaw);
- end = end & (~PAGE_MASK_4K);
+ end = end & (~VTD_PAGE_MASK);
/* clear ptes */
dma_pte_clear_range(domain, 0, end);
@@ -2423,6 +2431,6 @@ u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
if (pte)
pfn = dma_pte_addr(*pte);
- return pfn >> PAGE_SHIFT_4K;
+ return pfn >> VTD_PAGE_SHIFT;
}
EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 738d4c89581..2de5a3238c9 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -1,3 +1,4 @@
+#include <linux/interrupt.h>
#include <linux/dmar.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
@@ -11,41 +12,64 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
static int ir_ioapic_num;
int intr_remapping_enabled;
-static struct {
+struct irq_2_iommu {
struct intel_iommu *iommu;
u16 irte_index;
u16 sub_handle;
u8 irte_mask;
-} irq_2_iommu[NR_IRQS];
+};
+
+static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
+
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
+{
+ return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL;
+}
+
+static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
+{
+ return irq_2_iommu(irq);
+}
static DEFINE_SPINLOCK(irq_2_ir_lock);
-int irq_remapped(int irq)
+static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
{
- if (irq > NR_IRQS)
- return 0;
+ struct irq_2_iommu *irq_iommu;
+
+ irq_iommu = irq_2_iommu(irq);
+
+ if (!irq_iommu)
+ return NULL;
+
+ if (!irq_iommu->iommu)
+ return NULL;
- if (!irq_2_iommu[irq].iommu)
- return 0;
+ return irq_iommu;
+}
- return 1;
+int irq_remapped(int irq)
+{
+ return valid_irq_2_iommu(irq) != NULL;
}
int get_irte(int irq, struct irte *entry)
{
int index;
+ struct irq_2_iommu *irq_iommu;
- if (!entry || irq > NR_IRQS)
+ if (!entry)
return -1;
spin_lock(&irq_2_ir_lock);
- if (!irq_2_iommu[irq].iommu) {
+ irq_iommu = valid_irq_2_iommu(irq);
+ if (!irq_iommu) {
spin_unlock(&irq_2_ir_lock);
return -1;
}
- index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
- *entry = *(irq_2_iommu[irq].iommu->ir_table->base + index);
+ index = irq_iommu->irte_index + irq_iommu->sub_handle;
+ *entry = *(irq_iommu->iommu->ir_table->base + index);
spin_unlock(&irq_2_ir_lock);
return 0;
@@ -54,6 +78,7 @@ int get_irte(int irq, struct irte *entry)
int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
{
struct ir_table *table = iommu->ir_table;
+ struct irq_2_iommu *irq_iommu;
u16 index, start_index;
unsigned int mask = 0;
int i;
@@ -61,6 +86,10 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
if (!count)
return -1;
+ /* protect irq_2_iommu_alloc later */
+ if (irq >= nr_irqs)
+ return -1;
+
/*
* start the IRTE search from index 0.
*/
@@ -100,10 +129,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
for (i = index; i < index + count; i++)
table->base[i].present = 1;
- irq_2_iommu[irq].iommu = iommu;
- irq_2_iommu[irq].irte_index = index;
- irq_2_iommu[irq].sub_handle = 0;
- irq_2_iommu[irq].irte_mask = mask;
+ irq_iommu = irq_2_iommu_alloc(irq);
+ irq_iommu->iommu = iommu;
+ irq_iommu->irte_index = index;
+ irq_iommu->sub_handle = 0;
+ irq_iommu->irte_mask = mask;
spin_unlock(&irq_2_ir_lock);
@@ -124,31 +154,33 @@ static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
int map_irq_to_irte_handle(int irq, u16 *sub_handle)
{
int index;
+ struct irq_2_iommu *irq_iommu;
spin_lock(&irq_2_ir_lock);
- if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ irq_iommu = valid_irq_2_iommu(irq);
+ if (!irq_iommu) {
spin_unlock(&irq_2_ir_lock);
return -1;
}
- *sub_handle = irq_2_iommu[irq].sub_handle;
- index = irq_2_iommu[irq].irte_index;
+ *sub_handle = irq_iommu->sub_handle;
+ index = irq_iommu->irte_index;
spin_unlock(&irq_2_ir_lock);
return index;
}
int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
{
+ struct irq_2_iommu *irq_iommu;
+
spin_lock(&irq_2_ir_lock);
- if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
- spin_unlock(&irq_2_ir_lock);
- return -1;
- }
- irq_2_iommu[irq].iommu = iommu;
- irq_2_iommu[irq].irte_index = index;
- irq_2_iommu[irq].sub_handle = subhandle;
- irq_2_iommu[irq].irte_mask = 0;
+ irq_iommu = irq_2_iommu_alloc(irq);
+
+ irq_iommu->iommu = iommu;
+ irq_iommu->irte_index = index;
+ irq_iommu->sub_handle = subhandle;
+ irq_iommu->irte_mask = 0;
spin_unlock(&irq_2_ir_lock);
@@ -157,16 +189,19 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
{
+ struct irq_2_iommu *irq_iommu;
+
spin_lock(&irq_2_ir_lock);
- if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ irq_iommu = valid_irq_2_iommu(irq);
+ if (!irq_iommu) {
spin_unlock(&irq_2_ir_lock);
return -1;
}
- irq_2_iommu[irq].iommu = NULL;
- irq_2_iommu[irq].irte_index = 0;
- irq_2_iommu[irq].sub_handle = 0;
- irq_2_iommu[irq].irte_mask = 0;
+ irq_iommu->iommu = NULL;
+ irq_iommu->irte_index = 0;
+ irq_iommu->sub_handle = 0;
+ irq_2_iommu(irq)->irte_mask = 0;
spin_unlock(&irq_2_ir_lock);
@@ -178,16 +213,18 @@ int modify_irte(int irq, struct irte *irte_modified)
int index;
struct irte *irte;
struct intel_iommu *iommu;
+ struct irq_2_iommu *irq_iommu;
spin_lock(&irq_2_ir_lock);
- if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ irq_iommu = valid_irq_2_iommu(irq);
+ if (!irq_iommu) {
spin_unlock(&irq_2_ir_lock);
return -1;
}
- iommu = irq_2_iommu[irq].iommu;
+ iommu = irq_iommu->iommu;
- index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+ index = irq_iommu->irte_index + irq_iommu->sub_handle;
irte = &iommu->ir_table->base[index];
set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
@@ -203,18 +240,20 @@ int flush_irte(int irq)
{
int index;
struct intel_iommu *iommu;
+ struct irq_2_iommu *irq_iommu;
spin_lock(&irq_2_ir_lock);
- if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ irq_iommu = valid_irq_2_iommu(irq);
+ if (!irq_iommu) {
spin_unlock(&irq_2_ir_lock);
return -1;
}
- iommu = irq_2_iommu[irq].iommu;
+ iommu = irq_iommu->iommu;
- index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+ index = irq_iommu->irte_index + irq_iommu->sub_handle;
- qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
+ qi_flush_iec(iommu, index, irq_iommu->irte_mask);
spin_unlock(&irq_2_ir_lock);
return 0;
@@ -246,28 +285,30 @@ int free_irte(int irq)
int index, i;
struct irte *irte;
struct intel_iommu *iommu;
+ struct irq_2_iommu *irq_iommu;
spin_lock(&irq_2_ir_lock);
- if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ irq_iommu = valid_irq_2_iommu(irq);
+ if (!irq_iommu) {
spin_unlock(&irq_2_ir_lock);
return -1;
}
- iommu = irq_2_iommu[irq].iommu;
+ iommu = irq_iommu->iommu;
- index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+ index = irq_iommu->irte_index + irq_iommu->sub_handle;
irte = &iommu->ir_table->base[index];
- if (!irq_2_iommu[irq].sub_handle) {
- for (i = 0; i < (1 << irq_2_iommu[irq].irte_mask); i++)
+ if (!irq_iommu->sub_handle) {
+ for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
set_64bit((unsigned long *)irte, 0);
- qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
+ qi_flush_iec(iommu, index, irq_iommu->irte_mask);
}
- irq_2_iommu[irq].iommu = NULL;
- irq_2_iommu[irq].irte_index = 0;
- irq_2_iommu[irq].sub_handle = 0;
- irq_2_iommu[irq].irte_mask = 0;
+ irq_iommu->iommu = NULL;
+ irq_iommu->irte_index = 0;
+ irq_iommu->sub_handle = 0;
+ irq_iommu->irte_mask = 0;
spin_unlock(&irq_2_ir_lock);
diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c
new file mode 100644
index 00000000000..6441dfa969a
--- /dev/null
+++ b/drivers/pci/irq.c
@@ -0,0 +1,60 @@
+/*
+ * PCI IRQ failure handing code
+ *
+ * Copyright (c) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
+{
+ struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
+
+ dev_printk(KERN_ERR, &pdev->dev,
+ "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
+ parent->dev.bus_id, parent->vendor, parent->device);
+ dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
+ dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
+ WARN_ON(1);
+}
+
+/**
+ * pci_lost_interrupt - reports a lost PCI interrupt
+ * @pdev: device whose interrupt is lost
+ *
+ * The primary function of this routine is to report a lost interrupt
+ * in a standard way which users can recognise (instead of blaming the
+ * driver).
+ *
+ * Returns:
+ * a suggestion for fixing it (although the driver is not required to
+ * act on this).
+ */
+enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *pdev)
+{
+ if (pdev->msi_enabled || pdev->msix_enabled) {
+ enum pci_lost_interrupt_reason ret;
+
+ if (pdev->msix_enabled) {
+ pci_note_irq_problem(pdev, "MSIX routing failure");
+ ret = PCI_LOST_IRQ_DISABLE_MSIX;
+ } else {
+ pci_note_irq_problem(pdev, "MSI routing failure");
+ ret = PCI_LOST_IRQ_DISABLE_MSI;
+ }
+ return ret;
+ }
+#ifdef CONFIG_ACPI
+ if (!(acpi_disabled || acpi_noirq)) {
+ pci_note_irq_problem(pdev, "Potential ACPI misrouting please reboot with acpi=noirq");
+ /* currently no way to fix acpi on the fly */
+ return PCI_LOST_IRQ_DISABLE_ACPI;
+ }
+#endif
+ pci_note_irq_problem(pdev, "unknown cause (not MSI or ACPI)");
+ return PCI_LOST_IRQ_NO_INFORMATION;
+}
+EXPORT_SYMBOL(pci_lost_interrupt);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 4a10b5624f7..74801f7df9c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -378,23 +378,21 @@ static int msi_capability_init(struct pci_dev *dev)
entry->msi_attrib.masked = 1;
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = pos;
- if (is_mask_bit_support(control)) {
+ if (entry->msi_attrib.maskbit) {
entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
- is_64bit_address(control));
+ entry->msi_attrib.is_64);
}
entry->dev = dev;
if (entry->msi_attrib.maskbit) {
unsigned int maskbits, temp;
/* All MSIs are unmasked by default, Mask them all */
pci_read_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
+ msi_mask_bits_reg(pos, entry->msi_attrib.is_64),
&maskbits);
temp = (1 << multi_msi_capable(control));
temp = ((temp - 1) & ~temp);
maskbits |= temp;
- pci_write_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- maskbits);
+ pci_write_config_dword(dev, entry->msi_attrib.is_64, maskbits);
entry->msi_attrib.maskbits_mask = temp;
}
list_add_tail(&entry->list, &dev->msi_list);
@@ -761,3 +759,24 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
{
INIT_LIST_HEAD(&dev->msi_list);
}
+
+#ifdef CONFIG_ACPI
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+static void __devinit msi_acpi_init(void)
+{
+ if (acpi_pci_disabled)
+ return;
+ pci_osc_support_set(OSC_MSI_SUPPORT);
+ pcie_osc_support_set(OSC_MSI_SUPPORT);
+}
+#else
+static inline void msi_acpi_init(void) { }
+#endif /* CONFIG_ACPI */
+
+void __devinit msi_init(void)
+{
+ if (!pci_msi_enable)
+ return;
+ msi_acpi_init();
+}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 89a2f0fa10f..b3a63edb690 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -24,17 +24,17 @@ struct acpi_osc_data {
acpi_handle handle;
u32 support_set;
u32 control_set;
- int is_queried;
- u32 query_result;
struct list_head sibiling;
};
static LIST_HEAD(acpi_osc_data_list);
struct acpi_osc_args {
u32 capbuf[3];
- u32 query_result;
+ u32 ctrl_result;
};
+static DEFINE_MUTEX(pci_acpi_lock);
+
static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
{
struct acpi_osc_data *data;
@@ -83,6 +83,9 @@ static acpi_status acpi_run_osc(acpi_handle handle,
if (ACPI_FAILURE(status))
return status;
+ if (!output.length)
+ return AE_NULL_OBJECT;
+
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n");
@@ -108,9 +111,8 @@ static acpi_status acpi_run_osc(acpi_handle handle,
goto out_kfree;
}
out_success:
- if (flags & OSC_QUERY_ENABLE)
- osc_args->query_result =
- *((u32 *)(out_obj->buffer.pointer + 8));
+ osc_args->ctrl_result =
+ *((u32 *)(out_obj->buffer.pointer + 8));
status = AE_OK;
out_kfree:
@@ -118,41 +120,53 @@ out_kfree:
return status;
}
-static acpi_status acpi_query_osc(acpi_handle handle,
- u32 level, void *context, void **retval)
+static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
+ u32 *result)
{
acpi_status status;
- struct acpi_osc_data *osc_data;
- u32 flags = (unsigned long)context, support_set;
- acpi_handle tmp;
+ u32 support_set;
struct acpi_osc_args osc_args;
- status = acpi_get_handle(handle, "_OSC", &tmp);
- if (ACPI_FAILURE(status))
- return status;
-
- osc_data = acpi_get_osc_data(handle);
- if (!osc_data) {
- printk(KERN_ERR "acpi osc data array is full\n");
- return AE_ERROR;
- }
-
/* do _OSC query for all possible controls */
support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
- status = acpi_run_osc(handle, &osc_args);
+ status = acpi_run_osc(osc_data->handle, &osc_args);
if (ACPI_SUCCESS(status)) {
osc_data->support_set = support_set;
- osc_data->query_result = osc_args.query_result;
- osc_data->is_queried = 1;
+ *result = osc_args.ctrl_result;
}
return status;
}
+static acpi_status acpi_query_osc(acpi_handle handle,
+ u32 level, void *context, void **retval)
+{
+ acpi_status status;
+ struct acpi_osc_data *osc_data;
+ u32 flags = (unsigned long)context, dummy;
+ acpi_handle tmp;
+
+ status = acpi_get_handle(handle, "_OSC", &tmp);
+ if (ACPI_FAILURE(status))
+ return AE_OK;
+
+ mutex_lock(&pci_acpi_lock);
+ osc_data = acpi_get_osc_data(handle);
+ if (!osc_data) {
+ printk(KERN_ERR "acpi osc data array is full\n");
+ goto out;
+ }
+
+ __acpi_query_osc(flags, osc_data, &dummy);
+out:
+ mutex_unlock(&pci_acpi_lock);
+ return AE_OK;
+}
+
/**
* __pci_osc_support_set - register OS support to Firmware
* @flags: OS support bits
@@ -181,7 +195,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
{
acpi_status status;
- u32 ctrlset, control_set;
+ u32 ctrlset, control_set, result;
acpi_handle tmp;
struct acpi_osc_data *osc_data;
struct acpi_osc_args osc_args;
@@ -190,19 +204,28 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
if (ACPI_FAILURE(status))
return status;
+ mutex_lock(&pci_acpi_lock);
osc_data = acpi_get_osc_data(handle);
if (!osc_data) {
printk(KERN_ERR "acpi osc data array is full\n");
- return AE_ERROR;
+ status = AE_ERROR;
+ goto out;
}
ctrlset = (flags & OSC_CONTROL_MASKS);
- if (!ctrlset)
- return AE_TYPE;
+ if (!ctrlset) {
+ status = AE_TYPE;
+ goto out;
+ }
- if (osc_data->is_queried &&
- ((osc_data->query_result & ctrlset) != ctrlset))
- return AE_SUPPORT;
+ status = __acpi_query_osc(osc_data->support_set, osc_data, &result);
+ if (ACPI_FAILURE(status))
+ goto out;
+
+ if ((result & ctrlset) != ctrlset) {
+ status = AE_SUPPORT;
+ goto out;
+ }
control_set = osc_data->control_set | ctrlset;
osc_args.capbuf[OSC_QUERY_TYPE] = 0;
@@ -211,7 +234,8 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
status = acpi_run_osc(handle, &osc_args);
if (ACPI_SUCCESS(status))
osc_data->control_set = control_set;
-
+out:
+ mutex_unlock(&pci_acpi_lock);
return status;
}
EXPORT_SYMBOL(pci_osc_control_set);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a13f5348611..b4cdd690ae7 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -43,18 +43,32 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
{
struct pci_dynid *dynid;
struct pci_driver *pdrv = to_pci_driver(driver);
+ const struct pci_device_id *ids = pdrv->id_table;
__u32 vendor, device, subvendor=PCI_ANY_ID,
subdevice=PCI_ANY_ID, class=0, class_mask=0;
unsigned long driver_data=0;
int fields=0;
- int retval = 0;
+ int retval;
- fields = sscanf(buf, "%x %x %x %x %x %x %lux",
+ fields = sscanf(buf, "%x %x %x %x %x %x %lx",
&vendor, &device, &subvendor, &subdevice,
&class, &class_mask, &driver_data);
if (fields < 2)
return -EINVAL;
+ /* Only accept driver_data values that match an existing id_table
+ entry */
+ retval = -EINVAL;
+ while (ids->vendor || ids->subvendor || ids->class_mask) {
+ if (driver_data == ids->driver_data) {
+ retval = 0;
+ break;
+ }
+ ids++;
+ }
+ if (retval) /* No match */
+ return retval;
+
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
if (!dynid)
return -ENOMEM;
@@ -65,8 +79,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
dynid->id.subdevice = subdevice;
dynid->id.class = class;
dynid->id.class_mask = class_mask;
- dynid->id.driver_data = pdrv->dynids.use_driver_data ?
- driver_data : 0UL;
+ dynid->id.driver_data = driver_data;
spin_lock(&pdrv->dynids.lock);
list_add_tail(&dynid->node, &pdrv->dynids.list);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 77baff022f7..110022d7868 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -423,7 +423,7 @@ pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
* Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
* callback routine (pci_legacy_read).
*/
-ssize_t
+static ssize_t
pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
@@ -448,7 +448,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
* Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
* callback routine (pci_legacy_write).
*/
-ssize_t
+static ssize_t
pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
@@ -468,11 +468,11 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
* @attr: struct bin_attribute for this file
* @vma: struct vm_area_struct passed to mmap
*
- * Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap
+ * Uses an arch specific callback, pci_mmap_legacy_mem_page_range, to mmap
* legacy memory space (first meg of bus space) into application virtual
* memory space.
*/
-int
+static int
pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
struct vm_area_struct *vma)
{
@@ -480,7 +480,90 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
struct device,
kobj));
- return pci_mmap_legacy_page_range(bus, vma);
+ return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);
+}
+
+/**
+ * pci_mmap_legacy_io - map legacy PCI IO into user memory space
+ * @kobj: kobject corresponding to device to be mapped
+ * @attr: struct bin_attribute for this file
+ * @vma: struct vm_area_struct passed to mmap
+ *
+ * Uses an arch specific callback, pci_mmap_legacy_io_page_range, to mmap
+ * legacy IO space (first meg of bus space) into application virtual
+ * memory space. Returns -ENOSYS if the operation isn't supported
+ */
+static int
+pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr,
+ struct vm_area_struct *vma)
+{
+ struct pci_bus *bus = to_pci_bus(container_of(kobj,
+ struct device,
+ kobj));
+
+ return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);
+}
+
+/**
+ * pci_create_legacy_files - create legacy I/O port and memory files
+ * @b: bus to create files under
+ *
+ * Some platforms allow access to legacy I/O port and ISA memory space on
+ * a per-bus basis. This routine creates the files and ties them into
+ * their associated read, write and mmap files from pci-sysfs.c
+ *
+ * On error unwind, but don't propogate the error to the caller
+ * as it is ok to set up the PCI bus without these files.
+ */
+void pci_create_legacy_files(struct pci_bus *b)
+{
+ int error;
+
+ b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
+ GFP_ATOMIC);
+ if (!b->legacy_io)
+ goto kzalloc_err;
+
+ b->legacy_io->attr.name = "legacy_io";
+ b->legacy_io->size = 0xffff;
+ b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
+ b->legacy_io->read = pci_read_legacy_io;
+ b->legacy_io->write = pci_write_legacy_io;
+ b->legacy_io->mmap = pci_mmap_legacy_io;
+ error = device_create_bin_file(&b->dev, b->legacy_io);
+ if (error)
+ goto legacy_io_err;
+
+ /* Allocated above after the legacy_io struct */
+ b->legacy_mem = b->legacy_io + 1;
+ b->legacy_mem->attr.name = "legacy_mem";
+ b->legacy_mem->size = 1024*1024;
+ b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
+ b->legacy_mem->mmap = pci_mmap_legacy_mem;
+ error = device_create_bin_file(&b->dev, b->legacy_mem);
+ if (error)
+ goto legacy_mem_err;
+
+ return;
+
+legacy_mem_err:
+ device_remove_bin_file(&b->dev, b->legacy_io);
+legacy_io_err:
+ kfree(b->legacy_io);
+ b->legacy_io = NULL;
+kzalloc_err:
+ printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
+ "and ISA memory resources to sysfs\n");
+ return;
+}
+
+void pci_remove_legacy_files(struct pci_bus *b)
+{
+ if (b->legacy_io) {
+ device_remove_bin_file(&b->dev, b->legacy_io);
+ device_remove_bin_file(&b->dev, b->legacy_mem);
+ kfree(b->legacy_io); /* both are allocated here */
+ }
}
#endif /* HAVE_PCI_LEGACY */
@@ -715,7 +798,7 @@ static struct bin_attribute pci_config_attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
},
- .size = 256,
+ .size = PCI_CFG_SPACE_SIZE,
.read = pci_read_config,
.write = pci_write_config,
};
@@ -725,7 +808,7 @@ static struct bin_attribute pcie_config_attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
},
- .size = 4096,
+ .size = PCI_CFG_SPACE_EXP_SIZE,
.read = pci_read_config,
.write = pci_write_config,
};
@@ -735,86 +818,103 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
return 0;
}
+static int pci_create_capabilities_sysfs(struct pci_dev *dev)
+{
+ int retval;
+ struct bin_attribute *attr;
+
+ /* If the device has VPD, try to expose it in sysfs. */
+ if (dev->vpd) {
+ attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
+ if (!attr)
+ return -ENOMEM;
+
+ attr->size = dev->vpd->len;
+ attr->attr.name = "vpd";
+ attr->attr.mode = S_IRUSR | S_IWUSR;
+ attr->read = pci_read_vpd;
+ attr->write = pci_write_vpd;
+ retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
+ if (retval) {
+ kfree(dev->vpd->attr);
+ return retval;
+ }
+ dev->vpd->attr = attr;
+ }
+
+ /* Active State Power Management */
+ pcie_aspm_create_sysfs_dev_files(dev);
+
+ return 0;
+}
+
int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
{
- struct bin_attribute *attr = NULL;
int retval;
+ int rom_size = 0;
+ struct bin_attribute *attr;
if (!sysfs_initialized)
return -EACCES;
- if (pdev->cfg_size < 4096)
+ if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
else
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
if (retval)
goto err;
- /* If the device has VPD, try to expose it in sysfs. */
- if (pdev->vpd) {
- attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
- if (attr) {
- pdev->vpd->attr = attr;
- attr->size = pdev->vpd->len;
- attr->attr.name = "vpd";
- attr->attr.mode = S_IRUSR | S_IWUSR;
- attr->read = pci_read_vpd;
- attr->write = pci_write_vpd;
- retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
- if (retval)
- goto err_vpd;
- } else {
- retval = -ENOMEM;
- goto err_config_file;
- }
- }
-
retval = pci_create_resource_files(pdev);
if (retval)
- goto err_vpd_file;
+ goto err_config_file;
+
+ if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+ rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+ else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+ rom_size = 0x20000;
/* If the device has a ROM, try to expose it in sysfs. */
- if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
- (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
+ if (rom_size) {
attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
- if (attr) {
- pdev->rom_attr = attr;
- attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- attr->attr.name = "rom";
- attr->attr.mode = S_IRUSR;
- attr->read = pci_read_rom;
- attr->write = pci_write_rom;
- retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
- if (retval)
- goto err_rom;
- } else {
+ if (!attr) {
retval = -ENOMEM;
goto err_resource_files;
}
+ attr->size = rom_size;
+ attr->attr.name = "rom";
+ attr->attr.mode = S_IRUSR;
+ attr->read = pci_read_rom;
+ attr->write = pci_write_rom;
+ retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
+ if (retval) {
+ kfree(attr);
+ goto err_resource_files;
+ }
+ pdev->rom_attr = attr;
}
+
/* add platform-specific attributes */
- if (pcibios_add_platform_entries(pdev))
+ retval = pcibios_add_platform_entries(pdev);
+ if (retval)
goto err_rom_file;
- pcie_aspm_create_sysfs_dev_files(pdev);
+ /* add sysfs entries for various capabilities */
+ retval = pci_create_capabilities_sysfs(pdev);
+ if (retval)
+ goto err_rom_file;
return 0;
err_rom_file:
- if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+ if (rom_size) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
-err_rom:
- kfree(pdev->rom_attr);
+ kfree(pdev->rom_attr);
+ pdev->rom_attr = NULL;
+ }
err_resource_files:
pci_remove_resource_files(pdev);
-err_vpd_file:
- if (pdev->vpd) {
- sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
-err_vpd:
- kfree(pdev->vpd->attr);
- }
err_config_file:
- if (pdev->cfg_size < 4096)
+ if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
@@ -822,6 +922,16 @@ err:
return retval;
}
+static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
+{
+ if (dev->vpd && dev->vpd->attr) {
+ sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
+ kfree(dev->vpd->attr);
+ }
+
+ pcie_aspm_remove_sysfs_dev_files(dev);
+}
+
/**
* pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
* @pdev: device whose entries we should free
@@ -830,27 +940,28 @@ err:
*/
void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
{
+ int rom_size = 0;
+
if (!sysfs_initialized)
return;
- pcie_aspm_remove_sysfs_dev_files(pdev);
+ pci_remove_capabilities_sysfs(pdev);
- if (pdev->vpd) {
- sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
- kfree(pdev->vpd->attr);
- }
- if (pdev->cfg_size < 4096)
+ if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
pci_remove_resource_files(pdev);
- if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
- if (pdev->rom_attr) {
- sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
- kfree(pdev->rom_attr);
- }
+ if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+ rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+ else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+ rom_size = 0x20000;
+
+ if (rom_size && pdev->rom_attr) {
+ sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
+ kfree(pdev->rom_attr);
}
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c9884bba22d..21f2ac639ca 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -18,6 +18,7 @@
#include <linux/log2.h>
#include <linux/pci-aspm.h>
#include <linux/pm_wakeup.h>
+#include <linux/interrupt.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -213,10 +214,13 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
int pci_find_ext_capability(struct pci_dev *dev, int cap)
{
u32 header;
- int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
- int pos = 0x100;
+ int ttl;
+ int pos = PCI_CFG_SPACE_SIZE;
- if (dev->cfg_size <= 256)
+ /* minimum 8 bytes per capability */
+ ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+ if (dev->cfg_size <= PCI_CFG_SPACE_SIZE)
return 0;
if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
@@ -234,7 +238,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
return pos;
pos = PCI_EXT_CAP_NEXT(header);
- if (pos < 0x100)
+ if (pos < PCI_CFG_SPACE_SIZE)
break;
if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
@@ -1127,6 +1131,27 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
}
/**
+ * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
+ * @dev: PCI device to prepare
+ * @enable: True to enable wake-up event generation; false to disable
+ *
+ * Many drivers want the device to wake up the system from D3_hot or D3_cold
+ * and this function allows them to set that up cleanly - pci_enable_wake()
+ * should not be called twice in a row to enable wake-up due to PCI PM vs ACPI
+ * ordering constraints.
+ *
+ * This function only returns error code if the device is not capable of
+ * generating PME# from both D3_hot and D3_cold, and the platform is unable to
+ * enable wake-up power for it.
+ */
+int pci_wake_from_d3(struct pci_dev *dev, bool enable)
+{
+ return pci_pme_capable(dev, PCI_D3cold) ?
+ pci_enable_wake(dev, PCI_D3cold, enable) :
+ pci_enable_wake(dev, PCI_D3hot, enable);
+}
+
+/**
* pci_target_state - find an appropriate low power state for a given PCI dev
* @dev: PCI device
*
@@ -1242,25 +1267,25 @@ void pci_pm_init(struct pci_dev *dev)
dev->d1_support = false;
dev->d2_support = false;
if (!pci_no_d1d2(dev)) {
- if (pmc & PCI_PM_CAP_D1) {
- dev_printk(KERN_DEBUG, &dev->dev, "supports D1\n");
+ if (pmc & PCI_PM_CAP_D1)
dev->d1_support = true;
- }
- if (pmc & PCI_PM_CAP_D2) {
- dev_printk(KERN_DEBUG, &dev->dev, "supports D2\n");
+ if (pmc & PCI_PM_CAP_D2)
dev->d2_support = true;
- }
+
+ if (dev->d1_support || dev->d2_support)
+ dev_printk(KERN_DEBUG, &dev->dev, "supports%s%s\n",
+ dev->d1_support ? " D1" : "",
+ dev->d2_support ? " D2" : "");
}
pmc &= PCI_PM_CAP_PME_MASK;
if (pmc) {
- dev_printk(KERN_INFO, &dev->dev,
- "PME# supported from%s%s%s%s%s\n",
- (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
- (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
- (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
- (pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
- (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
+ dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n",
+ (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
+ (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
+ (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
+ (pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
+ (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT;
/*
* Make device's PM flags reflect the wake-up capability, but
@@ -1275,6 +1300,43 @@ void pci_pm_init(struct pci_dev *dev)
}
}
+/**
+ * pci_enable_ari - enable ARI forwarding if hardware support it
+ * @dev: the PCI device
+ */
+void pci_enable_ari(struct pci_dev *dev)
+{
+ int pos;
+ u32 cap;
+ u16 ctrl;
+ struct pci_dev *bridge;
+
+ if (!dev->is_pcie || dev->devfn)
+ return;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
+ if (!pos)
+ return;
+
+ bridge = dev->bus->self;
+ if (!bridge || !bridge->is_pcie)
+ return;
+
+ pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+
+ pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
+ if (!(cap & PCI_EXP_DEVCAP2_ARI))
+ return;
+
+ pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl);
+ ctrl |= PCI_EXP_DEVCTL2_ARI;
+ pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl);
+
+ bridge->ari_enabled = 1;
+}
+
int
pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
{
@@ -1358,11 +1420,10 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
return 0;
err_out:
- dev_warn(&pdev->dev, "BAR %d: can't reserve %s region [%#llx-%#llx]\n",
+ dev_warn(&pdev->dev, "BAR %d: can't reserve %s region %pR\n",
bar,
pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
- (unsigned long long)pci_resource_start(pdev, bar),
- (unsigned long long)pci_resource_end(pdev, bar));
+ &pdev->resource[bar]);
return -EBUSY;
}
@@ -1691,6 +1752,103 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
#endif
/**
+ * pci_execute_reset_function() - Reset a PCI device function
+ * @dev: Device function to reset
+ *
+ * Some devices allow an individual function to be reset without affecting
+ * other functions in the same device. The PCI device must be responsive
+ * to PCI config space in order to use this function.
+ *
+ * The device function is presumed to be unused when this function is called.
+ * Resetting the device will make the contents of PCI configuration space
+ * random, so any caller of this must be prepared to reinitialise the
+ * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
+ * etc.
+ *
+ * Returns 0 if the device function was successfully reset or -ENOTTY if the
+ * device doesn't support resetting a single function.
+ */
+int pci_execute_reset_function(struct pci_dev *dev)
+{
+ u16 status;
+ u32 cap;
+ int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+
+ if (!exppos)
+ return -ENOTTY;
+ pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
+ if (!(cap & PCI_EXP_DEVCAP_FLR))
+ return -ENOTTY;
+
+ pci_block_user_cfg_access(dev);
+
+ /* Wait for Transaction Pending bit clean */
+ msleep(100);
+ pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
+ if (status & PCI_EXP_DEVSTA_TRPND) {
+ dev_info(&dev->dev, "Busy after 100ms while trying to reset; "
+ "sleeping for 1 second\n");
+ ssleep(1);
+ pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
+ if (status & PCI_EXP_DEVSTA_TRPND)
+ dev_info(&dev->dev, "Still busy after 1s; "
+ "proceeding with reset anyway\n");
+ }
+
+ pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_BCR_FLR);
+ mdelay(100);
+
+ pci_unblock_user_cfg_access(dev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_execute_reset_function);
+
+/**
+ * pci_reset_function() - quiesce and reset a PCI device function
+ * @dev: Device function to reset
+ *
+ * Some devices allow an individual function to be reset without affecting
+ * other functions in the same device. The PCI device must be responsive
+ * to PCI config space in order to use this function.
+ *
+ * This function does not just reset the PCI portion of a device, but
+ * clears all the state associated with the device. This function differs
+ * from pci_execute_reset_function in that it saves and restores device state
+ * over the reset.
+ *
+ * Returns 0 if the device function was successfully reset or -ENOTTY if the
+ * device doesn't support resetting a single function.
+ */
+int pci_reset_function(struct pci_dev *dev)
+{
+ u32 cap;
+ int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ int r;
+
+ if (!exppos)
+ return -ENOTTY;
+ pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
+ if (!(cap & PCI_EXP_DEVCAP_FLR))
+ return -ENOTTY;
+
+ if (!dev->msi_enabled && !dev->msix_enabled)
+ disable_irq(dev->irq);
+ pci_save_state(dev);
+
+ pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
+
+ r = pci_execute_reset_function(dev);
+
+ pci_restore_state(dev);
+ if (!dev->msi_enabled && !dev->msix_enabled)
+ enable_irq(dev->irq);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(pci_reset_function);
+
+/**
* pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
* @dev: PCI device to query
*
@@ -1878,6 +2036,9 @@ static int __devinit pci_init(void)
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
pci_fixup_device(pci_fixup_final, dev);
}
+
+ msi_init();
+
return 0;
}
@@ -1943,6 +2104,7 @@ EXPORT_SYMBOL(pci_restore_state);
EXPORT_SYMBOL(pci_pme_capable);
EXPORT_SYMBOL(pci_pme_active);
EXPORT_SYMBOL(pci_enable_wake);
+EXPORT_SYMBOL(pci_wake_from_d3);
EXPORT_SYMBOL(pci_target_state);
EXPORT_SYMBOL(pci_prepare_to_sleep);
EXPORT_SYMBOL(pci_back_from_sleep);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d807cd786f2..9de87e9f98f 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1,3 +1,9 @@
+#ifndef DRIVERS_PCI_H
+#define DRIVERS_PCI_H
+
+#define PCI_CFG_SPACE_SIZE 256
+#define PCI_CFG_SPACE_EXP_SIZE 4096
+
/* Functions internal to the PCI core code */
extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
@@ -76,7 +82,13 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
/* Functions for PCI Hotplug drivers to use */
extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
+#ifdef HAVE_PCI_LEGACY
+extern void pci_create_legacy_files(struct pci_bus *bus);
extern void pci_remove_legacy_files(struct pci_bus *bus);
+#else
+static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
+static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
+#endif
/* Lock for read/write access to pci device and bus lists */
extern struct rw_semaphore pci_bus_sem;
@@ -86,9 +98,11 @@ extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
void pci_no_msi(void);
extern void pci_msi_init_pci_dev(struct pci_dev *dev);
+extern void __devinit msi_init(void);
#else
static inline void pci_no_msi(void) { }
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
+static inline void msi_init(void) { }
#endif
#ifdef CONFIG_PCIEAER
@@ -109,6 +123,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute dev_attr_cpuaffinity;
+extern struct device_attribute dev_attr_cpulistaffinity;
/**
* pci_match_one_device - Tell if a PCI device structure has a matching
@@ -144,3 +159,16 @@ struct pci_slot_attribute {
};
#define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
+extern void pci_enable_ari(struct pci_dev *dev);
+/**
+ * pci_ari_enabled - query ARI forwarding status
+ * @dev: the PCI device
+ *
+ * Returns 1 if ARI forwarding is enabled, or 0 if not enabled;
+ */
+static inline int pci_ari_enabled(struct pci_dev *dev)
+{
+ return dev->ari_enabled;
+}
+
+#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 77036f46acf..e390707661d 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -105,7 +105,7 @@ static irqreturn_t aer_irq(int irq, void *context)
unsigned long flags;
int pos;
- pos = pci_find_aer_capability(pdev->port);
+ pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR);
/*
* Must lock access to Root Error Status Reg, Root Error ID Reg,
* and Root error producer/consumer index
@@ -252,7 +252,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
u32 status;
int pos;
- pos = pci_find_aer_capability(dev);
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
/* Disable Root's interrupt in response to error messages */
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
@@ -316,7 +316,7 @@ static void aer_error_resume(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
/* Clean AER Root Error Status */
- pos = pci_find_aer_capability(dev);
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
if (dev->error_state == pci_channel_io_normal)
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index ee5e7b5176d..dfc63d01f20 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -28,41 +28,15 @@
static int forceload;
module_param(forceload, bool, 0);
-#define PCI_CFG_SPACE_SIZE (0x100)
-int pci_find_aer_capability(struct pci_dev *dev)
-{
- int pos;
- u32 reg32 = 0;
-
- /* Check if it's a pci-express device */
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
- if (!pos)
- return 0;
-
- /* Check if it supports pci-express AER */
- pos = PCI_CFG_SPACE_SIZE;
- while (pos) {
- if (pci_read_config_dword(dev, pos, &reg32))
- return 0;
-
- /* some broken boards return ~0 */
- if (reg32 == 0xffffffff)
- return 0;
-
- if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
- break;
-
- pos = reg32 >> 20;
- }
-
- return pos;
-}
-
int pci_enable_pcie_error_reporting(struct pci_dev *dev)
{
u16 reg16 = 0;
int pos;
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ return -EIO;
+
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (!pos)
return -EIO;
@@ -102,7 +76,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
int pos;
u32 status, mask;
- pos = pci_find_aer_capability(dev);
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return -EIO;
@@ -123,7 +97,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
int pos;
u32 status;
- pos = pci_find_aer_capability(dev);
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return -EIO;
@@ -502,7 +476,7 @@ static void handle_error_source(struct pcie_device * aerdev,
* Correctable error does not need software intevention.
* No need to go through error recovery process.
*/
- pos = pci_find_aer_capability(dev);
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (pos)
pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
info.status);
@@ -542,7 +516,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
- aer_pos = pci_find_aer_capability(pdev);
+ aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
/* Clear error status */
pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
@@ -579,7 +553,7 @@ static void disable_root_aer(struct aer_rpc *rpc)
u32 reg32;
int pos;
- pos = pci_find_aer_capability(pdev);
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
/* Disable Root's interrupt in response to error messages */
pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
@@ -618,7 +592,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
{
int pos;
- pos = pci_find_aer_capability(dev);
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
/* The device might not support AER */
if (!pos)
@@ -755,7 +729,6 @@ int aer_init(struct pcie_device *dev)
return AER_SUCCESS;
}
-EXPORT_SYMBOL_GPL(pci_find_aer_capability);
EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 851f5b83cdb..8f63f4c6b85 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -528,9 +528,9 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
&reg32);
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
- printk("Pre-1.1 PCIe device detected, "
- "disable ASPM for %s. It can be enabled forcedly"
- " with 'pcie_aspm=force'\n", pci_name(pdev));
+ dev_printk(KERN_INFO, &child_dev->dev, "disabling ASPM"
+ " on pre-1.1 PCIe device. You can enable it"
+ " with 'pcie_aspm=force'\n");
return -EINVAL;
}
}
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 3656e0349dd..2529f3f2ea5 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -25,7 +25,6 @@
#define PCIE_CAPABILITIES_REG 0x2
#define PCIE_SLOT_CAPABILITIES_REG 0x14
#define PCIE_PORT_DEVICE_MAXSERVICES 4
-#define PCI_CFG_SPACE_SIZE 256
#define get_descriptor_id(type, service) (((type - 4) << 4) | service)
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 890f0d2b370..2e091e01482 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -195,24 +195,11 @@ static int get_port_device_capability(struct pci_dev *dev)
/* PME Capable - root port capability */
if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
services |= PCIE_PORT_SERVICE_PME;
-
- pos = PCI_CFG_SPACE_SIZE;
- while (pos) {
- pci_read_config_dword(dev, pos, &reg32);
- switch (reg32 & 0xffff) {
- case PCI_EXT_CAP_ID_ERR:
- services |= PCIE_PORT_SERVICE_AER;
- pos = reg32 >> 20;
- break;
- case PCI_EXT_CAP_ID_VC:
- services |= PCIE_PORT_SERVICE_VC;
- pos = reg32 >> 20;
- break;
- default:
- pos = 0;
- break;
- }
- }
+
+ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
+ services |= PCIE_PORT_SERVICE_AER;
+ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
+ services |= PCIE_PORT_SERVICE_VC;
return services;
}
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 367c9c20000..584422da8d8 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
pci_set_master(dev);
if (!dev->irq && dev->pin) {
- dev_warn(&dev->dev, "device [%04x/%04x] has invalid IRQ; "
+ dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
"check vendor BIOS\n", dev->vendor, dev->device);
}
if (pcie_port_device_register(dev)) {
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index dd9161a054e..003a9b3c293 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -14,8 +14,6 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3
-#define PCI_CFG_SPACE_SIZE 256
-#define PCI_CFG_SPACE_EXP_SIZE 4096
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses);
@@ -44,72 +42,6 @@ int no_pci_devices(void)
}
EXPORT_SYMBOL(no_pci_devices);
-#ifdef HAVE_PCI_LEGACY
-/**
- * pci_create_legacy_files - create legacy I/O port and memory files
- * @b: bus to create files under
- *
- * Some platforms allow access to legacy I/O port and ISA memory space on
- * a per-bus basis. This routine creates the files and ties them into
- * their associated read, write and mmap files from pci-sysfs.c
- *
- * On error unwind, but don't propogate the error to the caller
- * as it is ok to set up the PCI bus without these files.
- */
-static void pci_create_legacy_files(struct pci_bus *b)
-{
- int error;
-
- b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
- GFP_ATOMIC);
- if (!b->legacy_io)
- goto kzalloc_err;
-
- b->legacy_io->attr.name = "legacy_io";
- b->legacy_io->size = 0xffff;
- b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
- b->legacy_io->read = pci_read_legacy_io;
- b->legacy_io->write = pci_write_legacy_io;
- error = device_create_bin_file(&b->dev, b->legacy_io);
- if (error)
- goto legacy_io_err;
-
- /* Allocated above after the legacy_io struct */
- b->legacy_mem = b->legacy_io + 1;
- b->legacy_mem->attr.name = "legacy_mem";
- b->legacy_mem->size = 1024*1024;
- b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
- b->legacy_mem->mmap = pci_mmap_legacy_mem;
- error = device_create_bin_file(&b->dev, b->legacy_mem);
- if (error)
- goto legacy_mem_err;
-
- return;
-
-legacy_mem_err:
- device_remove_bin_file(&b->dev, b->legacy_io);
-legacy_io_err:
- kfree(b->legacy_io);
- b->legacy_io = NULL;
-kzalloc_err:
- printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
- "and ISA memory resources to sysfs\n");
- return;
-}
-
-void pci_remove_legacy_files(struct pci_bus *b)
-{
- if (b->legacy_io) {
- device_remove_bin_file(&b->dev, b->legacy_io);
- device_remove_bin_file(&b->dev, b->legacy_mem);
- kfree(b->legacy_io); /* both are allocated here */
- }
-}
-#else /* !HAVE_PCI_LEGACY */
-static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
-void pci_remove_legacy_files(struct pci_bus *bus) { return; }
-#endif /* HAVE_PCI_LEGACY */
-
/*
* PCI Bus Class Devices
*/
@@ -219,7 +151,7 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
- if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64)
+ if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
return pci_bar_mem64;
return pci_bar_mem32;
}
@@ -304,9 +236,8 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
} else {
res->start = l64;
res->end = l64 + sz64;
- printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: [%llx, %llx]\n",
- pci_name(dev), pos, (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "reg %x 64bit mmio: %pR\n", pos, res);
}
} else {
sz = pci_size(l, sz, mask);
@@ -316,9 +247,10 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->start = l;
res->end = l + sz;
- printk(KERN_DEBUG "PCI: %s reg %x %s: [%llx, %llx]\n", pci_name(dev),
- pos, (res->flags & IORESOURCE_IO) ? "io port":"32bit mmio",
- (unsigned long long)res->start, (unsigned long long)res->end);
+
+ dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos,
+ (res->flags & IORESOURCE_IO) ? "io port" : "32bit mmio",
+ res);
}
out:
@@ -366,9 +298,6 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
child->resource[i] = child->parent->resource[i - 3];
}
- for(i=0; i<3; i++)
- child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
-
res = child->resource[0];
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
@@ -389,9 +318,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base;
if (!res->end)
res->end = limit + 0xfff;
- printk(KERN_DEBUG "PCI: bridge %s io port: [%llx, %llx]\n",
- pci_name(dev), (unsigned long long) res->start,
- (unsigned long long) res->end);
+ dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res);
}
res = child->resource[1];
@@ -403,9 +330,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base;
res->end = limit + 0xfffff;
- printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: [%llx, %llx]\n",
- pci_name(dev), (unsigned long long) res->start,
- (unsigned long long) res->end);
+ dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n",
+ res);
}
res = child->resource[2];
@@ -441,9 +367,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
res->start = base;
res->end = limit + 0xfffff;
- printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n",
- pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
- (unsigned long long) res->start, (unsigned long long) res->end);
+ dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
+ (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
+ res);
}
}
@@ -551,19 +477,27 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
u32 buses, i, j = 0;
u16 bctl;
+ int broken = 0;
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
dev_dbg(&dev->dev, "scanning behind bridge, config %06x, pass %d\n",
buses & 0xffffff, pass);
+ /* Check if setup is sensible at all */
+ if (!pass &&
+ ((buses & 0xff) != bus->number || ((buses >> 8) & 0xff) <= bus->number)) {
+ dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
+ broken = 1;
+ }
+
/* Disable MasterAbortMode during probing to avoid reporting
of bus errors (in some architectures) */
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl);
pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
- if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
+ if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus && !broken) {
unsigned int cmax, busnr;
/*
* Bus already configured by firmware, process it in the first
@@ -601,7 +535,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
* do in the second pass.
*/
if (!pass) {
- if (pcibios_assign_all_busses())
+ if (pcibios_assign_all_busses() || broken)
/* Temporarily disable forwarding of the
configuration cycles on all bridges in
this bus segment to avoid possible
@@ -764,7 +698,7 @@ static int pci_setup_device(struct pci_dev * dev)
dev->class = class;
class >>= 8;
- dev_dbg(&dev->dev, "found [%04x/%04x] class %06x header type %02x\n",
+ dev_dbg(&dev->dev, "found [%04x:%04x] class %06x header type %02x\n",
dev->vendor, dev->device, class, dev->hdr_type);
/* "Unknown power state" */
@@ -846,6 +780,11 @@ static int pci_setup_device(struct pci_dev * dev)
return 0;
}
+static void pci_release_capabilities(struct pci_dev *dev)
+{
+ pci_vpd_release(dev);
+}
+
/**
* pci_release_dev - free a pci device structure when all users of it are finished.
* @dev: device that's been disconnected
@@ -858,7 +797,7 @@ static void pci_release_dev(struct device *dev)
struct pci_dev *pci_dev;
pci_dev = to_pci_dev(dev);
- pci_vpd_release(pci_dev);
+ pci_release_capabilities(pci_dev);
kfree(pci_dev);
}
@@ -889,8 +828,9 @@ static void set_pcie_port_type(struct pci_dev *pdev)
int pci_cfg_space_size_ext(struct pci_dev *dev)
{
u32 status;
+ int pos = PCI_CFG_SPACE_SIZE;
- if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)
+ if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
goto fail;
if (status == 0xffffffff)
goto fail;
@@ -938,8 +878,6 @@ struct pci_dev *alloc_pci_dev(void)
INIT_LIST_HEAD(&dev->bus_list);
- pci_msi_init_pci_dev(dev);
-
return dev;
}
EXPORT_SYMBOL(alloc_pci_dev);
@@ -951,6 +889,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{
struct pci_dev *dev;
+ struct pci_slot *slot;
u32 l;
u8 hdr_type;
int delay = 1;
@@ -999,6 +938,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
dev->error_state = pci_channel_io_normal;
set_pcie_port_type(dev);
+ list_for_each_entry(slot, &bus->slots, list)
+ if (PCI_SLOT(devfn) == slot->number)
+ dev->slot = slot;
+
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */
dev->dma_mask = 0xffffffff;
@@ -1007,9 +950,22 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
return NULL;
}
+ return dev;
+}
+
+static void pci_init_capabilities(struct pci_dev *dev)
+{
+ /* MSI/MSI-X list */
+ pci_msi_init_pci_dev(dev);
+
+ /* Power Management */
+ pci_pm_init(dev);
+
+ /* Vital Product Data */
pci_vpd_pci22_init(dev);
- return dev;
+ /* Alternative Routing-ID Forwarding */
+ pci_enable_ari(dev);
}
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
@@ -1028,8 +984,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev);
- /* Initialize power management of the device */
- pci_pm_init(dev);
+ /* Initialize various capabilities */
+ pci_init_capabilities(dev);
/*
* Add the device to our list of discovered devices
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e872ac925b4..96cf8ecd04c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -24,6 +24,14 @@
#include <linux/kallsyms.h>
#include "pci.h"
+int isa_dma_bridge_buggy;
+EXPORT_SYMBOL(isa_dma_bridge_buggy);
+int pci_pci_problems;
+EXPORT_SYMBOL(pci_pci_problems);
+int pcie_mch_quirk;
+EXPORT_SYMBOL(pcie_mch_quirk);
+
+#ifdef CONFIG_PCI_QUIRKS
/* The Mellanox Tavor device gives false positive parity errors
* Mark this device with a broken_parity_status, to allow
* PCI scanning code to "skip" this now blacklisted device.
@@ -35,6 +43,20 @@ static void __devinit quirk_mellanox_tavor(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor);
+/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+int forbid_dac __read_mostly;
+EXPORT_SYMBOL(forbid_dac);
+
+static __devinit void via_no_dac(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+ dev_info(&dev->dev,
+ "VIA PCI bridge detected. Disabling DAC.\n");
+ forbid_dac = 1;
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+
/* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441FX/PPro MTRRs */
static void quirk_passive_release(struct pci_dev *dev)
@@ -62,8 +84,6 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p
This appears to be BIOS not version dependent. So presumably there is a
chipset level fix */
-int isa_dma_bridge_buggy;
-EXPORT_SYMBOL(isa_dma_bridge_buggy);
static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
{
@@ -84,9 +104,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_d
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs);
-int pci_pci_problems;
-EXPORT_SYMBOL(pci_pci_problems);
-
/*
* Chipsets where PCI->PCI transfers vanish or hang
*/
@@ -1362,9 +1379,6 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic);
#endif
-int pcie_mch_quirk;
-EXPORT_SYMBOL(pcie_mch_quirk);
-
static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
{
pcie_mch_quirk = 1;
@@ -1555,84 +1569,6 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
-static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
-{
- while (f < end) {
- if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
- (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
-#ifdef DEBUG
- dev_dbg(&dev->dev, "calling %pF\n", f->hook);
-#endif
- f->hook(dev);
- }
- f++;
- }
-}
-
-extern struct pci_fixup __start_pci_fixups_early[];
-extern struct pci_fixup __end_pci_fixups_early[];
-extern struct pci_fixup __start_pci_fixups_header[];
-extern struct pci_fixup __end_pci_fixups_header[];
-extern struct pci_fixup __start_pci_fixups_final[];
-extern struct pci_fixup __end_pci_fixups_final[];
-extern struct pci_fixup __start_pci_fixups_enable[];
-extern struct pci_fixup __end_pci_fixups_enable[];
-extern struct pci_fixup __start_pci_fixups_resume[];
-extern struct pci_fixup __end_pci_fixups_resume[];
-extern struct pci_fixup __start_pci_fixups_resume_early[];
-extern struct pci_fixup __end_pci_fixups_resume_early[];
-extern struct pci_fixup __start_pci_fixups_suspend[];
-extern struct pci_fixup __end_pci_fixups_suspend[];
-
-
-void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
-{
- struct pci_fixup *start, *end;
-
- switch(pass) {
- case pci_fixup_early:
- start = __start_pci_fixups_early;
- end = __end_pci_fixups_early;
- break;
-
- case pci_fixup_header:
- start = __start_pci_fixups_header;
- end = __end_pci_fixups_header;
- break;
-
- case pci_fixup_final:
- start = __start_pci_fixups_final;
- end = __end_pci_fixups_final;
- break;
-
- case pci_fixup_enable:
- start = __start_pci_fixups_enable;
- end = __end_pci_fixups_enable;
- break;
-
- case pci_fixup_resume:
- start = __start_pci_fixups_resume;
- end = __end_pci_fixups_resume;
- break;
-
- case pci_fixup_resume_early:
- start = __start_pci_fixups_resume_early;
- end = __end_pci_fixups_resume_early;
- break;
-
- case pci_fixup_suspend:
- start = __start_pci_fixups_suspend;
- end = __end_pci_fixups_suspend;
- break;
-
- default:
- /* stupid compiler warning, you would think with an enum... */
- return;
- }
- pci_do_fixups(dev, start, end);
-}
-EXPORT_SYMBOL(pci_fixup_device);
-
/* Enable 1k I/O space granularity on the Intel P64H2 */
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
{
@@ -2006,3 +1942,82 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
quirk_msi_intx_disable_bug);
#endif /* CONFIG_PCI_MSI */
+
+static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
+{
+ while (f < end) {
+ if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
+ (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
+ dev_dbg(&dev->dev, "calling %pF\n", f->hook);
+ f->hook(dev);
+ }
+ f++;
+ }
+}
+
+extern struct pci_fixup __start_pci_fixups_early[];
+extern struct pci_fixup __end_pci_fixups_early[];
+extern struct pci_fixup __start_pci_fixups_header[];
+extern struct pci_fixup __end_pci_fixups_header[];
+extern struct pci_fixup __start_pci_fixups_final[];
+extern struct pci_fixup __end_pci_fixups_final[];
+extern struct pci_fixup __start_pci_fixups_enable[];
+extern struct pci_fixup __end_pci_fixups_enable[];
+extern struct pci_fixup __start_pci_fixups_resume[];
+extern struct pci_fixup __end_pci_fixups_resume[];
+extern struct pci_fixup __start_pci_fixups_resume_early[];
+extern struct pci_fixup __end_pci_fixups_resume_early[];
+extern struct pci_fixup __start_pci_fixups_suspend[];
+extern struct pci_fixup __end_pci_fixups_suspend[];
+
+
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
+{
+ struct pci_fixup *start, *end;
+
+ switch(pass) {
+ case pci_fixup_early:
+ start = __start_pci_fixups_early;
+ end = __end_pci_fixups_early;
+ break;
+
+ case pci_fixup_header:
+ start = __start_pci_fixups_header;
+ end = __end_pci_fixups_header;
+ break;
+
+ case pci_fixup_final:
+ start = __start_pci_fixups_final;
+ end = __end_pci_fixups_final;
+ break;
+
+ case pci_fixup_enable:
+ start = __start_pci_fixups_enable;
+ end = __end_pci_fixups_enable;
+ break;
+
+ case pci_fixup_resume:
+ start = __start_pci_fixups_resume;
+ end = __end_pci_fixups_resume;
+ break;
+
+ case pci_fixup_resume_early:
+ start = __start_pci_fixups_resume_early;
+ end = __end_pci_fixups_resume_early;
+ break;
+
+ case pci_fixup_suspend:
+ start = __start_pci_fixups_suspend;
+ end = __end_pci_fixups_suspend;
+ break;
+
+ default:
+ /* stupid compiler warning, you would think with an enum... */
+ return;
+ }
+ pci_do_fixups(dev, start, end);
+}
+#else
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
+#endif
+EXPORT_SYMBOL(pci_fixup_device);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index bdc2a44d68e..042e0892442 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -73,6 +73,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
up_write(&pci_bus_sem);
pci_remove_legacy_files(pci_bus);
device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
+ device_remove_file(&pci_bus->dev, &dev_attr_cpulistaffinity);
device_unregister(&pci_bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
@@ -114,13 +115,9 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
{
struct list_head *l, *n;
- if (dev->subordinate) {
- list_for_each_safe(l, n, &dev->subordinate->devices) {
- struct pci_dev *dev = pci_dev_b(l);
-
- pci_remove_bus_device(dev);
- }
- }
+ if (dev->subordinate)
+ list_for_each_safe(l, n, &dev->subordinate->devices)
+ pci_remove_bus_device(pci_dev_b(l));
}
static void pci_stop_bus_devices(struct pci_bus *bus)
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index bd5c0e03139..1f5f6143f35 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -21,7 +21,7 @@
* between the ROM and other resources, so enabling it may disable access
* to MMIO registers or other card memory.
*/
-static int pci_enable_rom(struct pci_dev *pdev)
+int pci_enable_rom(struct pci_dev *pdev)
{
struct resource *res = pdev->resource + PCI_ROM_RESOURCE;
struct pci_bus_region region;
@@ -45,7 +45,7 @@ static int pci_enable_rom(struct pci_dev *pdev)
* Disable ROM decoding on a PCI device by turning off the last bit in the
* ROM BAR.
*/
-static void pci_disable_rom(struct pci_dev *pdev)
+void pci_disable_rom(struct pci_dev *pdev)
{
u32 rom_addr;
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
@@ -260,3 +260,5 @@ void pci_cleanup_rom(struct pci_dev *pdev)
EXPORT_SYMBOL(pci_map_rom);
EXPORT_SYMBOL(pci_unmap_rom);
+EXPORT_SYMBOL_GPL(pci_enable_rom);
+EXPORT_SYMBOL_GPL(pci_disable_rom);
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 4edfc4731bd..5af8bd53814 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
{
struct pci_dev *pdev;
+ pci_dev_get(from);
pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
pci_dev_put(pdev);
return pdev;
@@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
struct pci_dev *pdev = NULL;
WARN_ON(in_interrupt());
- if (from) {
- /* FIXME
- * take the cast off, when bus_find_device is made const.
- */
- dev_start = (struct device *)&from->dev;
- }
+ if (from)
+ dev_start = &from->dev;
dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
match_pci_dev_by_id);
if (dev)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index d5e2106760f..ea979f2bc6d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -299,7 +299,7 @@ static void pbus_size_io(struct pci_bus *bus)
if (r->parent || !(r->flags & IORESOURCE_IO))
continue;
- r_size = r->end - r->start + 1;
+ r_size = resource_size(r);
if (r_size < 0x400)
/* Might be re-aligned for ISA */
@@ -350,16 +350,13 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
if (r->parent || (r->flags & mask) != type)
continue;
- r_size = r->end - r->start + 1;
+ r_size = resource_size(r);
/* For bridges size != alignment */
align = resource_alignment(r);
order = __ffs(align) - 20;
if (order > 11) {
dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
- "%#016llx-%#016llx\n", i,
- (unsigned long long)align,
- (unsigned long long)r->start,
- (unsigned long long)r->end);
+ "%pR\n", i, (unsigned long long)align, r);
r->flags = 0;
continue;
}
@@ -539,11 +536,9 @@ static void pci_bus_dump_res(struct pci_bus *bus)
if (!res)
continue;
- printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n",
- bus->number, i,
- (res->flags & IORESOURCE_IO) ? "io port" : "mmio",
- (unsigned long long) res->start,
- (unsigned long long) res->end);
+ printk(KERN_INFO "bus: %02x index %x %s: %pR\n",
+ bus->number, i,
+ (res->flags & IORESOURCE_IO) ? "io port" : "mmio", res);
}
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 1a5fc83c71b..2dbd96cce2d 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -49,10 +49,8 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
pcibios_resource_to_bus(dev, &region, res);
- dev_dbg(&dev->dev, "BAR %d: got res [%#llx-%#llx] bus [%#llx-%#llx] "
- "flags %#lx\n", resno,
- (unsigned long long)res->start,
- (unsigned long long)res->end,
+ dev_dbg(&dev->dev, "BAR %d: got res %pR bus [%#llx-%#llx] "
+ "flags %#lx\n", resno, res,
(unsigned long long)region.start,
(unsigned long long)region.end,
(unsigned long)res->flags);
@@ -114,13 +112,11 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
err = insert_resource(root, res);
if (err) {
- dev_err(&dev->dev, "BAR %d: %s of %s [%#llx-%#llx]\n",
+ dev_err(&dev->dev, "BAR %d: %s of %s %pR\n",
resource,
root ? "address space collision on" :
"no parent found for",
- dtype,
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dtype, res);
}
return err;
@@ -133,15 +129,14 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
resource_size_t size, min, align;
int ret;
- size = res->end - res->start + 1;
+ size = resource_size(res);
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
align = resource_alignment(res);
if (!align) {
dev_err(&dev->dev, "BAR %d: can't allocate resource (bogus "
- "alignment) [%#llx-%#llx] flags %#lx\n",
- resno, (unsigned long long)res->start,
- (unsigned long long)res->end, res->flags);
+ "alignment) %pR flags %#lx\n",
+ resno, res, res->flags);
return -EINVAL;
}
@@ -162,11 +157,8 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
}
if (ret) {
- dev_err(&dev->dev, "BAR %d: can't allocate %s resource "
- "[%#llx-%#llx]\n", resno,
- res->flags & IORESOURCE_IO ? "I/O" : "mem",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+ resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
} else {
res->flags &= ~IORESOURCE_STARTALIGN;
if (resno < PCI_BRIDGE_RESOURCES)
@@ -202,11 +194,8 @@ int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
}
if (ret) {
- dev_err(&dev->dev, "BAR %d: can't allocate %s resource "
- "[%#llx-%#llx\n]", resno,
- res->flags & IORESOURCE_IO ? "I/O" : "mem",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+ resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
} else if (resno < PCI_BRIDGE_RESOURCES) {
pci_update_resource(dev, res, resno);
}
@@ -237,9 +226,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
r_align = resource_alignment(r);
if (!r_align) {
dev_warn(&dev->dev, "BAR %d: bogus alignment "
- "[%#llx-%#llx] flags %#lx\n",
- i, (unsigned long long)r->start,
- (unsigned long long)r->end, r->flags);
+ "%pR flags %#lx\n",
+ i, r, r->flags);
continue;
}
for (list = head; ; list = list->next) {
@@ -287,9 +275,7 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
if (!r->parent) {
dev_err(&dev->dev, "device not available because of "
- "BAR %d [%#llx-%#llx] collisions\n", i,
- (unsigned long long) r->start,
- (unsigned long long) r->end);
+ "BAR %d %pR collisions\n", i, r);
return -EINVAL;
}
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 7e5b85cbd94..4dd1c3e157a 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -49,11 +49,16 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf)
static void pci_slot_release(struct kobject *kobj)
{
+ struct pci_dev *dev;
struct pci_slot *slot = to_pci_slot(kobj);
pr_debug("%s: releasing pci_slot on %x:%d\n", __func__,
slot->bus->number, slot->number);
+ list_for_each_entry(dev, &slot->bus->devices, bus_list)
+ if (PCI_SLOT(dev->devfn) == slot->number)
+ dev->slot = NULL;
+
list_del(&slot->list);
kfree(slot);
@@ -73,18 +78,100 @@ static struct kobj_type pci_slot_ktype = {
.default_attrs = pci_slot_default_attrs,
};
+static char *make_slot_name(const char *name)
+{
+ char *new_name;
+ int len, max, dup;
+
+ new_name = kstrdup(name, GFP_KERNEL);
+ if (!new_name)
+ return NULL;
+
+ /*
+ * Make sure we hit the realloc case the first time through the
+ * loop. 'len' will be strlen(name) + 3 at that point which is
+ * enough space for "name-X" and the trailing NUL.
+ */
+ len = strlen(name) + 2;
+ max = 1;
+ dup = 1;
+
+ for (;;) {
+ struct kobject *dup_slot;
+ dup_slot = kset_find_obj(pci_slots_kset, new_name);
+ if (!dup_slot)
+ break;
+ kobject_put(dup_slot);
+ if (dup == max) {
+ len++;
+ max *= 10;
+ kfree(new_name);
+ new_name = kmalloc(len, GFP_KERNEL);
+ if (!new_name)
+ break;
+ }
+ sprintf(new_name, "%s-%d", name, dup++);
+ }
+
+ return new_name;
+}
+
+static int rename_slot(struct pci_slot *slot, const char *name)
+{
+ int result = 0;
+ char *slot_name;
+
+ if (strcmp(pci_slot_name(slot), name) == 0)
+ return result;
+
+ slot_name = make_slot_name(name);
+ if (!slot_name)
+ return -ENOMEM;
+
+ result = kobject_rename(&slot->kobj, slot_name);
+ kfree(slot_name);
+
+ return result;
+}
+
+static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
+{
+ struct pci_slot *slot;
+ /*
+ * We already hold pci_bus_sem so don't worry
+ */
+ list_for_each_entry(slot, &parent->slots, list)
+ if (slot->number == slot_nr) {
+ kobject_get(&slot->kobj);
+ return slot;
+ }
+
+ return NULL;
+}
+
/**
* pci_create_slot - create or increment refcount for physical PCI slot
* @parent: struct pci_bus of parent bridge
* @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder
* @name: user visible string presented in /sys/bus/pci/slots/<name>
+ * @hotplug: set if caller is hotplug driver, NULL otherwise
*
* PCI slots have first class attributes such as address, speed, width,
* and a &struct pci_slot is used to manage them. This interface will
* either return a new &struct pci_slot to the caller, or if the pci_slot
* already exists, its refcount will be incremented.
*
- * Slots are uniquely identified by a @pci_bus, @slot_nr, @name tuple.
+ * Slots are uniquely identified by a @pci_bus, @slot_nr tuple.
+ *
+ * There are known platforms with broken firmware that assign the same
+ * name to multiple slots. Workaround these broken platforms by renaming
+ * the slots on behalf of the caller. If firmware assigns name N to
+ * multiple slots:
+ *
+ * The first slot is assigned N
+ * The second slot is assigned N-1
+ * The third slot is assigned N-2
+ * etc.
*
* Placeholder slots:
* In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify
@@ -93,71 +180,82 @@ static struct kobj_type pci_slot_ktype = {
* the slot. In this scenario, the caller may pass -1 for @slot_nr.
*
* The following semantics are imposed when the caller passes @slot_nr ==
- * -1. First, the check for existing %struct pci_slot is skipped, as the
- * caller may know about several unpopulated slots on a given %struct
- * pci_bus, and each slot would have a @slot_nr of -1. Uniqueness for
- * these slots is then determined by the @name parameter. We expect
- * kobject_init_and_add() to warn us if the caller attempts to create
- * multiple slots with the same name. The other change in semantics is
+ * -1. First, we no longer check for an existing %struct pci_slot, as there
+ * may be many slots with @slot_nr of -1. The other change in semantics is
* user-visible, which is the 'address' parameter presented in sysfs will
* consist solely of a dddd:bb tuple, where dddd is the PCI domain of the
* %struct pci_bus and bb is the bus number. In other words, the devfn of
* the 'placeholder' slot will not be displayed.
*/
-
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
- const char *name)
+ const char *name,
+ struct hotplug_slot *hotplug)
{
+ struct pci_dev *dev;
struct pci_slot *slot;
- int err;
+ int err = 0;
+ char *slot_name = NULL;
down_write(&pci_bus_sem);
if (slot_nr == -1)
goto placeholder;
- /* If we've already created this slot, bump refcount and return. */
- list_for_each_entry(slot, &parent->slots, list) {
- if (slot->number == slot_nr) {
- kobject_get(&slot->kobj);
- pr_debug("%s: inc refcount to %d on %04x:%02x:%02x\n",
- __func__,
- atomic_read(&slot->kobj.kref.refcount),
- pci_domain_nr(parent), parent->number,
- slot_nr);
- goto out;
+ /*
+ * Hotplug drivers are allowed to rename an existing slot,
+ * but only if not already claimed.
+ */
+ slot = get_slot(parent, slot_nr);
+ if (slot) {
+ if (hotplug) {
+ if ((err = slot->hotplug ? -EBUSY : 0)
+ || (err = rename_slot(slot, name))) {
+ kobject_put(&slot->kobj);
+ slot = NULL;
+ goto err;
+ }
}
+ goto out;
}
placeholder:
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot) {
- slot = ERR_PTR(-ENOMEM);
- goto out;
+ err = -ENOMEM;
+ goto err;
}
slot->bus = parent;
slot->number = slot_nr;
slot->kobj.kset = pci_slots_kset;
- err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
- "%s", name);
- if (err) {
- printk(KERN_ERR "Unable to register kobject %s\n", name);
+
+ slot_name = make_slot_name(name);
+ if (!slot_name) {
+ err = -ENOMEM;
goto err;
}
+ err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
+ "%s", slot_name);
+ if (err)
+ goto err;
+
INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots);
+ list_for_each_entry(dev, &parent->devices, bus_list)
+ if (PCI_SLOT(dev->devfn) == slot_nr)
+ dev->slot = slot;
+
/* Don't care if debug printk has a -1 for slot_nr */
pr_debug("%s: created pci_slot on %04x:%02x:%02x\n",
__func__, pci_domain_nr(parent), parent->number, slot_nr);
- out:
+out:
up_write(&pci_bus_sem);
return slot;
- err:
+err:
kfree(slot);
slot = ERR_PTR(err);
goto out;
@@ -165,7 +263,7 @@ placeholder:
EXPORT_SYMBOL_GPL(pci_create_slot);
/**
- * pci_update_slot_number - update %struct pci_slot -> number
+ * pci_renumber_slot - update %struct pci_slot -> number
* @slot - %struct pci_slot to update
* @slot_nr - new number for slot
*
@@ -173,27 +271,22 @@ EXPORT_SYMBOL_GPL(pci_create_slot);
* created a placeholder slot in pci_create_slot() by passing a -1 as
* slot_nr, to update their %struct pci_slot with the correct @slot_nr.
*/
-
-void pci_update_slot_number(struct pci_slot *slot, int slot_nr)
+void pci_renumber_slot(struct pci_slot *slot, int slot_nr)
{
- int name_count = 0;
struct pci_slot *tmp;
down_write(&pci_bus_sem);
list_for_each_entry(tmp, &slot->bus->slots, list) {
WARN_ON(tmp->number == slot_nr);
- if (!strcmp(kobject_name(&tmp->kobj), kobject_name(&slot->kobj)))
- name_count++;
+ goto out;
}
- if (name_count > 1)
- printk(KERN_WARNING "pci_update_slot_number found %d slots with the same name: %s\n", name_count, kobject_name(&slot->kobj));
-
slot->number = slot_nr;
+out:
up_write(&pci_bus_sem);
}
-EXPORT_SYMBOL_GPL(pci_update_slot_number);
+EXPORT_SYMBOL_GPL(pci_renumber_slot);
/**
* pci_destroy_slot - decrement refcount for physical PCI slot
@@ -203,7 +296,6 @@ EXPORT_SYMBOL_GPL(pci_update_slot_number);
* just call kobject_put on its kobj and let our release methods do the
* rest.
*/
-
void pci_destroy_slot(struct pci_slot *slot)
{
pr_debug("%s: dec refcount to %d on %04x:%02x:%02x\n", __func__,
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index b46c60b7270..23e492bf75c 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -70,7 +70,7 @@ pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o
pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o
-pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps.o
+pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o
pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index a0ffb8ebfe0..9e1140f085f 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -273,7 +273,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
goto fail0d;
cf->socket.pci_irq = board->irq_pin;
} else
- cf->socket.pci_irq = NR_IRQS + 1;
+ cf->socket.pci_irq = nr_irqs + 1;
/* pcmcia layer only remaps "real" memory not iospace */
cf->socket.io_offset = (unsigned long)
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 117dc12ab43..9ef69cdb318 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -233,15 +233,18 @@ static struct hw_interrupt_type hd64465_ss_irq_type = {
*/
static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
{
+ struct irq_desc *desc;
+
DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq);
if (irq >= HS_NUM_MAPPED_IRQS)
return;
+ desc = irq_to_desc(irq);
hs_mapped_irq[irq].sock = sp;
/* insert ourselves as the irq controller */
- hs_mapped_irq[irq].old_handler = irq_desc[irq].chip;
- irq_desc[irq].chip = &hd64465_ss_irq_type;
+ hs_mapped_irq[irq].old_handler = desc->chip;
+ desc->chip = &hd64465_ss_irq_type;
}
@@ -250,13 +253,16 @@ static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
*/
static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
{
+ struct irq_desc *desc;
+
DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq);
if (irq >= HS_NUM_MAPPED_IRQS)
return;
+ desc = irq_to_desc(irq);
/* restore the original irq controller */
- irq_desc[irq].chip = hs_mapped_irq[irq].old_handler;
+ desc->chip = hs_mapped_irq[irq].old_handler;
}
/*============================================================*/
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index eee2f1cb213..b2c41241905 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -639,7 +639,7 @@ static int __devinit vrc4171_card_setup(char *options)
int irq;
options += 4;
irq = simple_strtoul(options, &options, 0);
- if (irq >= 0 && irq < NR_IRQS)
+ if (irq >= 0 && irq < nr_irqs)
vrc4171_irq = irq;
if (*options != ',')
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 821933f9aa5..2a37b3fedb8 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -20,13 +20,21 @@ menuconfig PNP
If unsure, say Y.
-if PNP
-
-config PNP_DEBUG
- bool "PnP Debug Messages"
+config PNP_DEBUG_MESSAGES
+ default y
+ bool "PNP debugging messages"
+ depends on PNP
help
- Say Y if you want the Plug and Play Layer to print debug messages.
- This is useful if you are developing a PnP driver or troubleshooting.
+ Say Y here if you want the PNP layer to be able to produce debugging
+ messages if needed. The messages can be enabled at boot-time with
+ the pnp.debug kernel parameter.
+
+ This option allows you to save a bit of space if you do not want
+ the messages to even be built into the kernel.
+
+ If you have any doubts about this, say Y here.
+
+if PNP
comment "Protocols"
diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile
index e83f34f1b5b..8de3775ec24 100644
--- a/drivers/pnp/Makefile
+++ b/drivers/pnp/Makefile
@@ -10,7 +10,3 @@ obj-$(CONFIG_ISAPNP) += isapnp/
# pnp_system_init goes after pnpacpi/pnpbios init
obj-y += system.o
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 3b8b9d3cb03..0b8d14050ef 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -166,3 +166,13 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
resource_size_t start,
resource_size_t end, int flags);
+
+extern int pnp_debug;
+
+#if defined(CONFIG_PNP_DEBUG_MESSAGES)
+#define pnp_dbg(dev, format, arg...) \
+ ({ if (pnp_debug) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; })
+#else
+#define pnp_dbg(dev, format, arg...) \
+ ({ if (0) dev_printk(KERN_DEBUG, dev, format, ## arg); 0; })
+#endif
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 817fe626e15..16c01c6fa7c 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -177,6 +177,9 @@ int __pnp_add_device(struct pnp_dev *dev)
int pnp_add_device(struct pnp_dev *dev)
{
int ret;
+ char buf[128];
+ int len = 0;
+ struct pnp_id *id;
if (dev->card)
return -EINVAL;
@@ -185,17 +188,12 @@ int pnp_add_device(struct pnp_dev *dev)
if (ret)
return ret;
-#ifdef CONFIG_PNP_DEBUG
- {
- struct pnp_id *id;
+ buf[0] = '\0';
+ for (id = dev->id; id; id = id->next)
+ len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
- dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs",
- dev->protocol->name);
- for (id = dev->id; id; id = id->next)
- printk(" %s", id->id);
- printk(" (%s)\n", dev->active ? "active" : "disabled");
- }
-#endif
+ pnp_dbg(&dev->dev, "%s device, IDs%s (%s)\n",
+ dev->protocol->name, buf, dev->active ? "active" : "disabled");
return 0;
}
@@ -214,3 +212,14 @@ static int __init pnp_init(void)
}
subsys_initcall(pnp_init);
+
+int pnp_debug;
+
+#if defined(CONFIG_PNP_DEBUG_MESSAGES)
+static int __init pnp_debug_setup(char *__unused)
+{
+ pnp_debug = 1;
+ return 1;
+}
+__setup("pnp.debug", pnp_debug_setup);
+#endif
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index e3f7e89c4df..527ee764c93 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -114,7 +114,6 @@ static int pnp_device_probe(struct device *dev)
} else
goto fail;
- dev_dbg(dev, "driver attached\n");
return error;
fail:
@@ -211,8 +210,6 @@ struct bus_type pnp_bus_type = {
int pnp_register_driver(struct pnp_driver *drv)
{
- pnp_dbg("the driver '%s' has been registered", drv->name);
-
drv->driver.name = drv->name;
drv->driver.bus = &pnp_bus_type;
@@ -222,7 +219,6 @@ int pnp_register_driver(struct pnp_driver *drv)
void pnp_unregister_driver(struct pnp_driver *drv)
{
driver_unregister(&drv->driver);
- pnp_dbg("the driver '%s' has been unregistered", drv->name);
}
/**
diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
index 3e38f06f8d7..cac18bbfb81 100644
--- a/drivers/pnp/isapnp/Makefile
+++ b/drivers/pnp/isapnp/Makefile
@@ -5,7 +5,3 @@
isapnp-proc-$(CONFIG_PROC_FS) = proc.o
obj-y := core.o compat.o $(isapnp-proc-y)
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 46455fbab6d..e851160e14f 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -901,7 +901,7 @@ static int isapnp_get_resources(struct pnp_dev *dev)
{
int i, ret;
- dev_dbg(&dev->dev, "get resources\n");
+ pnp_dbg(&dev->dev, "get resources\n");
pnp_init_resources(dev);
isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
@@ -939,13 +939,13 @@ static int isapnp_set_resources(struct pnp_dev *dev)
struct resource *res;
int tmp;
- dev_dbg(&dev->dev, "set resources\n");
+ pnp_dbg(&dev->dev, "set resources\n");
isapnp_cfg_begin(dev->card->number, dev->number);
dev->active = 1;
for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
if (pnp_resource_enabled(res)) {
- dev_dbg(&dev->dev, " set io %d to %#llx\n",
+ pnp_dbg(&dev->dev, " set io %d to %#llx\n",
tmp, (unsigned long long) res->start);
isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
res->start);
@@ -957,14 +957,14 @@ static int isapnp_set_resources(struct pnp_dev *dev)
int irq = res->start;
if (irq == 2)
irq = 9;
- dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq);
+ pnp_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq);
isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
}
}
for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
if (pnp_resource_enabled(res)) {
- dev_dbg(&dev->dev, " set dma %d to %lld\n",
+ pnp_dbg(&dev->dev, " set dma %d to %lld\n",
tmp, (unsigned long long) res->start);
isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
}
@@ -972,7 +972,7 @@ static int isapnp_set_resources(struct pnp_dev *dev)
for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
if (pnp_resource_enabled(res)) {
- dev_dbg(&dev->dev, " set mem %d to %#llx\n",
+ pnp_dbg(&dev->dev, " set mem %d to %#llx\n",
tmp, (unsigned long long) res->start);
isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
(res->start >> 8) & 0xffff);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index b526eaad3f6..00fd3577b98 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -25,7 +25,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_IO, idx);
if (res) {
- dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
+ pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
"flags %#lx\n", idx, (unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
return 0;
@@ -38,7 +38,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
if (!rule->size) {
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " io %d disabled\n", idx);
+ pnp_dbg(&dev->dev, " io %d disabled\n", idx);
goto __add;
}
@@ -49,7 +49,7 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
res->start += rule->align;
res->end = res->start + rule->size - 1;
if (res->start > rule->max || !rule->align) {
- dev_dbg(&dev->dev, " couldn't assign io %d "
+ pnp_dbg(&dev->dev, " couldn't assign io %d "
"(min %#llx max %#llx)\n", idx,
(unsigned long long) rule->min,
(unsigned long long) rule->max);
@@ -68,7 +68,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
if (res) {
- dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
+ pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
"flags %#lx\n", idx, (unsigned long long) res->start,
(unsigned long long) res->end, res->flags);
return 0;
@@ -90,7 +90,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
if (!rule->size) {
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " mem %d disabled\n", idx);
+ pnp_dbg(&dev->dev, " mem %d disabled\n", idx);
goto __add;
}
@@ -101,7 +101,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
res->start += rule->align;
res->end = res->start + rule->size - 1;
if (res->start > rule->max || !rule->align) {
- dev_dbg(&dev->dev, " couldn't assign mem %d "
+ pnp_dbg(&dev->dev, " couldn't assign mem %d "
"(min %#llx max %#llx)\n", idx,
(unsigned long long) rule->min,
(unsigned long long) rule->max);
@@ -126,7 +126,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
if (res) {
- dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
+ pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
idx, (int) res->start, res->flags);
return 0;
}
@@ -138,7 +138,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) {
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " irq %d disabled\n", idx);
+ pnp_dbg(&dev->dev, " irq %d disabled\n", idx);
goto __add;
}
@@ -160,11 +160,11 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
res->start = -1;
res->end = -1;
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
+ pnp_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
goto __add;
}
- dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
+ pnp_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
return -EBUSY;
__add:
@@ -184,7 +184,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
if (res) {
- dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
+ pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
idx, (int) res->start, res->flags);
return 0;
}
@@ -205,7 +205,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
res->start = res->end = MAX_DMA_CHANNELS;
#endif
res->flags |= IORESOURCE_DISABLED;
- dev_dbg(&dev->dev, " disable dma %d\n", idx);
+ pnp_dbg(&dev->dev, " disable dma %d\n", idx);
__add:
pnp_add_dma_resource(dev, res->start, res->flags);
@@ -238,7 +238,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set)
int nport = 0, nmem = 0, nirq = 0, ndma = 0;
int ret = 0;
- dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
+ pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
mutex_lock(&pnp_res_mutex);
pnp_clean_resource_table(dev);
@@ -270,7 +270,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set)
mutex_unlock(&pnp_res_mutex);
if (ret < 0) {
- dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
+ pnp_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
pnp_clean_resource_table(dev);
} else
dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded");
@@ -286,7 +286,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int i, ret;
if (!pnp_can_configure(dev)) {
- dev_dbg(&dev->dev, "configuration not supported\n");
+ pnp_dbg(&dev->dev, "configuration not supported\n");
return -ENODEV;
}
@@ -313,7 +313,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int pnp_start_dev(struct pnp_dev *dev)
{
if (!pnp_can_write(dev)) {
- dev_dbg(&dev->dev, "activation not supported\n");
+ pnp_dbg(&dev->dev, "activation not supported\n");
return -EINVAL;
}
@@ -336,7 +336,7 @@ int pnp_start_dev(struct pnp_dev *dev)
int pnp_stop_dev(struct pnp_dev *dev)
{
if (!pnp_can_disable(dev)) {
- dev_dbg(&dev->dev, "disabling not supported\n");
+ pnp_dbg(&dev->dev, "disabling not supported\n");
return -EINVAL;
}
if (dev->protocol->disable(dev) < 0) {
diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile
index 2d7a1e6908b..905326fcca8 100644
--- a/drivers/pnp/pnpacpi/Makefile
+++ b/drivers/pnp/pnpacpi/Makefile
@@ -3,7 +3,3 @@
#
obj-y := core.o rsparser.o
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 53561d72b4e..383e47c392a 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -75,7 +75,7 @@ static int __init ispnpidacpi(char *id)
static int pnpacpi_get_resources(struct pnp_dev *dev)
{
- dev_dbg(&dev->dev, "get resources\n");
+ pnp_dbg(&dev->dev, "get resources\n");
return pnpacpi_parse_allocated_resource(dev);
}
@@ -86,7 +86,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
int ret;
acpi_status status;
- dev_dbg(&dev->dev, "set resources\n");
+ pnp_dbg(&dev->dev, "set resources\n");
ret = pnpacpi_build_resource_template(dev, &buffer);
if (ret)
return ret;
@@ -148,9 +148,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
acpi_status status;
struct pnp_dev *dev;
+ /*
+ * If a PnPacpi device is not present , the device
+ * driver should not be loaded.
+ */
status = acpi_get_handle(device->handle, "_CRS", &temp);
if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
- is_exclusive_device(device))
+ is_exclusive_device(device) || (!device->status.present))
return 0;
dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
@@ -255,14 +259,14 @@ int pnpacpi_disabled __initdata;
static int __init pnpacpi_init(void)
{
if (acpi_disabled || pnpacpi_disabled) {
- pnp_info("PnP ACPI: disabled");
+ printk(KERN_INFO "pnp: PnP ACPI: disabled\n");
return 0;
}
- pnp_info("PnP ACPI init");
+ printk(KERN_INFO "pnp: PnP ACPI init\n");
pnp_register_protocol(&pnpacpi_protocol);
register_acpi_bus_type(&acpi_pnp_bus);
acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
- pnp_info("PnP ACPI: found %d devices", num);
+ printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num);
unregister_acpi_bus_type(&acpi_pnp_bus);
pnp_platform_devices = 1;
return 0;
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 95015cbfd33..adf17856bac 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -132,7 +132,8 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
pnp_add_irq_resource(dev, irq, flags);
}
-static int dma_flags(int type, int bus_master, int transfer)
+static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
+ int transfer)
{
int flags = 0;
@@ -154,7 +155,7 @@ static int dma_flags(int type, int bus_master, int transfer)
default:
/* Set a default value ? */
flags |= IORESOURCE_DMA_COMPATIBLE;
- pnp_err("Invalid DMA type");
+ dev_err(&dev->dev, "invalid DMA type %d\n", type);
}
switch (transfer) {
case ACPI_TRANSFER_8:
@@ -169,7 +170,7 @@ static int dma_flags(int type, int bus_master, int transfer)
default:
/* Set a default value ? */
flags |= IORESOURCE_DMA_8AND16BIT;
- pnp_err("Invalid DMA transfer type");
+ dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);
}
return flags;
@@ -336,7 +337,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_DMA:
dma = &res->data.dma;
if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
- flags = dma_flags(dma->type, dma->bus_master,
+ flags = dma_flags(dev, dma->type, dma->bus_master,
dma->transfer);
else
flags = IORESOURCE_DISABLED;
@@ -449,7 +450,7 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
acpi_handle handle = dev->data;
acpi_status status;
- dev_dbg(&dev->dev, "parse allocated resources\n");
+ pnp_dbg(&dev->dev, "parse allocated resources\n");
pnp_init_resources(dev);
@@ -477,7 +478,7 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
for (i = 0; i < p->channel_count; i++)
map |= 1 << p->channels[i];
- flags = dma_flags(p->type, p->bus_master, p->transfer);
+ flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
pnp_register_dma_resource(dev, option_flags, map, flags);
}
@@ -608,8 +609,8 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
unsigned char flags = 0;
status = acpi_resource_to_address64(r, p);
- if (!ACPI_SUCCESS(status)) {
- pnp_warn("PnPACPI: failed to convert resource type %d",
+ if (ACPI_FAILURE(status)) {
+ dev_warn(&dev->dev, "can't convert resource type %d\n",
r->type);
return;
}
@@ -735,7 +736,7 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
acpi_status status;
struct acpipnp_parse_option_s parse_data;
- dev_dbg(&dev->dev, "parse resource options\n");
+ pnp_dbg(&dev->dev, "parse resource options\n");
parse_data.dev = dev;
parse_data.option_flags = 0;
@@ -843,7 +844,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
if (!pnp_resource_enabled(p)) {
irq->interrupt_count = 0;
- dev_dbg(&dev->dev, " encode irq (%s)\n",
+ pnp_dbg(&dev->dev, " encode irq (%s)\n",
p ? "disabled" : "missing");
return;
}
@@ -855,7 +856,7 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
irq->interrupt_count = 1;
irq->interrupts[0] = p->start;
- dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",
+ pnp_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",
(int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
@@ -872,7 +873,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
if (!pnp_resource_enabled(p)) {
extended_irq->interrupt_count = 0;
- dev_dbg(&dev->dev, " encode extended irq (%s)\n",
+ pnp_dbg(&dev->dev, " encode extended irq (%s)\n",
p ? "disabled" : "missing");
return;
}
@@ -885,7 +886,7 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
extended_irq->interrupt_count = 1;
extended_irq->interrupts[0] = p->start;
- dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
+ pnp_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
polarity == ACPI_ACTIVE_LOW ? "low" : "high",
extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
@@ -899,7 +900,7 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
if (!pnp_resource_enabled(p)) {
dma->channel_count = 0;
- dev_dbg(&dev->dev, " encode dma (%s)\n",
+ pnp_dbg(&dev->dev, " encode dma (%s)\n",
p ? "disabled" : "missing");
return;
}
@@ -934,7 +935,7 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
dma->channel_count = 1;
dma->channels[0] = p->start;
- dev_dbg(&dev->dev, " encode dma %d "
+ pnp_dbg(&dev->dev, " encode dma %d "
"type %#x transfer %#x master %d\n",
(int) p->start, dma->type, dma->transfer, dma->bus_master);
}
@@ -958,7 +959,7 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
io->address_length = 0;
}
- dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
+ pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
io->minimum + io->address_length - 1, io->io_decode);
}
@@ -976,7 +977,7 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
fixed_io->address_length = 0;
}
- dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
+ pnp_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
fixed_io->address + fixed_io->address_length - 1);
}
@@ -999,7 +1000,7 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
memory24->address_length = 0;
}
- dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
+ pnp_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
memory24->minimum,
memory24->minimum + memory24->address_length - 1,
memory24->write_protect);
@@ -1023,7 +1024,7 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
memory32->alignment = 0;
}
- dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
+ pnp_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
memory32->minimum,
memory32->minimum + memory32->address_length - 1,
memory32->write_protect);
@@ -1046,7 +1047,7 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
fixed_memory32->address_length = 0;
}
- dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
+ pnp_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
fixed_memory32->address,
fixed_memory32->address + fixed_memory32->address_length - 1,
fixed_memory32->write_protect);
@@ -1060,7 +1061,7 @@ int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
struct acpi_resource *resource = buffer->pointer;
int port = 0, irq = 0, dma = 0, mem = 0;
- dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
+ pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt);
while (i < res_cnt) {
switch (resource->type) {
case ACPI_RESOURCE_TYPE_IRQ:
diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile
index 310e2b3a771..3cd3ed76060 100644
--- a/drivers/pnp/pnpbios/Makefile
+++ b/drivers/pnp/pnpbios/Makefile
@@ -5,7 +5,3 @@
pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o
obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y)
-
-ifeq ($(CONFIG_PNP_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 2bfe13369df..996f6483807 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -211,7 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev)
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- dev_dbg(&dev->dev, "get resources\n");
+ pnp_dbg(&dev->dev, "get resources\n");
node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
@@ -234,7 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev)
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- dev_dbg(&dev->dev, "set resources\n");
+ pnp_dbg(&dev->dev, "set resources\n");
node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index ca567671379..87b4f49a525 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -87,7 +87,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
if (!p)
return NULL;
- dev_dbg(&dev->dev, "parse allocated resources\n");
+ pnp_dbg(&dev->dev, "parse allocated resources\n");
pnp_init_resources(dev);
@@ -324,7 +324,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
if (!p)
return NULL;
- dev_dbg(&dev->dev, "parse resource options\n");
+ pnp_dbg(&dev->dev, "parse resource options\n");
option_flags = 0;
while ((char *)p < (char *)end) {
@@ -519,7 +519,7 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
p[10] = (len >> 8) & 0xff;
p[11] = ((len >> 8) >> 8) & 0xff;
- dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
+ pnp_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
}
static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
@@ -549,7 +549,7 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
p[18] = (len >> 16) & 0xff;
p[19] = (len >> 24) & 0xff;
- dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
+ pnp_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
}
static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
@@ -575,7 +575,7 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
p[10] = (len >> 16) & 0xff;
p[11] = (len >> 24) & 0xff;
- dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
+ pnp_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
base + len - 1);
}
@@ -592,7 +592,7 @@ static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
p[1] = map & 0xff;
p[2] = (map >> 8) & 0xff;
- dev_dbg(&dev->dev, " encode irq mask %#lx\n", map);
+ pnp_dbg(&dev->dev, " encode irq mask %#lx\n", map);
}
static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
@@ -607,7 +607,7 @@ static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
p[1] = map & 0xff;
- dev_dbg(&dev->dev, " encode dma mask %#lx\n", map);
+ pnp_dbg(&dev->dev, " encode dma mask %#lx\n", map);
}
static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
@@ -630,7 +630,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
p[5] = (base >> 8) & 0xff;
p[7] = len & 0xff;
- dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
+ pnp_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
}
static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
@@ -651,7 +651,7 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
p[2] = (base >> 8) & 0xff;
p[3] = len & 0xff;
- dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
+ pnp_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
base + len - 1);
}
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index c144bd57561..8473fe5ed7f 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -337,9 +337,8 @@ void pnp_fixup_device(struct pnp_dev *dev)
for (f = pnp_fixups; *f->id; f++) {
if (!compare_pnp_id(dev->id, f->id))
continue;
-#ifdef DEBUG
- dev_dbg(&dev->dev, "%s: calling %pF\n", f->id, f->quirk_function);
-#endif
+ pnp_dbg(&dev->dev, "%s: calling %pF\n", f->id,
+ f->quirk_function);
f->quirk_function(dev);
}
}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index dbae23acdd5..f604061d2bb 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -294,7 +294,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
u8 progif;
if (pci->irq == irq) {
- dev_dbg(&pnp->dev, "device %s using irq %d\n",
+ pnp_dbg(&pnp->dev, " device %s using irq %d\n",
pci_name(pci), irq);
return 1;
}
@@ -316,7 +316,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
if ((progif & 0x5) != 0x5)
if (pci_get_legacy_ide_irq(pci, 0) == irq ||
pci_get_legacy_ide_irq(pci, 1) == irq) {
- dev_dbg(&pnp->dev, "legacy IDE device %s "
+ pnp_dbg(&pnp->dev, " legacy IDE device %s "
"using irq %d\n", pci_name(pci), irq);
return 1;
}
@@ -517,7 +517,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
res->start = irq;
res->end = irq;
- dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags);
+ pnp_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags);
return pnp_res;
}
@@ -538,7 +538,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
res->start = dma;
res->end = dma;
- dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags);
+ pnp_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags);
return pnp_res;
}
@@ -562,7 +562,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
res->start = start;
res->end = end;
- dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n",
+ pnp_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n",
(unsigned long long) start, (unsigned long long) end, flags);
return pnp_res;
}
@@ -587,7 +587,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
res->start = start;
res->end = end;
- dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n",
+ pnp_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n",
(unsigned long long) start, (unsigned long long) end, flags);
return pnp_res;
}
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index b42df162071..63087d5ce60 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -75,18 +75,17 @@ char *pnp_resource_type_name(struct resource *res)
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
{
-#ifdef DEBUG
char buf[128];
int len;
struct pnp_resource *pnp_res;
struct resource *res;
if (list_empty(&dev->resources)) {
- dev_dbg(&dev->dev, "%s: no current resources\n", desc);
+ pnp_dbg(&dev->dev, "%s: no current resources\n", desc);
return;
}
- dev_dbg(&dev->dev, "%s: current resources:\n", desc);
+ pnp_dbg(&dev->dev, "%s: current resources:\n", desc);
list_for_each_entry(pnp_res, &dev->resources, list) {
res = &pnp_res->res;
len = 0;
@@ -95,7 +94,7 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
pnp_resource_type_name(res));
if (res->flags & IORESOURCE_DISABLED) {
- dev_dbg(&dev->dev, "%sdisabled\n", buf);
+ pnp_dbg(&dev->dev, "%sdisabled\n", buf);
continue;
}
@@ -116,9 +115,8 @@ void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
res->flags);
break;
}
- dev_dbg(&dev->dev, "%s\n", buf);
+ pnp_dbg(&dev->dev, "%s\n", buf);
}
-#endif
}
char *pnp_option_priority_name(struct pnp_option *option)
@@ -136,7 +134,6 @@ char *pnp_option_priority_name(struct pnp_option *option)
void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
{
-#ifdef DEBUG
char buf[128];
int len = 0, i;
struct pnp_port *port;
@@ -208,6 +205,5 @@ void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
"flags %#x", dma->map, dma->flags);
break;
}
- dev_dbg(&dev->dev, "%s\n", buf);
-#endif
+ pnp_dbg(&dev->dev, "%s\n", buf);
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 63bb5791044..8e0c2b47803 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -51,7 +51,7 @@ config BATTERY_OLPC
config BATTERY_TOSA
tristate "Sharp SL-6000 (tosa) battery"
- depends on MACH_TOSA && MFD_TC6393XB
+ depends on MACH_TOSA && MFD_TC6393XB && TOUCHSCREEN_WM97XX
help
Say Y to enable support for the battery on the Sharp Zaurus
SL-6000 (tosa) models.
@@ -62,4 +62,10 @@ config BATTERY_WM97XX
help
Say Y to enable support for battery measured by WM97xx aux port.
+config BATTERY_BQ27x00
+ tristate "BQ27200 battery driver"
+ depends on I2C
+ help
+ Say Y here to enable support for batteries with BQ27200(I2C) chip.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 4e20026cc45..e8f1ecec5d8 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -21,4 +21,5 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
-obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o \ No newline at end of file
+obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
+obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
new file mode 100644
index 00000000000..0c056fcc01c
--- /dev/null
+++ b/drivers/power/bq27x00_battery.c
@@ -0,0 +1,381 @@
+/*
+ * BQ27x00 battery driver
+ *
+ * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/idr.h>
+#include <linux/i2c.h>
+#include <asm/unaligned.h>
+
+#define DRIVER_VERSION "1.0.0"
+
+#define BQ27x00_REG_TEMP 0x06
+#define BQ27x00_REG_VOLT 0x08
+#define BQ27x00_REG_RSOC 0x0B /* Relative State-of-Charge */
+#define BQ27x00_REG_AI 0x14
+#define BQ27x00_REG_FLAGS 0x0A
+
+/* If the system has several batteries we need a different name for each
+ * of them...
+ */
+static DEFINE_IDR(battery_id);
+static DEFINE_MUTEX(battery_mutex);
+
+struct bq27x00_device_info;
+struct bq27x00_access_methods {
+ int (*read)(u8 reg, int *rt_value, int b_single,
+ struct bq27x00_device_info *di);
+};
+
+struct bq27x00_device_info {
+ struct device *dev;
+ int id;
+ int voltage_uV;
+ int current_uA;
+ int temp_C;
+ int charge_rsoc;
+ struct bq27x00_access_methods *bus;
+ struct power_supply bat;
+
+ struct i2c_client *client;
+};
+
+static enum power_supply_property bq27x00_battery_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+/*
+ * Common code for BQ27x00 devices
+ */
+
+static int bq27x00_read(u8 reg, int *rt_value, int b_single,
+ struct bq27x00_device_info *di)
+{
+ int ret;
+
+ ret = di->bus->read(reg, rt_value, b_single, di);
+ *rt_value = be16_to_cpu(*rt_value);
+
+ return ret;
+}
+
+/*
+ * Return the battery temperature in Celcius degrees
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
+{
+ int ret;
+ int temp = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading temperature\n");
+ return ret;
+ }
+
+ return (temp >> 2) - 273;
+}
+
+/*
+ * Return the battery Voltage in milivolts
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_voltage(struct bq27x00_device_info *di)
+{
+ int ret;
+ int volt = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading voltage\n");
+ return ret;
+ }
+
+ return volt;
+}
+
+/*
+ * Return the battery average current
+ * Note that current can be negative signed as well
+ * Or 0 if something fails.
+ */
+static int bq27x00_battery_current(struct bq27x00_device_info *di)
+{
+ int ret;
+ int curr = 0;
+ int flags = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
+ if (ret) {
+ dev_err(di->dev, "error reading current\n");
+ return 0;
+ }
+ ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
+ if (ret < 0) {
+ dev_err(di->dev, "error reading flags\n");
+ return 0;
+ }
+ if ((flags & (1 << 7)) != 0) {
+ dev_dbg(di->dev, "negative current!\n");
+ return -curr;
+ }
+ return curr;
+}
+
+/*
+ * Return the battery Relative State-of-Charge
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
+{
+ int ret;
+ int rsoc = 0;
+
+ ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di);
+ if (ret) {
+ dev_err(di->dev, "error reading relative State-of-Charge\n");
+ return ret;
+ }
+
+ return rsoc >> 8;
+}
+
+#define to_bq27x00_device_info(x) container_of((x), \
+ struct bq27x00_device_info, bat);
+
+static int bq27x00_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = bq27x00_battery_voltage(di);
+ if (psp == POWER_SUPPLY_PROP_PRESENT)
+ val->intval = val->intval <= 0 ? 0 : 1;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = bq27x00_battery_current(di);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = bq27x00_battery_rsoc(di);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = bq27x00_battery_temperature(di);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void bq27x00_powersupply_init(struct bq27x00_device_info *di)
+{
+ di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat.properties = bq27x00_battery_props;
+ di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
+ di->bat.get_property = bq27x00_battery_get_property;
+ di->bat.external_power_changed = NULL;
+}
+
+/*
+ * BQ27200 specific code
+ */
+
+static int bq27200_read(u8 reg, int *rt_value, int b_single,
+ struct bq27x00_device_info *di)
+{
+ struct i2c_client *client = di->client;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+ int err;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg->addr = client->addr;
+ msg->flags = 0;
+ msg->len = 1;
+ msg->buf = data;
+
+ data[0] = reg;
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0) {
+ if (!b_single)
+ msg->len = 2;
+ else
+ msg->len = 1;
+
+ msg->flags = I2C_M_RD;
+ err = i2c_transfer(client->adapter, msg, 1);
+ if (err >= 0) {
+ if (!b_single)
+ *rt_value = get_unaligned_be16(data);
+ else
+ *rt_value = data[0];
+
+ return 0;
+ }
+ }
+ return err;
+}
+
+static int bq27200_battery_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ char *name;
+ struct bq27x00_device_info *di;
+ struct bq27x00_access_methods *bus;
+ int num;
+ int retval = 0;
+
+ /* Get new ID for the new battery device */
+ retval = idr_pre_get(&battery_id, GFP_KERNEL);
+ if (retval == 0)
+ return -ENOMEM;
+ mutex_lock(&battery_mutex);
+ retval = idr_get_new(&battery_id, client, &num);
+ mutex_unlock(&battery_mutex);
+ if (retval < 0)
+ return retval;
+
+ name = kasprintf(GFP_KERNEL, "bq27200-%d", num);
+ if (!name) {
+ dev_err(&client->dev, "failed to allocate device name\n");
+ retval = -ENOMEM;
+ goto batt_failed_1;
+ }
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ dev_err(&client->dev, "failed to allocate device info data\n");
+ retval = -ENOMEM;
+ goto batt_failed_2;
+ }
+ di->id = num;
+
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus) {
+ dev_err(&client->dev, "failed to allocate access method "
+ "data\n");
+ retval = -ENOMEM;
+ goto batt_failed_3;
+ }
+
+ i2c_set_clientdata(client, di);
+ di->dev = &client->dev;
+ di->bat.name = name;
+ bus->read = &bq27200_read;
+ di->bus = bus;
+ di->client = client;
+
+ bq27x00_powersupply_init(di);
+
+ retval = power_supply_register(&client->dev, &di->bat);
+ if (retval) {
+ dev_err(&client->dev, "failed to register battery\n");
+ goto batt_failed_4;
+ }
+
+ dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+ return 0;
+
+batt_failed_4:
+ kfree(bus);
+batt_failed_3:
+ kfree(di);
+batt_failed_2:
+ kfree(name);
+batt_failed_1:
+ mutex_lock(&battery_mutex);
+ idr_remove(&battery_id, num);
+ mutex_unlock(&battery_mutex);
+
+ return retval;
+}
+
+static int bq27200_battery_remove(struct i2c_client *client)
+{
+ struct bq27x00_device_info *di = i2c_get_clientdata(client);
+
+ power_supply_unregister(&di->bat);
+
+ kfree(di->bat.name);
+
+ mutex_lock(&battery_mutex);
+ idr_remove(&battery_id, di->id);
+ mutex_unlock(&battery_mutex);
+
+ kfree(di);
+
+ return 0;
+}
+
+/*
+ * Module stuff
+ */
+
+static const struct i2c_device_id bq27200_id[] = {
+ { "bq27200", 0 },
+ {},
+};
+
+static struct i2c_driver bq27200_battery_driver = {
+ .driver = {
+ .name = "bq27200-battery",
+ },
+ .probe = bq27200_battery_probe,
+ .remove = bq27200_battery_remove,
+ .id_table = bq27200_id,
+};
+
+static int __init bq27x00_battery_init(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&bq27200_battery_driver);
+ if (ret)
+ printk(KERN_ERR "Unable to register BQ27200 driver\n");
+
+ return ret;
+}
+module_init(bq27x00_battery_init);
+
+static void __exit bq27x00_battery_exit(void)
+{
+ i2c_del_driver(&bq27200_battery_driver);
+}
+module_exit(bq27x00_battery_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 0471ec743ab..d30bb766fce 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -334,13 +334,16 @@ static int pda_power_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
+static int ac_wakeup_enabled;
+static int usb_wakeup_enabled;
+
static int pda_power_suspend(struct platform_device *pdev, pm_message_t state)
{
if (device_may_wakeup(&pdev->dev)) {
if (ac_irq)
- enable_irq_wake(ac_irq->start);
+ ac_wakeup_enabled = !enable_irq_wake(ac_irq->start);
if (usb_irq)
- enable_irq_wake(usb_irq->start);
+ usb_wakeup_enabled = !enable_irq_wake(usb_irq->start);
}
return 0;
@@ -349,9 +352,9 @@ static int pda_power_suspend(struct platform_device *pdev, pm_message_t state)
static int pda_power_resume(struct platform_device *pdev)
{
if (device_may_wakeup(&pdev->dev)) {
- if (usb_irq)
+ if (usb_irq && usb_wakeup_enabled)
disable_irq_wake(usb_irq->start);
- if (ac_irq)
+ if (ac_irq && ac_wakeup_enabled)
disable_irq_wake(ac_irq->start);
}
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 3007695f90c..5520040449c 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -87,6 +87,30 @@ int power_supply_am_i_supplied(struct power_supply *psy)
return error;
}
+static int __power_supply_is_system_supplied(struct device *dev, void *data)
+{
+ union power_supply_propval ret = {0,};
+ struct power_supply *psy = dev_get_drvdata(dev);
+
+ if (psy->type != POWER_SUPPLY_TYPE_BATTERY) {
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
+ return 0;
+ if (ret.intval)
+ return ret.intval;
+ }
+ return 0;
+}
+
+int power_supply_is_system_supplied(void)
+{
+ int error;
+
+ error = class_for_each_device(power_supply_class, NULL, NULL,
+ __power_supply_is_system_supplied);
+
+ return error;
+}
+
int power_supply_register(struct device *parent, struct power_supply *psy)
{
int rc = 0;
@@ -148,6 +172,7 @@ static void __exit power_supply_class_exit(void)
EXPORT_SYMBOL_GPL(power_supply_changed);
EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
+EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
EXPORT_SYMBOL_GPL(power_supply_register);
EXPORT_SYMBOL_GPL(power_supply_unregister);
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index fe2aeb11939..23ae8460f5c 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -30,7 +30,7 @@
#define POWER_SUPPLY_ATTR(_name) \
{ \
- .attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+ .attr = { .name = #_name, .mode = 0444 }, \
.show = power_supply_show_property, \
.store = NULL, \
}
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 6f2f90ebb02..06848b254d5 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -915,6 +915,22 @@ int ps3av_video_mute(int mute)
EXPORT_SYMBOL_GPL(ps3av_video_mute);
+/* mute analog output only */
+int ps3av_audio_mute_analog(int mute)
+{
+ int i, res;
+
+ for (i = 0; i < ps3av->av_hw_conf.num_of_avmulti; i++) {
+ res = ps3av_cmd_av_audio_mute(1,
+ &ps3av->av_port[i + ps3av->av_hw_conf.num_of_hdmi],
+ mute);
+ if (res < 0)
+ return -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3av_audio_mute_analog);
+
int ps3av_audio_mute(int mute)
{
return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index 7f880c26122..11eb50318fe 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -660,9 +660,10 @@ u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,
}
/* default cs val */
-static const u8 ps3av_mode_cs_info[] = {
+u8 ps3av_mode_cs_info[] = {
0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
};
+EXPORT_SYMBOL_GPL(ps3av_mode_cs_info);
#define CS_44 0x00
#define CS_48 0x02
@@ -677,7 +678,7 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
u32 ch, u32 fs, u32 word_bits, u32 format,
u32 source)
{
- int spdif_through, spdif_bitstream;
+ int spdif_through;
int i;
if (!(ch | fs | format | word_bits | source)) {
@@ -687,7 +688,6 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
format = PS3AV_CMD_AUDIO_FORMAT_PCM;
source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
}
- spdif_through = spdif_bitstream = 0; /* XXX not supported */
/* audio mode */
memset(audio, 0, sizeof(*audio));
@@ -777,16 +777,17 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
break;
}
+ /* non-audio bit */
+ spdif_through = audio->audio_cs_info[0] & 0x02;
+
/* pass through setting */
if (spdif_through &&
(avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
- avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+ avport == PS3AV_CMD_AVPORT_SPDIF_1 ||
+ avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+ avport == PS3AV_CMD_AVPORT_HDMI_1)) {
audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
- audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
- if (spdif_bitstream) {
- audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
- audio->audio_cs_info[0] |= CS_BIT;
- }
+ audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
}
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index f660ef3e5b2..8abbb2020af 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -171,10 +171,10 @@ config RTC_DRV_MAX6900
will be called rtc-max6900.
config RTC_DRV_RS5C372
- tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A"
+ tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help
If you say yes here you get support for the
- Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips.
+ Ricoh R2025S/D, RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-rs5c372.
@@ -246,6 +246,16 @@ config RTC_DRV_TWL92330
platforms. The support is integrated with the rest of
the Menelaus driver; it's not separate module.
+config RTC_DRV_TWL4030
+ tristate "TI TWL4030/TWL5030/TPS659x0"
+ depends on RTC_CLASS && TWL4030_CORE
+ help
+ If you say yes here you get support for the RTC on the
+ TWL4030 family chips, used mostly with OMAP3 platforms.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-twl4030.
+
config RTC_DRV_S35390A
tristate "Seiko Instruments S-35390A"
select BITREVERSE
@@ -610,6 +620,14 @@ config RTC_DRV_RS5C313
help
If you say yes here you get support for the Ricoh RS5C313 RTC chips.
+config RTC_DRV_PARISC
+ tristate "PA-RISC firmware RTC support"
+ depends on PARISC
+ help
+ Say Y or M here to enable RTC support on PA-RISC systems using
+ firmware calls. If you do not know what you are doing, you should
+ just say Y.
+
config RTC_DRV_PPC
tristate "PowerPC machine dependent RTC support"
depends on PPC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index d05928b3ca9..e9e8474cc8f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_PARISC) += rtc-parisc.o
obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
@@ -62,6 +63,7 @@ obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
+obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 37082616482..b5bf9370691 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -53,21 +53,21 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
} while ((time != at91_sys_read(timereg)) ||
(date != at91_sys_read(calreg)));
- tm->tm_sec = BCD2BIN((time & AT91_RTC_SEC) >> 0);
- tm->tm_min = BCD2BIN((time & AT91_RTC_MIN) >> 8);
- tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16);
+ tm->tm_sec = bcd2bin((time & AT91_RTC_SEC) >> 0);
+ tm->tm_min = bcd2bin((time & AT91_RTC_MIN) >> 8);
+ tm->tm_hour = bcd2bin((time & AT91_RTC_HOUR) >> 16);
/*
* The Calendar Alarm register does not have a field for
* the year - so these will return an invalid value. When an
* alarm is set, at91_alarm_year wille store the current year.
*/
- tm->tm_year = BCD2BIN(date & AT91_RTC_CENT) * 100; /* century */
- tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8); /* year */
+ tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */
+ tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */
- tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
- tm->tm_mon = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1;
- tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24);
+ tm->tm_wday = bcd2bin((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
+ tm->tm_mon = bcd2bin((date & AT91_RTC_MONTH) >> 16) - 1;
+ tm->tm_mday = bcd2bin((date & AT91_RTC_DATE) >> 24);
}
/*
@@ -106,16 +106,16 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
at91_sys_write(AT91_RTC_TIMR,
- BIN2BCD(tm->tm_sec) << 0
- | BIN2BCD(tm->tm_min) << 8
- | BIN2BCD(tm->tm_hour) << 16);
+ bin2bcd(tm->tm_sec) << 0
+ | bin2bcd(tm->tm_min) << 8
+ | bin2bcd(tm->tm_hour) << 16);
at91_sys_write(AT91_RTC_CALR,
- BIN2BCD((tm->tm_year + 1900) / 100) /* century */
- | BIN2BCD(tm->tm_year % 100) << 8 /* year */
- | BIN2BCD(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */
- | BIN2BCD(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
- | BIN2BCD(tm->tm_mday) << 24);
+ bin2bcd((tm->tm_year + 1900) / 100) /* century */
+ | bin2bcd(tm->tm_year % 100) << 8 /* year */
+ | bin2bcd(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */
+ | bin2bcd(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
+ | bin2bcd(tm->tm_mday) << 24);
/* Restart Time/Calendar */
cr = at91_sys_read(AT91_RTC_CR);
@@ -162,13 +162,13 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
at91_sys_write(AT91_RTC_TIMALR,
- BIN2BCD(tm.tm_sec) << 0
- | BIN2BCD(tm.tm_min) << 8
- | BIN2BCD(tm.tm_hour) << 16
+ bin2bcd(tm.tm_sec) << 0
+ | bin2bcd(tm.tm_min) << 8
+ | bin2bcd(tm.tm_hour) << 16
| AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
at91_sys_write(AT91_RTC_CALALR,
- BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
- | BIN2BCD(tm.tm_mday) << 24
+ bin2bcd(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
+ | bin2bcd(tm.tm_mday) << 24
| AT91_RTC_DATEEN | AT91_RTC_MTHEN);
if (alrm->enabled) {
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
index 189a018bdf3..d00a274df8f 100644
--- a/drivers/rtc/rtc-bq4802.c
+++ b/drivers/rtc/rtc-bq4802.c
@@ -71,14 +71,14 @@ static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
spin_unlock_irqrestore(&p->lock, flags);
- BCD_TO_BIN(tm->tm_sec);
- BCD_TO_BIN(tm->tm_min);
- BCD_TO_BIN(tm->tm_hour);
- BCD_TO_BIN(tm->tm_mday);
- BCD_TO_BIN(tm->tm_mon);
- BCD_TO_BIN(tm->tm_year);
- BCD_TO_BIN(tm->tm_wday);
- BCD_TO_BIN(century);
+ tm->tm_sec = bcd2bin(tm->tm_sec);
+ tm->tm_min = bcd2bin(tm->tm_min);
+ tm->tm_hour = bcd2bin(tm->tm_hour);
+ tm->tm_mday = bcd2bin(tm->tm_mday);
+ tm->tm_mon = bcd2bin(tm->tm_mon);
+ tm->tm_year = bcd2bin(tm->tm_year);
+ tm->tm_wday = bcd2bin(tm->tm_wday);
+ century = bcd2bin(century);
tm->tm_year += (century * 100);
tm->tm_year -= 1900;
@@ -106,13 +106,13 @@ static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
min = tm->tm_min;
sec = tm->tm_sec;
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hrs);
- BIN_TO_BCD(day);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(yrs);
- BIN_TO_BCD(century);
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
+ century = bin2bcd(century);
spin_lock_irqsave(&p->lock, flags);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 963ad0b6a4e..5549231179a 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -143,6 +143,43 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler)
/*----------------------------------------------------------------*/
+#ifdef RTC_PORT
+
+/* Most newer x86 systems have two register banks, the first used
+ * for RTC and NVRAM and the second only for NVRAM. Caller must
+ * own rtc_lock ... and we won't worry about access during NMI.
+ */
+#define can_bank2 true
+
+static inline unsigned char cmos_read_bank2(unsigned char addr)
+{
+ outb(addr, RTC_PORT(2));
+ return inb(RTC_PORT(3));
+}
+
+static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
+{
+ outb(addr, RTC_PORT(2));
+ outb(val, RTC_PORT(2));
+}
+
+#else
+
+#define can_bank2 false
+
+static inline unsigned char cmos_read_bank2(unsigned char addr)
+{
+ return 0;
+}
+
+static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
+{
+}
+
+#endif
+
+/*----------------------------------------------------------------*/
+
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
/* REVISIT: if the clock has a "century" register, use
@@ -203,26 +240,26 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
/* REVISIT this assumes PC style usage: always BCD */
if (((unsigned)t->time.tm_sec) < 0x60)
- t->time.tm_sec = BCD2BIN(t->time.tm_sec);
+ t->time.tm_sec = bcd2bin(t->time.tm_sec);
else
t->time.tm_sec = -1;
if (((unsigned)t->time.tm_min) < 0x60)
- t->time.tm_min = BCD2BIN(t->time.tm_min);
+ t->time.tm_min = bcd2bin(t->time.tm_min);
else
t->time.tm_min = -1;
if (((unsigned)t->time.tm_hour) < 0x24)
- t->time.tm_hour = BCD2BIN(t->time.tm_hour);
+ t->time.tm_hour = bcd2bin(t->time.tm_hour);
else
t->time.tm_hour = -1;
if (cmos->day_alrm) {
if (((unsigned)t->time.tm_mday) <= 0x31)
- t->time.tm_mday = BCD2BIN(t->time.tm_mday);
+ t->time.tm_mday = bcd2bin(t->time.tm_mday);
else
t->time.tm_mday = -1;
if (cmos->mon_alrm) {
if (((unsigned)t->time.tm_mon) <= 0x12)
- t->time.tm_mon = BCD2BIN(t->time.tm_mon) - 1;
+ t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1;
else
t->time.tm_mon = -1;
}
@@ -294,19 +331,19 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
/* Writing 0xff means "don't care" or "match all". */
mon = t->time.tm_mon + 1;
- mon = (mon <= 12) ? BIN2BCD(mon) : 0xff;
+ mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
mday = t->time.tm_mday;
- mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+ mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
hrs = t->time.tm_hour;
- hrs = (hrs < 24) ? BIN2BCD(hrs) : 0xff;
+ hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff;
min = t->time.tm_min;
- min = (min < 60) ? BIN2BCD(min) : 0xff;
+ min = (min < 60) ? bin2bcd(min) : 0xff;
sec = t->time.tm_sec;
- sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
+ sec = (sec < 60) ? bin2bcd(sec) : 0xff;
spin_lock_irq(&rtc_lock);
@@ -491,12 +528,21 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
if (unlikely(off >= attr->size))
return 0;
+ if (unlikely(off < 0))
+ return -EINVAL;
if ((off + count) > attr->size)
count = attr->size - off;
+ off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
- for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++)
- *buf++ = CMOS_READ(off);
+ for (retval = 0; count; count--, off++, retval++) {
+ if (off < 128)
+ *buf++ = CMOS_READ(off);
+ else if (can_bank2)
+ *buf++ = cmos_read_bank2(off);
+ else
+ break;
+ }
spin_unlock_irq(&rtc_lock);
return retval;
@@ -512,6 +558,8 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
if (unlikely(off >= attr->size))
return -EFBIG;
+ if (unlikely(off < 0))
+ return -EINVAL;
if ((off + count) > attr->size)
count = attr->size - off;
@@ -520,15 +568,20 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
* here. If userspace is smart enough to know what fields of
* NVRAM to update, updating checksums is also part of its job.
*/
+ off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
- for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) {
+ for (retval = 0; count; count--, off++, retval++) {
/* don't trash RTC registers */
if (off == cmos->day_alrm
|| off == cmos->mon_alrm
|| off == cmos->century)
buf++;
- else
+ else if (off < 128)
CMOS_WRITE(*buf++, off);
+ else if (can_bank2)
+ cmos_write_bank2(*buf++, off);
+ else
+ break;
}
spin_unlock_irq(&rtc_lock);
@@ -539,7 +592,6 @@ static struct bin_attribute nvram = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.read = cmos_nvram_read,
@@ -631,8 +683,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
/* Heuristic to deduce NVRAM size ... do what the legacy NVRAM
* driver did, but don't reject unknown configs. Old hardware
- * won't address 128 bytes, and for now we ignore the way newer
- * chips can address 256 bytes (using two more i/o ports).
+ * won't address 128 bytes. Newer chips have multiple banks,
+ * though they may not be listed in one I/O resource.
*/
#if defined(CONFIG_ATARI)
address_space = 64;
@@ -642,6 +694,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
address_space = 128;
#endif
+ if (can_bank2 && ports->end > (ports->start + 1))
+ address_space = 256;
/* For ACPI systems extension info comes from the FADT. On others,
* board specific setup provides it as appropriate. Systems where
@@ -740,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
goto cleanup2;
}
- pr_info("%s: alarms up to one %s%s%s\n",
+ pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n",
cmos_rtc.rtc->dev.bus_id,
is_valid_irq(rtc_irq)
? (cmos_rtc.mon_alrm
@@ -749,6 +803,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
? "month" : "day"))
: "no",
cmos_rtc.century ? ", y3k" : "",
+ nvram.size,
is_hpet_enabled() ? ", hpet irqs" : "");
return 0;
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
index 0b17770b032..9a234a4ec06 100644
--- a/drivers/rtc/rtc-ds1216.c
+++ b/drivers/rtc/rtc-ds1216.c
@@ -86,19 +86,19 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
ds1216_switch_ds_to_clock(priv->ioaddr);
ds1216_read(priv->ioaddr, (u8 *)&regs);
- tm->tm_sec = BCD2BIN(regs.sec);
- tm->tm_min = BCD2BIN(regs.min);
+ tm->tm_sec = bcd2bin(regs.sec);
+ tm->tm_min = bcd2bin(regs.min);
if (regs.hour & DS1216_HOUR_1224) {
/* AM/PM mode */
- tm->tm_hour = BCD2BIN(regs.hour & 0x1f);
+ tm->tm_hour = bcd2bin(regs.hour & 0x1f);
if (regs.hour & DS1216_HOUR_AMPM)
tm->tm_hour += 12;
} else
- tm->tm_hour = BCD2BIN(regs.hour & 0x3f);
+ tm->tm_hour = bcd2bin(regs.hour & 0x3f);
tm->tm_wday = (regs.wday & 7) - 1;
- tm->tm_mday = BCD2BIN(regs.mday & 0x3f);
- tm->tm_mon = BCD2BIN(regs.month & 0x1f);
- tm->tm_year = BCD2BIN(regs.year);
+ tm->tm_mday = bcd2bin(regs.mday & 0x3f);
+ tm->tm_mon = bcd2bin(regs.month & 0x1f);
+ tm->tm_year = bcd2bin(regs.year);
if (tm->tm_year < 70)
tm->tm_year += 100;
return 0;
@@ -114,19 +114,19 @@ static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
ds1216_read(priv->ioaddr, (u8 *)&regs);
regs.tsec = 0; /* clear 0.1 and 0.01 seconds */
- regs.sec = BIN2BCD(tm->tm_sec);
- regs.min = BIN2BCD(tm->tm_min);
+ regs.sec = bin2bcd(tm->tm_sec);
+ regs.min = bin2bcd(tm->tm_min);
regs.hour &= DS1216_HOUR_1224;
if (regs.hour && tm->tm_hour > 12) {
regs.hour |= DS1216_HOUR_AMPM;
tm->tm_hour -= 12;
}
- regs.hour |= BIN2BCD(tm->tm_hour);
+ regs.hour |= bin2bcd(tm->tm_hour);
regs.wday &= ~7;
regs.wday |= tm->tm_wday;
- regs.mday = BIN2BCD(tm->tm_mday);
- regs.month = BIN2BCD(tm->tm_mon);
- regs.year = BIN2BCD(tm->tm_year % 100);
+ regs.mday = bin2bcd(tm->tm_mday);
+ regs.month = bin2bcd(tm->tm_mon);
+ regs.year = bin2bcd(tm->tm_year % 100);
ds1216_switch_ds_to_clock(priv->ioaddr);
ds1216_write(priv->ioaddr, (u8 *)&regs);
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index b9397818f73..18455662077 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -40,7 +40,7 @@
#define RTC_SCLK 0x0400
#ifdef CONFIG_SH_SECUREEDGE5410
-#include <asm/snapgear.h>
+#include <mach/snapgear.h>
#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
#define get_dp() SECUREEDGE_READ_IOPORT()
#else
@@ -107,13 +107,13 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
spin_lock_irq(&rtc->lock);
- tm->tm_sec = BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC));
- tm->tm_min = BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN));
- tm->tm_hour = BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR));
- tm->tm_wday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY));
- tm->tm_mday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE));
- tm->tm_mon = BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1;
- tm->tm_year = BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR));
+ tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC));
+ tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN));
+ tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR));
+ tm->tm_wday = bcd2bin(ds1302_readbyte(RTC_ADDR_DAY));
+ tm->tm_mday = bcd2bin(ds1302_readbyte(RTC_ADDR_DATE));
+ tm->tm_mon = bcd2bin(ds1302_readbyte(RTC_ADDR_MON)) - 1;
+ tm->tm_year = bcd2bin(ds1302_readbyte(RTC_ADDR_YEAR));
if (tm->tm_year < 70)
tm->tm_year += 100;
@@ -141,13 +141,13 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Stop RTC */
ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
- ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec));
- ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min));
- ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour));
- ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday));
- ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday));
- ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1));
- ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100));
+ ds1302_writebyte(RTC_ADDR_SEC, bin2bcd(tm->tm_sec));
+ ds1302_writebyte(RTC_ADDR_MIN, bin2bcd(tm->tm_min));
+ ds1302_writebyte(RTC_ADDR_HOUR, bin2bcd(tm->tm_hour));
+ ds1302_writebyte(RTC_ADDR_DAY, bin2bcd(tm->tm_wday));
+ ds1302_writebyte(RTC_ADDR_DATE, bin2bcd(tm->tm_mday));
+ ds1302_writebyte(RTC_ADDR_MON, bin2bcd(tm->tm_mon + 1));
+ ds1302_writebyte(RTC_ADDR_YEAR, bin2bcd(tm->tm_year % 100));
/* Start RTC */
ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index b91d02a3ace..fc372df6534 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -114,10 +114,10 @@ static unsigned bcd2hour(u8 bcd)
hour = 12;
bcd &= ~DS1305_HR_PM;
}
- hour += BCD2BIN(bcd);
+ hour += bcd2bin(bcd);
return hour - 1;
}
- return BCD2BIN(bcd);
+ return bcd2bin(bcd);
}
static u8 hour2bcd(bool hr12, int hour)
@@ -125,11 +125,11 @@ static u8 hour2bcd(bool hr12, int hour)
if (hr12) {
hour++;
if (hour <= 12)
- return DS1305_HR_12 | BIN2BCD(hour);
+ return DS1305_HR_12 | bin2bcd(hour);
hour -= 12;
- return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour);
+ return DS1305_HR_12 | DS1305_HR_PM | bin2bcd(hour);
}
- return BIN2BCD(hour);
+ return bin2bcd(hour);
}
/*----------------------------------------------------------------------*/
@@ -206,13 +206,13 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time)
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_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;
+ 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",
@@ -239,13 +239,13 @@ static int ds1305_set_time(struct device *dev, struct rtc_time *time)
/* 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++ = 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);
+ *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],
@@ -329,8 +329,8 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
* 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_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;
@@ -387,8 +387,8 @@ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
/* 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_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;
@@ -606,7 +606,6 @@ ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
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,
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 4fcf0734a6e..162330b9d1d 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -222,17 +222,17 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
ds1307->regs[4], ds1307->regs[5],
ds1307->regs[6]);
- t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f);
- t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+ t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
+ t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
- t->tm_hour = BCD2BIN(tmp);
- t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
- t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+ t->tm_hour = bcd2bin(tmp);
+ t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
+ t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
- t->tm_mon = BCD2BIN(tmp) - 1;
+ t->tm_mon = bcd2bin(tmp) - 1;
/* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
- t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100;
+ t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100;
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -258,16 +258,16 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
t->tm_mon, t->tm_year, t->tm_wday);
*buf++ = 0; /* first register addr */
- buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec);
- buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min);
- buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour);
- buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1);
- buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday);
- buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1);
+ buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
+ buf[DS1307_REG_MIN] = bin2bcd(t->tm_min);
+ buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
+ buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
+ buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);
+ buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
/* assume 20YY not 19YY */
tmp = t->tm_year - 100;
- buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
+ buf[DS1307_REG_YEAR] = bin2bcd(tmp);
switch (ds1307->type) {
case ds_1337:
@@ -551,7 +551,6 @@ static struct bin_attribute nvram = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.read = ds1307_nvram_read,
@@ -709,18 +708,18 @@ read_rtc:
}
tmp = ds1307->regs[DS1307_REG_SECS];
- tmp = BCD2BIN(tmp & 0x7f);
+ tmp = bcd2bin(tmp & 0x7f);
if (tmp > 60)
goto exit_bad;
- tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+ tmp = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
if (tmp > 60)
goto exit_bad;
- tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+ tmp = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
if (tmp == 0 || tmp > 31)
goto exit_bad;
- tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
+ tmp = bcd2bin(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
if (tmp == 0 || tmp > 12)
goto exit_bad;
@@ -739,14 +738,14 @@ read_rtc:
/* Be sure we're in 24 hour mode. Multi-master systems
* take note...
*/
- tmp = BCD2BIN(tmp & 0x1f);
+ tmp = bcd2bin(tmp & 0x1f);
if (tmp == 12)
tmp = 0;
if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
tmp += 12;
i2c_smbus_write_byte_data(client,
DS1307_REG_HOUR,
- BIN2BCD(tmp));
+ bin2bcd(tmp));
}
ds1307->rtc = rtc_device_register(client->name, &client->dev,
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 86981d34fbb..25caada7839 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -153,8 +153,8 @@ ds1511_wdog_set(unsigned long deciseconds)
/*
* set the wdog values in the wdog registers
*/
- rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC);
- rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC);
+ rtc_write(bin2bcd(deciseconds % 100), DS1511_WD_MSEC);
+ rtc_write(bin2bcd(deciseconds / 100), DS1511_WD_SEC);
/*
* set wdog enable and wdog 'steering' bit to issue a reset
*/
@@ -220,13 +220,13 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
/*
* each register is a different number of valid bits
*/
- sec = BIN2BCD(sec) & 0x7f;
- min = BIN2BCD(min) & 0x7f;
- hrs = BIN2BCD(hrs) & 0x3f;
- day = BIN2BCD(day) & 0x3f;
- mon = BIN2BCD(mon) & 0x1f;
- yrs = BIN2BCD(yrs) & 0xff;
- cen = BIN2BCD(cen) & 0xff;
+ sec = bin2bcd(sec) & 0x7f;
+ min = bin2bcd(min) & 0x7f;
+ hrs = bin2bcd(hrs) & 0x3f;
+ day = bin2bcd(day) & 0x3f;
+ mon = bin2bcd(mon) & 0x1f;
+ yrs = bin2bcd(yrs) & 0xff;
+ cen = bin2bcd(cen) & 0xff;
spin_lock_irqsave(&ds1511_lock, flags);
rtc_disable_update();
@@ -264,14 +264,14 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_enable_update();
spin_unlock_irqrestore(&ds1511_lock, flags);
- rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
- rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
- rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
- rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
- rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday);
- rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
- rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);
- century = BCD2BIN(century) * 100;
+ rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+ rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+ rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+ rtc_tm->tm_wday = bcd2bin(rtc_tm->tm_wday);
+ rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
+ century = bcd2bin(century) * 100;
/*
* Account for differences between how the RTC uses the values
@@ -304,16 +304,16 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata)
spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f,
+ 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f,
RTC_ALARM_DATE);
rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f,
+ 0x80 : bin2bcd(pdata->alrm_hour) & 0x3f,
RTC_ALARM_HOUR);
rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_min) & 0x7f,
+ 0x80 : bin2bcd(pdata->alrm_min) & 0x7f,
RTC_ALARM_MIN);
rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f,
+ 0x80 : bin2bcd(pdata->alrm_sec) & 0x7f,
RTC_ALARM_SEC);
rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD);
rtc_read(RTC_CMD1); /* clear interrupts */
@@ -481,7 +481,6 @@ static struct bin_attribute ds1511_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUGO,
- .owner = THIS_MODULE,
},
.size = DS1511_RAM_MAX,
.read = ds1511_nvram_read,
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 4ef59285b48..b9475cd2021 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -78,17 +78,17 @@ static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
void __iomem *ioaddr = pdata->ioaddr;
u8 century;
- century = BIN2BCD((tm->tm_year + 1900) / 100);
+ century = bin2bcd((tm->tm_year + 1900) / 100);
writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL);
- writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
- writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
- writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
- writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
- writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
- writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
- writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+ writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
+ writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+ writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+ writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
+ writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
+ writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
+ writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
/* RTC_CENTURY and RTC_CONTROL share same register */
writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
@@ -118,14 +118,14 @@ static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
year = readb(ioaddr + RTC_YEAR);
century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
writeb(0, ioaddr + RTC_CONTROL);
- tm->tm_sec = BCD2BIN(second);
- tm->tm_min = BCD2BIN(minute);
- tm->tm_hour = BCD2BIN(hour);
- tm->tm_mday = BCD2BIN(day);
- tm->tm_wday = BCD2BIN(week);
- tm->tm_mon = BCD2BIN(month) - 1;
+ tm->tm_sec = bcd2bin(second);
+ tm->tm_min = bcd2bin(minute);
+ tm->tm_hour = bcd2bin(hour);
+ tm->tm_mday = bcd2bin(day);
+ tm->tm_wday = bcd2bin(week);
+ tm->tm_mon = bcd2bin(month) - 1;
/* year is 1900 + tm->tm_year */
- tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+ tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "retrieved date/time is not valid.\n");
@@ -141,16 +141,16 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_mday),
+ 0x80 : bin2bcd(pdata->alrm_mday),
ioaddr + RTC_DATE_ALARM);
writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_hour),
+ 0x80 : bin2bcd(pdata->alrm_hour),
ioaddr + RTC_HOURS_ALARM);
writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_min),
+ 0x80 : bin2bcd(pdata->alrm_min),
ioaddr + RTC_MINUTES_ALARM);
writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_sec),
+ 0x80 : bin2bcd(pdata->alrm_sec),
ioaddr + RTC_SECONDS_ALARM);
writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
readb(ioaddr + RTC_FLAGS); /* clear interrupts */
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 24d35ede2db..8bc8501bffc 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -66,17 +66,17 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
void __iomem *ioaddr = pdata->ioaddr_rtc;
u8 century;
- century = BIN2BCD((tm->tm_year + 1900) / 100);
+ century = bin2bcd((tm->tm_year + 1900) / 100);
writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
- writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
- writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
- writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
- writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
- writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
- writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
- writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+ writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
+ writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+ writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+ writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
+ writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
+ writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
+ writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
/* RTC_CENTURY and RTC_CONTROL share same register */
writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
@@ -106,14 +106,14 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
year = readb(ioaddr + RTC_YEAR);
century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
writeb(0, ioaddr + RTC_CONTROL);
- tm->tm_sec = BCD2BIN(second);
- tm->tm_min = BCD2BIN(minute);
- tm->tm_hour = BCD2BIN(hour);
- tm->tm_mday = BCD2BIN(day);
- tm->tm_wday = BCD2BIN(week);
- tm->tm_mon = BCD2BIN(month) - 1;
+ tm->tm_sec = bcd2bin(second);
+ tm->tm_min = bcd2bin(minute);
+ tm->tm_hour = bcd2bin(hour);
+ tm->tm_mday = bcd2bin(day);
+ tm->tm_wday = bcd2bin(week);
+ tm->tm_mon = bcd2bin(month) - 1;
/* year is 1900 + tm->tm_year */
- tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+ tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "retrieved date/time is not valid.\n");
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index abfdfcbaa05..3a7be11cc6b 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -131,17 +131,17 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)
fm3130->regs[0xc], fm3130->regs[0xd],
fm3130->regs[0xe]);
- t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
- t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
+ t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
+ t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
- t->tm_hour = BCD2BIN(tmp);
- t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
- t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
+ t->tm_hour = bcd2bin(tmp);
+ t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
+ t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
- t->tm_mon = BCD2BIN(tmp) - 1;
+ t->tm_mon = bcd2bin(tmp) - 1;
/* assume 20YY not 19YY, and ignore CF bit */
- t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100;
+ t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -167,16 +167,16 @@ static int fm3130_set_time(struct device *dev, struct rtc_time *t)
t->tm_mon, t->tm_year, t->tm_wday);
/* first register addr */
- buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec);
- buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min);
- buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour);
- buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1);
- buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday);
- buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1);
+ buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
+ buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
+ buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
+ buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
+ buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
+ buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
/* assume 20YY not 19YY */
tmp = t->tm_year - 100;
- buf[FM3130_RTC_YEARS] = BIN2BCD(tmp);
+ buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x"
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -222,11 +222,11 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
fm3130->regs[FM3130_ALARM_MONTHS]);
- tm->tm_sec = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
- tm->tm_min = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
- tm->tm_hour = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
- tm->tm_mday = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
- tm->tm_mon = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
+ tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
+ tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
+ tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
+ tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
+ tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
if (tm->tm_mon > 0)
tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
dev_dbg(dev, "%s secs=%d, mins=%d, "
@@ -252,23 +252,23 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (tm->tm_sec != -1)
fm3130->regs[FM3130_ALARM_SECONDS] =
- BIN2BCD(tm->tm_sec) | 0x80;
+ bin2bcd(tm->tm_sec) | 0x80;
if (tm->tm_min != -1)
fm3130->regs[FM3130_ALARM_MINUTES] =
- BIN2BCD(tm->tm_min) | 0x80;
+ bin2bcd(tm->tm_min) | 0x80;
if (tm->tm_hour != -1)
fm3130->regs[FM3130_ALARM_HOURS] =
- BIN2BCD(tm->tm_hour) | 0x80;
+ bin2bcd(tm->tm_hour) | 0x80;
if (tm->tm_mday != -1)
fm3130->regs[FM3130_ALARM_DATE] =
- BIN2BCD(tm->tm_mday) | 0x80;
+ bin2bcd(tm->tm_mday) | 0x80;
if (tm->tm_mon != -1)
fm3130->regs[FM3130_ALARM_MONTHS] =
- BIN2BCD(tm->tm_mon + 1) | 0x80;
+ bin2bcd(tm->tm_mon + 1) | 0x80;
dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
fm3130->regs[FM3130_ALARM_SECONDS],
@@ -414,18 +414,18 @@ static int __devinit fm3130_probe(struct i2c_client *client,
/* TODO */
/* TODO need to sanity check alarm */
tmp = fm3130->regs[FM3130_RTC_SECONDS];
- tmp = BCD2BIN(tmp & 0x7f);
+ tmp = bcd2bin(tmp & 0x7f);
if (tmp > 60)
goto exit_bad;
- tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
+ tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
if (tmp > 60)
goto exit_bad;
- tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
+ tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
if (tmp == 0 || tmp > 31)
goto exit_bad;
- tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
+ tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
if (tmp == 0 || tmp > 12)
goto exit_bad;
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index a81adab6e51..2cd77ab8fc6 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -259,26 +259,26 @@ isl1208_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
return sr;
}
- tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]);
- tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]);
+ tm->tm_sec = bcd2bin(regs[ISL1208_REG_SC]);
+ tm->tm_min = bcd2bin(regs[ISL1208_REG_MN]);
/* HR field has a more complex interpretation */
{
const u8 _hr = regs[ISL1208_REG_HR];
if (_hr & ISL1208_REG_HR_MIL) /* 24h format */
- tm->tm_hour = BCD2BIN(_hr & 0x3f);
+ tm->tm_hour = bcd2bin(_hr & 0x3f);
else {
/* 12h format */
- tm->tm_hour = BCD2BIN(_hr & 0x1f);
+ tm->tm_hour = bcd2bin(_hr & 0x1f);
if (_hr & ISL1208_REG_HR_PM) /* PM flag set */
tm->tm_hour += 12;
}
}
- tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]);
- tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
- tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100;
- tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]);
+ tm->tm_mday = bcd2bin(regs[ISL1208_REG_DT]);
+ tm->tm_mon = bcd2bin(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
+ tm->tm_year = bcd2bin(regs[ISL1208_REG_YR]) + 100;
+ tm->tm_wday = bcd2bin(regs[ISL1208_REG_DW]);
return 0;
}
@@ -305,13 +305,13 @@ isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
}
/* MSB of each alarm register is an enable bit */
- tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f);
- tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f);
- tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f);
- tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f);
+ tm->tm_sec = bcd2bin(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f);
+ tm->tm_min = bcd2bin(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f);
+ tm->tm_hour = bcd2bin(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f);
+ tm->tm_mday = bcd2bin(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f);
tm->tm_mon =
- BCD2BIN(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
- tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
+ bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
+ tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
return 0;
}
@@ -328,15 +328,15 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
int sr;
u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
- regs[ISL1208_REG_SC] = BIN2BCD(tm->tm_sec);
- regs[ISL1208_REG_MN] = BIN2BCD(tm->tm_min);
- regs[ISL1208_REG_HR] = BIN2BCD(tm->tm_hour) | ISL1208_REG_HR_MIL;
+ regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec);
+ regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min);
+ regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL;
- regs[ISL1208_REG_DT] = BIN2BCD(tm->tm_mday);
- regs[ISL1208_REG_MO] = BIN2BCD(tm->tm_mon + 1);
- regs[ISL1208_REG_YR] = BIN2BCD(tm->tm_year - 100);
+ regs[ISL1208_REG_DT] = bin2bcd(tm->tm_mday);
+ regs[ISL1208_REG_MO] = bin2bcd(tm->tm_mon + 1);
+ regs[ISL1208_REG_YR] = bin2bcd(tm->tm_year - 100);
- regs[ISL1208_REG_DW] = BIN2BCD(tm->tm_wday & 7);
+ regs[ISL1208_REG_DW] = bin2bcd(tm->tm_wday & 7);
sr = isl1208_i2c_get_sr(client);
if (sr < 0) {
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 470fb2d2954..893f7dece23 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -110,15 +110,15 @@ static int m41t80_get_datetime(struct i2c_client *client,
return -EIO;
}
- tm->tm_sec = BCD2BIN(buf[M41T80_REG_SEC] & 0x7f);
- tm->tm_min = BCD2BIN(buf[M41T80_REG_MIN] & 0x7f);
- tm->tm_hour = BCD2BIN(buf[M41T80_REG_HOUR] & 0x3f);
- tm->tm_mday = BCD2BIN(buf[M41T80_REG_DAY] & 0x3f);
+ tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f);
+ tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f);
+ tm->tm_hour = bcd2bin(buf[M41T80_REG_HOUR] & 0x3f);
+ tm->tm_mday = bcd2bin(buf[M41T80_REG_DAY] & 0x3f);
tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07;
- tm->tm_mon = BCD2BIN(buf[M41T80_REG_MON] & 0x1f) - 1;
+ tm->tm_mon = bcd2bin(buf[M41T80_REG_MON] & 0x1f) - 1;
/* assume 20YY not 19YY, and ignore the Century Bit */
- tm->tm_year = BCD2BIN(buf[M41T80_REG_YEAR]) + 100;
+ tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100;
return 0;
}
@@ -161,19 +161,19 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
/* Merge time-data and register flags into buf[0..7] */
buf[M41T80_REG_SSEC] = 0;
buf[M41T80_REG_SEC] =
- BIN2BCD(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
+ bin2bcd(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
buf[M41T80_REG_MIN] =
- BIN2BCD(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
+ bin2bcd(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
buf[M41T80_REG_HOUR] =
- BIN2BCD(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
+ bin2bcd(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
buf[M41T80_REG_WDAY] =
(tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
buf[M41T80_REG_DAY] =
- BIN2BCD(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
+ bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
buf[M41T80_REG_MON] =
- BIN2BCD(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
+ bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
/* assume 20YY not 19YY */
- buf[M41T80_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+ buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100);
if (i2c_transfer(client->adapter, msgs, 1) != 1) {
dev_err(&client->dev, "write error\n");
@@ -288,15 +288,15 @@ static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */
reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ?
- BIN2BCD(t->time.tm_sec) : 0x80;
+ bin2bcd(t->time.tm_sec) : 0x80;
reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ?
- BIN2BCD(t->time.tm_min) : 0x80;
+ bin2bcd(t->time.tm_min) : 0x80;
reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ?
- BIN2BCD(t->time.tm_hour) : 0x80;
+ bin2bcd(t->time.tm_hour) : 0x80;
reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ?
- BIN2BCD(t->time.tm_mday) : 0x80;
+ bin2bcd(t->time.tm_mday) : 0x80;
if (t->time.tm_mon >= 0)
- reg[M41T80_REG_ALARM_MON] |= BIN2BCD(t->time.tm_mon + 1);
+ reg[M41T80_REG_ALARM_MON] |= bin2bcd(t->time.tm_mon + 1);
else
reg[M41T80_REG_ALARM_DAY] |= 0x40;
@@ -347,15 +347,15 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_mday = -1;
t->time.tm_mon = -1;
if (!(reg[M41T80_REG_ALARM_SEC] & 0x80))
- t->time.tm_sec = BCD2BIN(reg[M41T80_REG_ALARM_SEC] & 0x7f);
+ t->time.tm_sec = bcd2bin(reg[M41T80_REG_ALARM_SEC] & 0x7f);
if (!(reg[M41T80_REG_ALARM_MIN] & 0x80))
- t->time.tm_min = BCD2BIN(reg[M41T80_REG_ALARM_MIN] & 0x7f);
+ t->time.tm_min = bcd2bin(reg[M41T80_REG_ALARM_MIN] & 0x7f);
if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80))
- t->time.tm_hour = BCD2BIN(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
+ t->time.tm_hour = bcd2bin(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
if (!(reg[M41T80_REG_ALARM_DAY] & 0x80))
- t->time.tm_mday = BCD2BIN(reg[M41T80_REG_ALARM_DAY] & 0x3f);
+ t->time.tm_mday = bcd2bin(reg[M41T80_REG_ALARM_DAY] & 0x3f);
if (!(reg[M41T80_REG_ALARM_DAY] & 0x40))
- t->time.tm_mon = BCD2BIN(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
+ t->time.tm_mon = bcd2bin(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
t->time.tm_year = -1;
t->time.tm_wday = -1;
t->time.tm_yday = -1;
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
index 9b19499c829..c3a18c58daf 100644
--- a/drivers/rtc/rtc-m41t94.c
+++ b/drivers/rtc/rtc-m41t94.c
@@ -41,17 +41,17 @@ static int m41t94_set_time(struct device *dev, struct rtc_time *tm)
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_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);
+ buf[M41T94_REG_YEAR] = bin2bcd(tm->tm_year % 100);
return spi_write(spi, buf, 8);
}
@@ -82,14 +82,14 @@ static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
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));
+ 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));
+ 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;
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index ce4eff6a8d5..04b63dab693 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -76,10 +76,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* Issue the READ command */
M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
- tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+ tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
/* tm_mon is 0-11 */
- tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
- tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY));
+ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
+ tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY));
val = M48T59_READ(M48T59_WDAY);
if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
@@ -88,10 +88,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year += 100; /* one century */
}
- tm->tm_wday = BCD2BIN(val & 0x07);
- tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F);
- tm->tm_min = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F);
- tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F);
+ tm->tm_wday = bcd2bin(val & 0x07);
+ tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F);
+ tm->tm_min = bcd2bin(M48T59_READ(M48T59_MIN) & 0x7F);
+ tm->tm_sec = bcd2bin(M48T59_READ(M48T59_SEC) & 0x7F);
/* Clear the READ bit */
M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
@@ -119,17 +119,17 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Issue the WRITE command */
M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
- M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC);
- M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN);
- M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR);
- M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY);
+ M48T59_WRITE((bin2bcd(tm->tm_sec) & 0x7F), M48T59_SEC);
+ M48T59_WRITE((bin2bcd(tm->tm_min) & 0x7F), M48T59_MIN);
+ M48T59_WRITE((bin2bcd(tm->tm_hour) & 0x3F), M48T59_HOUR);
+ M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY);
/* tm_mon is 0-11 */
- M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
- M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
+ M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
+ M48T59_WRITE(bin2bcd(tm->tm_year % 100), M48T59_YEAR);
if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100))
val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
- val |= (BIN2BCD(tm->tm_wday) & 0x07);
+ val |= (bin2bcd(tm->tm_wday) & 0x07);
M48T59_WRITE(val, M48T59_WDAY);
/* Clear the WRITE bit */
@@ -158,18 +158,18 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Issue the READ command */
M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
- tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+ tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
/* tm_mon is 0-11 */
- tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
val = M48T59_READ(M48T59_WDAY);
if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
tm->tm_year += 100; /* one century */
- tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE));
- tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR));
- tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN));
- tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC));
+ tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE));
+ tm->tm_hour = bcd2bin(M48T59_READ(M48T59_ALARM_HOUR));
+ tm->tm_min = bcd2bin(M48T59_READ(M48T59_ALARM_MIN));
+ tm->tm_sec = bcd2bin(M48T59_READ(M48T59_ALARM_SEC));
/* Clear the READ bit */
M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
@@ -201,18 +201,18 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
* 0xff means "always match"
*/
mday = tm->tm_mday;
- mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+ mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
if (mday == 0xff)
mday = M48T59_READ(M48T59_MDAY);
hour = tm->tm_hour;
- hour = (hour < 24) ? BIN2BCD(hour) : 0x00;
+ hour = (hour < 24) ? bin2bcd(hour) : 0x00;
min = tm->tm_min;
- min = (min < 60) ? BIN2BCD(min) : 0x00;
+ min = (min < 60) ? bin2bcd(min) : 0x00;
sec = tm->tm_sec;
- sec = (sec < 60) ? BIN2BCD(sec) : 0x00;
+ sec = (sec < 60) ? bin2bcd(sec) : 0x00;
spin_lock_irqsave(&m48t59->lock, flags);
/* Issue the WRITE command */
@@ -360,7 +360,6 @@ static struct bin_attribute m48t59_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.read = m48t59_nvram_read,
.write = m48t59_nvram_write,
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index 3f7f99a5d96..7c045cffa9f 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -62,14 +62,14 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_wday = ops->readbyte(M48T86_REG_DOW);
} else {
/* bcd mode */
- tm->tm_sec = BCD2BIN(ops->readbyte(M48T86_REG_SEC));
- tm->tm_min = BCD2BIN(ops->readbyte(M48T86_REG_MIN));
- tm->tm_hour = BCD2BIN(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
- tm->tm_mday = BCD2BIN(ops->readbyte(M48T86_REG_DOM));
+ tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC));
+ tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN));
+ tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
+ tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM));
/* tm_mon is 0-11 */
- tm->tm_mon = BCD2BIN(ops->readbyte(M48T86_REG_MONTH)) - 1;
- tm->tm_year = BCD2BIN(ops->readbyte(M48T86_REG_YEAR)) + 100;
- tm->tm_wday = BCD2BIN(ops->readbyte(M48T86_REG_DOW));
+ tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1;
+ tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100;
+ tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW));
}
/* correct the hour if the clock is in 12h mode */
@@ -103,13 +103,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
} else {
/* bcd mode */
- ops->writebyte(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
- ops->writebyte(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
- ops->writebyte(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
- ops->writebyte(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
- ops->writebyte(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
- ops->writebyte(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
- ops->writebyte(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
+ ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC);
+ ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN);
+ ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
+ ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM);
+ ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
+ ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
+ ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW);
}
/* update ended */
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index 12c9cd25cad..80782798763 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -150,14 +150,14 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
if (rc < 0)
return rc;
- tm->tm_sec = BCD2BIN(regs[MAX6900_REG_SC]);
- tm->tm_min = BCD2BIN(regs[MAX6900_REG_MN]);
- tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f);
- tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]);
- tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1;
- tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) +
- BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
- tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]);
+ tm->tm_sec = bcd2bin(regs[MAX6900_REG_SC]);
+ tm->tm_min = bcd2bin(regs[MAX6900_REG_MN]);
+ tm->tm_hour = bcd2bin(regs[MAX6900_REG_HR] & 0x3f);
+ tm->tm_mday = bcd2bin(regs[MAX6900_REG_DT]);
+ tm->tm_mon = bcd2bin(regs[MAX6900_REG_MO]) - 1;
+ tm->tm_year = bcd2bin(regs[MAX6900_REG_YR]) +
+ bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
+ tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]);
return 0;
}
@@ -184,14 +184,14 @@ max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
if (rc < 0)
return rc;
- regs[MAX6900_REG_SC] = BIN2BCD(tm->tm_sec);
- regs[MAX6900_REG_MN] = BIN2BCD(tm->tm_min);
- regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour);
- regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday);
- regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1);
- regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday);
- regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year % 100);
- regs[MAX6900_REG_CENTURY] = BIN2BCD((tm->tm_year + 1900) / 100);
+ regs[MAX6900_REG_SC] = bin2bcd(tm->tm_sec);
+ regs[MAX6900_REG_MN] = bin2bcd(tm->tm_min);
+ regs[MAX6900_REG_HR] = bin2bcd(tm->tm_hour);
+ regs[MAX6900_REG_DT] = bin2bcd(tm->tm_mday);
+ regs[MAX6900_REG_MO] = bin2bcd(tm->tm_mon + 1);
+ regs[MAX6900_REG_DW] = bin2bcd(tm->tm_wday);
+ regs[MAX6900_REG_YR] = bin2bcd(tm->tm_year % 100);
+ regs[MAX6900_REG_CENTURY] = bin2bcd((tm->tm_year + 1900) / 100);
/* set write protect */
regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP;
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index 78b2551fb19..2f6507df7b4 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -124,15 +124,15 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt)
/* The chip sends data in this order:
* Seconds, Minutes, Hours, Date, Month, Day, Year */
- dt->tm_sec = BCD2BIN(chip->buf[1]);
- dt->tm_min = BCD2BIN(chip->buf[2]);
- dt->tm_hour = BCD2BIN(chip->buf[3]);
- dt->tm_mday = BCD2BIN(chip->buf[4]);
- dt->tm_mon = BCD2BIN(chip->buf[5]) - 1;
- dt->tm_wday = BCD2BIN(chip->buf[6]);
- dt->tm_year = BCD2BIN(chip->buf[7]);
+ dt->tm_sec = bcd2bin(chip->buf[1]);
+ dt->tm_min = bcd2bin(chip->buf[2]);
+ dt->tm_hour = bcd2bin(chip->buf[3]);
+ dt->tm_mday = bcd2bin(chip->buf[4]);
+ dt->tm_mon = bcd2bin(chip->buf[5]) - 1;
+ dt->tm_wday = bcd2bin(chip->buf[6]);
+ dt->tm_year = bcd2bin(chip->buf[7]);
- century = BCD2BIN(tmp) * 100;
+ century = bcd2bin(tmp) * 100;
dt->tm_year += century;
dt->tm_year -= 1900;
@@ -168,15 +168,15 @@ static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
/* Remove write protection */
max6902_set_reg(dev, 0xF, 0);
- max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec));
- max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min));
- max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour));
+ max6902_set_reg(dev, 0x01, bin2bcd(dt->tm_sec));
+ max6902_set_reg(dev, 0x03, bin2bcd(dt->tm_min));
+ max6902_set_reg(dev, 0x05, bin2bcd(dt->tm_hour));
- max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday));
- max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1));
- max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday));
- max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100));
- max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100));
+ max6902_set_reg(dev, 0x07, bin2bcd(dt->tm_mday));
+ max6902_set_reg(dev, 0x09, bin2bcd(dt->tm_mon+1));
+ max6902_set_reg(dev, 0x0B, bin2bcd(dt->tm_wday));
+ max6902_set_reg(dev, 0x0D, bin2bcd(dt->tm_year%100));
+ max6902_set_reg(dev, 0x13, bin2bcd(dt->tm_year/100));
/* Compulab used a delay here. However, the datasheet
* does not mention a delay being required anywhere... */
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 8876605d4d4..2cbeb0794f1 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -186,30 +186,30 @@ static int tm2bcd(struct rtc_time *tm)
if (rtc_valid_tm(tm) != 0)
return -EINVAL;
- tm->tm_sec = BIN2BCD(tm->tm_sec);
- tm->tm_min = BIN2BCD(tm->tm_min);
- tm->tm_hour = BIN2BCD(tm->tm_hour);
- tm->tm_mday = BIN2BCD(tm->tm_mday);
+ tm->tm_sec = bin2bcd(tm->tm_sec);
+ tm->tm_min = bin2bcd(tm->tm_min);
+ tm->tm_hour = bin2bcd(tm->tm_hour);
+ tm->tm_mday = bin2bcd(tm->tm_mday);
- tm->tm_mon = BIN2BCD(tm->tm_mon + 1);
+ tm->tm_mon = bin2bcd(tm->tm_mon + 1);
/* epoch == 1900 */
if (tm->tm_year < 100 || tm->tm_year > 199)
return -EINVAL;
- tm->tm_year = BIN2BCD(tm->tm_year - 100);
+ tm->tm_year = bin2bcd(tm->tm_year - 100);
return 0;
}
static void bcd2tm(struct rtc_time *tm)
{
- tm->tm_sec = BCD2BIN(tm->tm_sec);
- tm->tm_min = BCD2BIN(tm->tm_min);
- tm->tm_hour = BCD2BIN(tm->tm_hour);
- tm->tm_mday = BCD2BIN(tm->tm_mday);
- tm->tm_mon = BCD2BIN(tm->tm_mon) - 1;
+ tm->tm_sec = bcd2bin(tm->tm_sec);
+ tm->tm_min = bcd2bin(tm->tm_min);
+ tm->tm_hour = bcd2bin(tm->tm_hour);
+ tm->tm_mday = bcd2bin(tm->tm_mday);
+ tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
/* epoch == 1900 */
- tm->tm_year = BCD2BIN(tm->tm_year) + 100;
+ tm->tm_year = bcd2bin(tm->tm_year) + 100;
}
diff --git a/drivers/rtc/rtc-parisc.c b/drivers/rtc/rtc-parisc.c
new file mode 100644
index 00000000000..346d633655e
--- /dev/null
+++ b/drivers/rtc/rtc-parisc.c
@@ -0,0 +1,111 @@
+/* rtc-parisc: RTC for HP PA-RISC firmware
+ *
+ * Copyright (C) 2008 Kyle McMartin <kyle@mcmartin.ca>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+
+#include <asm/rtc.h>
+
+/* as simple as can be, and no simpler. */
+struct parisc_rtc {
+ struct rtc_device *rtc;
+ spinlock_t lock;
+};
+
+static int parisc_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct parisc_rtc *p = dev_get_drvdata(dev);
+ unsigned long flags, ret;
+
+ spin_lock_irqsave(&p->lock, flags);
+ ret = get_rtc_time(tm);
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ if (ret & RTC_BATT_BAD)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int parisc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct parisc_rtc *p = dev_get_drvdata(dev);
+ unsigned long flags, ret;
+
+ spin_lock_irqsave(&p->lock, flags);
+ ret = set_rtc_time(tm);
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ if (ret < 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static const struct rtc_class_ops parisc_rtc_ops = {
+ .read_time = parisc_get_time,
+ .set_time = parisc_set_time,
+};
+
+static int __devinit parisc_rtc_probe(struct platform_device *dev)
+{
+ struct parisc_rtc *p;
+
+ p = kzalloc(sizeof (*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ spin_lock_init(&p->lock);
+
+ p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops,
+ THIS_MODULE);
+ if (IS_ERR(p->rtc)) {
+ int err = PTR_ERR(p->rtc);
+ kfree(p);
+ return err;
+ }
+
+ platform_set_drvdata(dev, p);
+
+ return 0;
+}
+
+static int __devexit parisc_rtc_remove(struct platform_device *dev)
+{
+ struct parisc_rtc *p = platform_get_drvdata(dev);
+
+ rtc_device_unregister(p->rtc);
+ kfree(p);
+
+ return 0;
+}
+
+static struct platform_driver parisc_rtc_driver = {
+ .driver = {
+ .name = "rtc-parisc",
+ .owner = THIS_MODULE,
+ },
+ .probe = parisc_rtc_probe,
+ .remove = __devexit_p(parisc_rtc_remove),
+};
+
+static int __init parisc_rtc_init(void)
+{
+ return platform_driver_register(&parisc_rtc_driver);
+}
+
+static void __exit parisc_rtc_fini(void)
+{
+ platform_driver_unregister(&parisc_rtc_driver);
+}
+
+module_init(parisc_rtc_init);
+module_exit(parisc_rtc_fini);
+
+MODULE_AUTHOR("Kyle McMartin <kyle@mcmartin.ca>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HP PA-RISC RTC driver");
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index a829f20ad6d..b725913ccbe 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -97,13 +97,13 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[8]);
- tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F);
- tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F);
- tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
- tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F);
+ tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
+ tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
+ tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
+ tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
- tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
- tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]);
+ tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+ tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
if (tm->tm_year < 70)
tm->tm_year += 100; /* assume we are in 1970...2069 */
/* detect the polarity heuristically. see note above. */
@@ -138,17 +138,17 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* hours, minutes and seconds */
- buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec);
- buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min);
- buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour);
+ buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
+ buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
+ buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
- buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday);
+ buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
/* month, 1 - 12 */
- buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1);
+ buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
/* year and century */
- buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
+ buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index d388c662bf4..7d33cda3f8f 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -76,11 +76,11 @@ static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
buf[4] &= 0x3f;
buf[5] &= 0x1f;
- dt->tm_sec = BCD2BIN(buf[1]);
- dt->tm_min = BCD2BIN(buf[2]);
- dt->tm_hour = BCD2BIN(buf[3]);
- dt->tm_mday = BCD2BIN(buf[4]);
- dt->tm_mon = BCD2BIN(buf[5]) - 1;
+ dt->tm_sec = bcd2bin(buf[1]);
+ dt->tm_min = bcd2bin(buf[2]);
+ dt->tm_hour = bcd2bin(buf[3]);
+ dt->tm_mday = bcd2bin(buf[4]);
+ dt->tm_mon = bcd2bin(buf[5]) - 1;
}
return ret == 2 ? 0 : -EIO;
@@ -94,14 +94,14 @@ static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt,
buf[0] = 0;
buf[1] = get_ctrl(client) | 0x80;
buf[2] = 0;
- buf[3] = BIN2BCD(dt->tm_sec);
- buf[4] = BIN2BCD(dt->tm_min);
- buf[5] = BIN2BCD(dt->tm_hour);
+ buf[3] = bin2bcd(dt->tm_sec);
+ buf[4] = bin2bcd(dt->tm_min);
+ buf[5] = bin2bcd(dt->tm_hour);
if (datetoo) {
len = 8;
- buf[6] = BIN2BCD(dt->tm_mday) | (dt->tm_year << 6);
- buf[7] = BIN2BCD(dt->tm_mon + 1) | (dt->tm_wday << 5);
+ buf[6] = bin2bcd(dt->tm_mday) | (dt->tm_year << 6);
+ buf[7] = bin2bcd(dt->tm_mon + 1) | (dt->tm_wday << 5);
}
ret = i2c_master_send(client, (char *)buf, len);
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index 395985b339c..42028f233be 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -80,13 +80,13 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
memset(dt, 0, sizeof(*dt));
- dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */
- dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */
- dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */
+ dt->tm_sec = bcd2bin(buf[0]); /* RSECCNT */
+ dt->tm_min = bcd2bin(buf[1]); /* RMINCNT */
+ dt->tm_hour = bcd2bin(buf[2]); /* RHRCNT */
- dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */
- dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */
- dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */
+ dt->tm_mday = bcd2bin(buf[3]); /* RDAYCNT */
+ dt->tm_mon = bcd2bin(buf[4]) - 1; /* RMONCNT */
+ dt->tm_year = bcd2bin(buf[5]) + 100; /* RYRCNT */
/* the rtc device may contain illegal values on power up
* according to the data sheet. make sure they are valid.
@@ -103,12 +103,12 @@ static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)
if (year >= 2100 || year < 2000)
return -EINVAL;
- ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour));
- ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min));
- ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec));
- ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday));
- ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1));
- ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100));
+ ret = write_reg(dev, RHRCNT, bin2bcd(dt->tm_hour));
+ ret = ret ? ret : write_reg(dev, RMINCNT, bin2bcd(dt->tm_min));
+ ret = ret ? ret : write_reg(dev, RSECCNT, bin2bcd(dt->tm_sec));
+ ret = ret ? ret : write_reg(dev, RDAYCNT, bin2bcd(dt->tm_mday));
+ ret = ret ? ret : write_reg(dev, RMONCNT, bin2bcd(dt->tm_mon + 1));
+ ret = ret ? ret : write_reg(dev, RYRCNT, bin2bcd(dt->tm_year - 100));
ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday);
return ret;
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c
index 1c14d4497c4..e6ea3f5ee1e 100644
--- a/drivers/rtc/rtc-rs5c313.c
+++ b/drivers/rtc/rtc-rs5c313.c
@@ -235,33 +235,33 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
data = rs5c313_read_reg(RS5C313_ADDR_SEC);
data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4);
- tm->tm_sec = BCD2BIN(data);
+ tm->tm_sec = bcd2bin(data);
data = rs5c313_read_reg(RS5C313_ADDR_MIN);
data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4);
- tm->tm_min = BCD2BIN(data);
+ tm->tm_min = bcd2bin(data);
data = rs5c313_read_reg(RS5C313_ADDR_HOUR);
data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4);
- tm->tm_hour = BCD2BIN(data);
+ tm->tm_hour = bcd2bin(data);
data = rs5c313_read_reg(RS5C313_ADDR_DAY);
data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4);
- tm->tm_mday = BCD2BIN(data);
+ tm->tm_mday = bcd2bin(data);
data = rs5c313_read_reg(RS5C313_ADDR_MON);
data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4);
- tm->tm_mon = BCD2BIN(data) - 1;
+ tm->tm_mon = bcd2bin(data) - 1;
data = rs5c313_read_reg(RS5C313_ADDR_YEAR);
data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4);
- tm->tm_year = BCD2BIN(data);
+ tm->tm_year = bcd2bin(data);
if (tm->tm_year < 70)
tm->tm_year += 100;
data = rs5c313_read_reg(RS5C313_ADDR_WEEK);
- tm->tm_wday = BCD2BIN(data);
+ tm->tm_wday = bcd2bin(data);
RS5C313_CEDISABLE;
ndelay(700); /* CE:L */
@@ -294,31 +294,31 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
}
}
- data = BIN2BCD(tm->tm_sec);
+ data = bin2bcd(tm->tm_sec);
rs5c313_write_reg(RS5C313_ADDR_SEC, data);
rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4));
- data = BIN2BCD(tm->tm_min);
+ data = bin2bcd(tm->tm_min);
rs5c313_write_reg(RS5C313_ADDR_MIN, data );
rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4));
- data = BIN2BCD(tm->tm_hour);
+ data = bin2bcd(tm->tm_hour);
rs5c313_write_reg(RS5C313_ADDR_HOUR, data);
rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4));
- data = BIN2BCD(tm->tm_mday);
+ data = bin2bcd(tm->tm_mday);
rs5c313_write_reg(RS5C313_ADDR_DAY, data);
rs5c313_write_reg(RS5C313_ADDR_DAY10, (data>> 4));
- data = BIN2BCD(tm->tm_mon + 1);
+ data = bin2bcd(tm->tm_mon + 1);
rs5c313_write_reg(RS5C313_ADDR_MON, data);
rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4));
- data = BIN2BCD(tm->tm_year % 100);
+ data = bin2bcd(tm->tm_year % 100);
rs5c313_write_reg(RS5C313_ADDR_YEAR, data);
rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4));
- data = BIN2BCD(tm->tm_wday);
+ data = bin2bcd(tm->tm_wday);
rs5c313_write_reg(RS5C313_ADDR_WEEK, data);
RS5C313_CEDISABLE; /* CE:H */
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
index 839462659af..dd1e2bc7a47 100644
--- a/drivers/rtc/rtc-rs5c348.c
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -74,20 +74,20 @@ rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm)
txbuf[3] = 0; /* dummy */
txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */
txp = &txbuf[5];
- txp[RS5C348_REG_SECS] = BIN2BCD(tm->tm_sec);
- txp[RS5C348_REG_MINS] = BIN2BCD(tm->tm_min);
+ txp[RS5C348_REG_SECS] = bin2bcd(tm->tm_sec);
+ txp[RS5C348_REG_MINS] = bin2bcd(tm->tm_min);
if (pdata->rtc_24h) {
- txp[RS5C348_REG_HOURS] = BIN2BCD(tm->tm_hour);
+ txp[RS5C348_REG_HOURS] = bin2bcd(tm->tm_hour);
} else {
/* hour 0 is AM12, noon is PM12 */
- txp[RS5C348_REG_HOURS] = BIN2BCD((tm->tm_hour + 11) % 12 + 1) |
+ txp[RS5C348_REG_HOURS] = bin2bcd((tm->tm_hour + 11) % 12 + 1) |
(tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0);
}
- txp[RS5C348_REG_WDAY] = BIN2BCD(tm->tm_wday);
- txp[RS5C348_REG_DAY] = BIN2BCD(tm->tm_mday);
- txp[RS5C348_REG_MONTH] = BIN2BCD(tm->tm_mon + 1) |
+ txp[RS5C348_REG_WDAY] = bin2bcd(tm->tm_wday);
+ txp[RS5C348_REG_DAY] = bin2bcd(tm->tm_mday);
+ txp[RS5C348_REG_MONTH] = bin2bcd(tm->tm_mon + 1) |
(tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0);
- txp[RS5C348_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+ txp[RS5C348_REG_YEAR] = bin2bcd(tm->tm_year % 100);
/* write in one transfer to avoid data inconsistency */
ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0);
udelay(62); /* Tcsr 62us */
@@ -116,20 +116,20 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (ret < 0)
return ret;
- tm->tm_sec = BCD2BIN(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK);
- tm->tm_min = BCD2BIN(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
- tm->tm_hour = BCD2BIN(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
+ tm->tm_sec = bcd2bin(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK);
+ tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
+ tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
if (!pdata->rtc_24h) {
tm->tm_hour %= 12;
if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM)
tm->tm_hour += 12;
}
- tm->tm_wday = BCD2BIN(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
- tm->tm_mday = BCD2BIN(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
+ tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
+ tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
tm->tm_mon =
- BCD2BIN(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1;
+ bcd2bin(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1;
/* year is 1900 + tm->tm_year */
- tm->tm_year = BCD2BIN(rxbuf[RS5C348_REG_YEAR]) +
+ tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) +
((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0);
if (rtc_valid_tm(tm) < 0) {
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 8b561958fb1..2f2c68d476d 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -148,9 +148,9 @@ static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg)
unsigned hour;
if (rs5c->time24)
- return BCD2BIN(reg & 0x3f);
+ return bcd2bin(reg & 0x3f);
- hour = BCD2BIN(reg & 0x1f);
+ hour = bcd2bin(reg & 0x1f);
if (hour == 12)
hour = 0;
if (reg & 0x20)
@@ -161,15 +161,15 @@ static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg)
static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour)
{
if (rs5c->time24)
- return BIN2BCD(hour);
+ return bin2bcd(hour);
if (hour > 12)
- return 0x20 | BIN2BCD(hour - 12);
+ return 0x20 | bin2bcd(hour - 12);
if (hour == 12)
- return 0x20 | BIN2BCD(12);
+ return 0x20 | bin2bcd(12);
if (hour == 0)
- return BIN2BCD(12);
- return BIN2BCD(hour);
+ return bin2bcd(12);
+ return bin2bcd(hour);
}
static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
@@ -180,18 +180,18 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
if (status < 0)
return status;
- tm->tm_sec = BCD2BIN(rs5c->regs[RS5C372_REG_SECS] & 0x7f);
- tm->tm_min = BCD2BIN(rs5c->regs[RS5C372_REG_MINS] & 0x7f);
+ tm->tm_sec = bcd2bin(rs5c->regs[RS5C372_REG_SECS] & 0x7f);
+ tm->tm_min = bcd2bin(rs5c->regs[RS5C372_REG_MINS] & 0x7f);
tm->tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C372_REG_HOURS]);
- tm->tm_wday = BCD2BIN(rs5c->regs[RS5C372_REG_WDAY] & 0x07);
- tm->tm_mday = BCD2BIN(rs5c->regs[RS5C372_REG_DAY] & 0x3f);
+ tm->tm_wday = bcd2bin(rs5c->regs[RS5C372_REG_WDAY] & 0x07);
+ tm->tm_mday = bcd2bin(rs5c->regs[RS5C372_REG_DAY] & 0x3f);
/* tm->tm_mon is zero-based */
- tm->tm_mon = BCD2BIN(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1;
+ tm->tm_mon = bcd2bin(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1;
/* year is 1900 + tm->tm_year */
- tm->tm_year = BCD2BIN(rs5c->regs[RS5C372_REG_YEAR]) + 100;
+ tm->tm_year = bcd2bin(rs5c->regs[RS5C372_REG_YEAR]) + 100;
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -216,13 +216,13 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
addr = RS5C_ADDR(RS5C372_REG_SECS);
- buf[0] = BIN2BCD(tm->tm_sec);
- buf[1] = BIN2BCD(tm->tm_min);
+ buf[0] = bin2bcd(tm->tm_sec);
+ buf[1] = bin2bcd(tm->tm_min);
buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour);
- buf[3] = BIN2BCD(tm->tm_wday);
- buf[4] = BIN2BCD(tm->tm_mday);
- buf[5] = BIN2BCD(tm->tm_mon + 1);
- buf[6] = BIN2BCD(tm->tm_year - 100);
+ buf[3] = bin2bcd(tm->tm_wday);
+ buf[4] = bin2bcd(tm->tm_mday);
+ buf[5] = bin2bcd(tm->tm_mon + 1);
+ buf[6] = bin2bcd(tm->tm_year - 100);
if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) {
dev_err(&client->dev, "%s: write error\n", __func__);
@@ -367,7 +367,7 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
/* report alarm time */
t->time.tm_sec = 0;
- t->time.tm_min = BCD2BIN(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
+ t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
t->time.tm_mday = -1;
t->time.tm_mon = -1;
@@ -413,7 +413,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
}
/* set alarm */
- buf[0] = BIN2BCD(t->time.tm_min);
+ buf[0] = bin2bcd(t->time.tm_min);
buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
buf[2] = 0x7f; /* any/all days */
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index a6fa1f2f2ca..def4d396d0b 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -104,12 +104,12 @@ static int s35390a_disable_test_mode(struct s35390a *s35390a)
static char s35390a_hr2reg(struct s35390a *s35390a, int hour)
{
if (s35390a->twentyfourhour)
- return BIN2BCD(hour);
+ return bin2bcd(hour);
if (hour < 12)
- return BIN2BCD(hour);
+ return bin2bcd(hour);
- return 0x40 | BIN2BCD(hour - 12);
+ return 0x40 | bin2bcd(hour - 12);
}
static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
@@ -117,9 +117,9 @@ static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
unsigned hour;
if (s35390a->twentyfourhour)
- return BCD2BIN(reg & 0x3f);
+ return bcd2bin(reg & 0x3f);
- hour = BCD2BIN(reg & 0x3f);
+ hour = bcd2bin(reg & 0x3f);
if (reg & 0x40)
hour += 12;
@@ -137,13 +137,13 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_wday);
- buf[S35390A_BYTE_YEAR] = BIN2BCD(tm->tm_year - 100);
- buf[S35390A_BYTE_MONTH] = BIN2BCD(tm->tm_mon + 1);
- buf[S35390A_BYTE_DAY] = BIN2BCD(tm->tm_mday);
- buf[S35390A_BYTE_WDAY] = BIN2BCD(tm->tm_wday);
+ buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100);
+ buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1);
+ buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday);
+ buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday);
buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour);
- buf[S35390A_BYTE_MINS] = BIN2BCD(tm->tm_min);
- buf[S35390A_BYTE_SECS] = BIN2BCD(tm->tm_sec);
+ buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min);
+ buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec);
/* This chip expects the bits of each byte to be in reverse order */
for (i = 0; i < 7; ++i)
@@ -168,13 +168,13 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
for (i = 0; i < 7; ++i)
buf[i] = bitrev8(buf[i]);
- tm->tm_sec = BCD2BIN(buf[S35390A_BYTE_SECS]);
- tm->tm_min = BCD2BIN(buf[S35390A_BYTE_MINS]);
+ tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]);
+ tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]);
tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]);
- tm->tm_wday = BCD2BIN(buf[S35390A_BYTE_WDAY]);
- tm->tm_mday = BCD2BIN(buf[S35390A_BYTE_DAY]);
- tm->tm_mon = BCD2BIN(buf[S35390A_BYTE_MONTH]) - 1;
- tm->tm_year = BCD2BIN(buf[S35390A_BYTE_YEAR]) + 100;
+ tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]);
+ tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]);
+ tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1;
+ tm->tm_year = bcd2bin(buf[S35390A_BYTE_YEAR]) + 100;
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, "
"mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e7d19b6c265..910bc704939 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -134,12 +134,12 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
- BCD_TO_BIN(rtc_tm->tm_sec);
- BCD_TO_BIN(rtc_tm->tm_min);
- BCD_TO_BIN(rtc_tm->tm_hour);
- BCD_TO_BIN(rtc_tm->tm_mday);
- BCD_TO_BIN(rtc_tm->tm_mon);
- BCD_TO_BIN(rtc_tm->tm_year);
+ rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+ rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+ rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
rtc_tm->tm_year += 100;
rtc_tm->tm_mon -= 1;
@@ -163,12 +163,12 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
- writeb(BIN2BCD(tm->tm_sec), base + S3C2410_RTCSEC);
- writeb(BIN2BCD(tm->tm_min), base + S3C2410_RTCMIN);
- writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR);
- writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE);
- writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON);
- writeb(BIN2BCD(year), base + S3C2410_RTCYEAR);
+ writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC);
+ writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN);
+ writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);
+ writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
+ writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
+ writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
return 0;
}
@@ -199,34 +199,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* decode the alarm enable field */
if (alm_en & S3C2410_RTCALM_SECEN)
- BCD_TO_BIN(alm_tm->tm_sec);
+ alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
else
alm_tm->tm_sec = 0xff;
if (alm_en & S3C2410_RTCALM_MINEN)
- BCD_TO_BIN(alm_tm->tm_min);
+ alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
else
alm_tm->tm_min = 0xff;
if (alm_en & S3C2410_RTCALM_HOUREN)
- BCD_TO_BIN(alm_tm->tm_hour);
+ alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
else
alm_tm->tm_hour = 0xff;
if (alm_en & S3C2410_RTCALM_DAYEN)
- BCD_TO_BIN(alm_tm->tm_mday);
+ alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
else
alm_tm->tm_mday = 0xff;
if (alm_en & S3C2410_RTCALM_MONEN) {
- BCD_TO_BIN(alm_tm->tm_mon);
+ alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
alm_tm->tm_mon -= 1;
} else {
alm_tm->tm_mon = 0xff;
}
if (alm_en & S3C2410_RTCALM_YEAREN)
- BCD_TO_BIN(alm_tm->tm_year);
+ alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
else
alm_tm->tm_year = 0xffff;
@@ -250,17 +250,17 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
alrm_en |= S3C2410_RTCALM_SECEN;
- writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC);
+ writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC);
}
if (tm->tm_min < 60 && tm->tm_min >= 0) {
alrm_en |= S3C2410_RTCALM_MINEN;
- writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN);
+ writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN);
}
if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
alrm_en |= S3C2410_RTCALM_HOUREN;
- writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR);
+ writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);
}
pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index fcead4c4cd1..aaf9d6a337c 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -324,23 +324,23 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
sec128 = readb(rtc->regbase + R64CNT);
- tm->tm_sec = BCD2BIN(readb(rtc->regbase + RSECCNT));
- tm->tm_min = BCD2BIN(readb(rtc->regbase + RMINCNT));
- tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT));
- tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT));
- tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT));
- tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1;
+ tm->tm_sec = bcd2bin(readb(rtc->regbase + RSECCNT));
+ tm->tm_min = bcd2bin(readb(rtc->regbase + RMINCNT));
+ tm->tm_hour = bcd2bin(readb(rtc->regbase + RHRCNT));
+ tm->tm_wday = bcd2bin(readb(rtc->regbase + RWKCNT));
+ tm->tm_mday = bcd2bin(readb(rtc->regbase + RDAYCNT));
+ tm->tm_mon = bcd2bin(readb(rtc->regbase + RMONCNT)) - 1;
if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
yr = readw(rtc->regbase + RYRCNT);
- yr100 = BCD2BIN(yr >> 8);
+ yr100 = bcd2bin(yr >> 8);
yr &= 0xff;
} else {
yr = readb(rtc->regbase + RYRCNT);
- yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
+ yr100 = bcd2bin((yr == 0x99) ? 0x19 : 0x20);
}
- tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
+ tm->tm_year = (yr100 * 100 + bcd2bin(yr)) - 1900;
sec2 = readb(rtc->regbase + R64CNT);
cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;
@@ -382,20 +382,20 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
tmp &= ~RCR2_START;
writeb(tmp, rtc->regbase + RCR2);
- writeb(BIN2BCD(tm->tm_sec), rtc->regbase + RSECCNT);
- writeb(BIN2BCD(tm->tm_min), rtc->regbase + RMINCNT);
- writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
- writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
- writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
- writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT);
+ writeb(bin2bcd(tm->tm_sec), rtc->regbase + RSECCNT);
+ writeb(bin2bcd(tm->tm_min), rtc->regbase + RMINCNT);
+ writeb(bin2bcd(tm->tm_hour), rtc->regbase + RHRCNT);
+ writeb(bin2bcd(tm->tm_wday), rtc->regbase + RWKCNT);
+ writeb(bin2bcd(tm->tm_mday), rtc->regbase + RDAYCNT);
+ writeb(bin2bcd(tm->tm_mon + 1), rtc->regbase + RMONCNT);
if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
- year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
- BIN2BCD(tm->tm_year % 100);
+ year = (bin2bcd((tm->tm_year + 1900) / 100) << 8) |
+ bin2bcd(tm->tm_year % 100);
writew(year, rtc->regbase + RYRCNT);
} else {
year = tm->tm_year % 100;
- writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
+ writeb(bin2bcd(year), rtc->regbase + RYRCNT);
}
/* Start RTC */
@@ -417,7 +417,7 @@ static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off)
byte = readb(rtc->regbase + reg_off);
if (byte & AR_ENB) {
byte &= ~AR_ENB; /* strip the enable bit */
- value = BCD2BIN(byte);
+ value = bcd2bin(byte);
}
return value;
@@ -455,7 +455,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
if (value < 0)
writeb(0, rtc->regbase + reg_off);
else
- writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off);
+ writeb(bin2bcd(value) | AR_ENB, rtc->regbase + reg_off);
}
static int sh_rtc_check_alarm(struct rtc_time *tm)
@@ -568,7 +568,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
struct sh_rtc *rtc;
struct resource *res;
unsigned int tmp;
- int ret = -ENOENT;
+ int ret;
rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
if (unlikely(!rtc))
@@ -577,26 +577,33 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
spin_lock_init(&rtc->lock);
/* get periodic/carry/alarm irqs */
- rtc->periodic_irq = platform_get_irq(pdev, 0);
- if (unlikely(rtc->periodic_irq < 0)) {
+ ret = platform_get_irq(pdev, 0);
+ if (unlikely(ret < 0)) {
+ ret = -ENOENT;
dev_err(&pdev->dev, "No IRQ for period\n");
goto err_badres;
}
+ rtc->periodic_irq = ret;
- rtc->carry_irq = platform_get_irq(pdev, 1);
- if (unlikely(rtc->carry_irq < 0)) {
+ ret = platform_get_irq(pdev, 1);
+ if (unlikely(ret < 0)) {
+ ret = -ENOENT;
dev_err(&pdev->dev, "No IRQ for carry\n");
goto err_badres;
}
+ rtc->carry_irq = ret;
- rtc->alarm_irq = platform_get_irq(pdev, 2);
- if (unlikely(rtc->alarm_irq < 0)) {
+ ret = platform_get_irq(pdev, 2);
+ if (unlikely(ret < 0)) {
+ ret = -ENOENT;
dev_err(&pdev->dev, "No IRQ for alarm\n");
goto err_badres;
}
+ rtc->alarm_irq = ret;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (unlikely(res == NULL)) {
+ ret = -ENOENT;
dev_err(&pdev->dev, "No IO resource\n");
goto err_badres;
}
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 9a7e920315f..f4cd46e15af 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -82,14 +82,14 @@ static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
flags = readb(pdata->ioaddr + RTC_FLAGS);
writeb(flags | RTC_WRITE, pdata->ioaddr + RTC_FLAGS);
- writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
- writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
- writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
- writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
- writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
- writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
- writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
- writeb(BIN2BCD((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY);
+ writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
+ writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+ writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+ writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
+ writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
+ writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
+ writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+ writeb(bin2bcd((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY);
writeb(flags & ~RTC_WRITE, pdata->ioaddr + RTC_FLAGS);
return 0;
@@ -120,14 +120,14 @@ static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm)
year = readb(ioaddr + RTC_YEAR);
century = readb(ioaddr + RTC_CENTURY);
writeb(flags & ~RTC_READ, ioaddr + RTC_FLAGS);
- tm->tm_sec = BCD2BIN(second);
- tm->tm_min = BCD2BIN(minute);
- tm->tm_hour = BCD2BIN(hour);
- tm->tm_mday = BCD2BIN(day);
- tm->tm_wday = BCD2BIN(week);
- tm->tm_mon = BCD2BIN(month) - 1;
+ tm->tm_sec = bcd2bin(second);
+ tm->tm_min = bcd2bin(minute);
+ tm->tm_hour = bcd2bin(hour);
+ tm->tm_mday = bcd2bin(day);
+ tm->tm_wday = bcd2bin(week);
+ tm->tm_mon = bcd2bin(month) - 1;
/* year is 1900 + tm->tm_year */
- tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+ tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "retrieved date/time is not valid.\n");
@@ -148,16 +148,16 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata)
writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS);
writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_mday),
+ 0x80 : bin2bcd(pdata->alrm_mday),
ioaddr + RTC_DATE_ALARM);
writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_hour),
+ 0x80 : bin2bcd(pdata->alrm_hour),
ioaddr + RTC_HOURS_ALARM);
writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_min),
+ 0x80 : bin2bcd(pdata->alrm_min),
ioaddr + RTC_MINUTES_ALARM);
writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
- 0x80 : BIN2BCD(pdata->alrm_sec),
+ 0x80 : bin2bcd(pdata->alrm_sec),
ioaddr + RTC_SECONDS_ALARM);
writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS);
readb(ioaddr + RTC_FLAGS); /* clear interrupts */
@@ -280,7 +280,6 @@ static struct bin_attribute stk17ta8_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = RTC_OFFSET,
.read = stk17ta8_nvram_read,
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c
new file mode 100644
index 00000000000..abe87a4d266
--- /dev/null
+++ b/drivers/rtc/rtc-twl4030.c
@@ -0,0 +1,564 @@
+/*
+ * rtc-twl4030.c -- TWL4030 Real Time Clock interface
+ *
+ * Copyright (C) 2007 MontaVista Software, Inc
+ * Author: Alexandre Rusev <source@mvista.com>
+ *
+ * Based on original TI driver twl4030-rtc.c
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * Based on rtc-omap.c
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
+ * Copyright (C) 2006 David Brownell
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include <linux/i2c/twl4030.h>
+
+
+/*
+ * RTC block register offsets (use TWL_MODULE_RTC)
+ */
+#define REG_SECONDS_REG 0x00
+#define REG_MINUTES_REG 0x01
+#define REG_HOURS_REG 0x02
+#define REG_DAYS_REG 0x03
+#define REG_MONTHS_REG 0x04
+#define REG_YEARS_REG 0x05
+#define REG_WEEKS_REG 0x06
+
+#define REG_ALARM_SECONDS_REG 0x07
+#define REG_ALARM_MINUTES_REG 0x08
+#define REG_ALARM_HOURS_REG 0x09
+#define REG_ALARM_DAYS_REG 0x0A
+#define REG_ALARM_MONTHS_REG 0x0B
+#define REG_ALARM_YEARS_REG 0x0C
+
+#define REG_RTC_CTRL_REG 0x0D
+#define REG_RTC_STATUS_REG 0x0E
+#define REG_RTC_INTERRUPTS_REG 0x0F
+
+#define REG_RTC_COMP_LSB_REG 0x10
+#define REG_RTC_COMP_MSB_REG 0x11
+
+/* RTC_CTRL_REG bitfields */
+#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01
+#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02
+#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04
+#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08
+#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10
+#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20
+#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40
+
+/* RTC_STATUS_REG bitfields */
+#define BIT_RTC_STATUS_REG_RUN_M 0x02
+#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04
+#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08
+#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10
+#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20
+#define BIT_RTC_STATUS_REG_ALARM_M 0x40
+#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80
+
+/* RTC_INTERRUPTS_REG bitfields */
+#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03
+#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04
+#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08
+
+
+/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
+#define ALL_TIME_REGS 6
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Supports 1 byte read from TWL4030 RTC register.
+ */
+static int twl4030_rtc_read_u8(u8 *data, u8 reg)
+{
+ int ret;
+
+ ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg);
+ if (ret < 0)
+ pr_err("twl4030_rtc: Could not read TWL4030"
+ "register %X - error %d\n", reg, ret);
+ return ret;
+}
+
+/*
+ * Supports 1 byte write to TWL4030 RTC registers.
+ */
+static int twl4030_rtc_write_u8(u8 data, u8 reg)
+{
+ int ret;
+
+ ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg);
+ if (ret < 0)
+ pr_err("twl4030_rtc: Could not write TWL4030"
+ "register %X - error %d\n", reg, ret);
+ return ret;
+}
+
+/*
+ * Cache the value for timer/alarm interrupts register; this is
+ * only changed by callers holding rtc ops lock (or resume).
+ */
+static unsigned char rtc_irq_bits;
+
+/*
+ * Enable timer and/or alarm interrupts.
+ */
+static int set_rtc_irq_bit(unsigned char bit)
+{
+ unsigned char val;
+ int ret;
+
+ val = rtc_irq_bits | bit;
+ ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
+ if (ret == 0)
+ rtc_irq_bits = val;
+
+ return ret;
+}
+
+/*
+ * Disable timer and/or alarm interrupts.
+ */
+static int mask_rtc_irq_bit(unsigned char bit)
+{
+ unsigned char val;
+ int ret;
+
+ val = rtc_irq_bits & ~bit;
+ ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
+ if (ret == 0)
+ rtc_irq_bits = val;
+
+ return ret;
+}
+
+static inline int twl4030_rtc_alarm_irq_set_state(int enabled)
+{
+ int ret;
+
+ if (enabled)
+ ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+ else
+ ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+
+ return ret;
+}
+
+static inline int twl4030_rtc_irq_set_state(int enabled)
+{
+ int ret;
+
+ if (enabled)
+ ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+ else
+ ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+
+ return ret;
+}
+
+/*
+ * Gets current TWL4030 RTC time and date parameters.
+ *
+ * The RTC's time/alarm representation is not what gmtime(3) requires
+ * Linux to use:
+ *
+ * - Months are 1..12 vs Linux 0-11
+ * - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ */
+static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned char rtc_data[ALL_TIME_REGS + 1];
+ int ret;
+ u8 save_control;
+
+ ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
+ if (ret < 0)
+ return ret;
+
+ save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;
+
+ ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+ if (ret < 0)
+ return ret;
+
+ ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
+ REG_SECONDS_REG, ALL_TIME_REGS);
+
+ if (ret < 0) {
+ dev_err(dev, "rtc_read_time error %d\n", ret);
+ return ret;
+ }
+
+ tm->tm_sec = bcd2bin(rtc_data[0]);
+ tm->tm_min = bcd2bin(rtc_data[1]);
+ tm->tm_hour = bcd2bin(rtc_data[2]);
+ tm->tm_mday = bcd2bin(rtc_data[3]);
+ tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
+ tm->tm_year = bcd2bin(rtc_data[5]) + 100;
+
+ return ret;
+}
+
+static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned char save_control;
+ unsigned char rtc_data[ALL_TIME_REGS + 1];
+ int ret;
+
+ rtc_data[1] = bin2bcd(tm->tm_sec);
+ rtc_data[2] = bin2bcd(tm->tm_min);
+ rtc_data[3] = bin2bcd(tm->tm_hour);
+ rtc_data[4] = bin2bcd(tm->tm_mday);
+ rtc_data[5] = bin2bcd(tm->tm_mon + 1);
+ rtc_data[6] = bin2bcd(tm->tm_year - 100);
+
+ /* Stop RTC while updating the TC registers */
+ ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
+ if (ret < 0)
+ goto out;
+
+ save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
+ twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+ if (ret < 0)
+ goto out;
+
+ /* update all the time registers in one shot */
+ ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data,
+ REG_SECONDS_REG, ALL_TIME_REGS);
+ if (ret < 0) {
+ dev_err(dev, "rtc_set_time error %d\n", ret);
+ goto out;
+ }
+
+ /* Start back RTC */
+ save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
+ ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+
+out:
+ return ret;
+}
+
+/*
+ * Gets current TWL4030 RTC alarm time.
+ */
+static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ unsigned char rtc_data[ALL_TIME_REGS + 1];
+ int ret;
+
+ ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
+ REG_ALARM_SECONDS_REG, ALL_TIME_REGS);
+ if (ret < 0) {
+ dev_err(dev, "rtc_read_alarm error %d\n", ret);
+ return ret;
+ }
+
+ /* some of these fields may be wildcard/"match all" */
+ alm->time.tm_sec = bcd2bin(rtc_data[0]);
+ alm->time.tm_min = bcd2bin(rtc_data[1]);
+ alm->time.tm_hour = bcd2bin(rtc_data[2]);
+ alm->time.tm_mday = bcd2bin(rtc_data[3]);
+ alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1;
+ alm->time.tm_year = bcd2bin(rtc_data[5]) + 100;
+
+ /* report cached alarm enable state */
+ if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
+ alm->enabled = 1;
+
+ return ret;
+}
+
+static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ unsigned char alarm_data[ALL_TIME_REGS + 1];
+ int ret;
+
+ ret = twl4030_rtc_alarm_irq_set_state(0);
+ if (ret)
+ goto out;
+
+ alarm_data[1] = bin2bcd(alm->time.tm_sec);
+ alarm_data[2] = bin2bcd(alm->time.tm_min);
+ alarm_data[3] = bin2bcd(alm->time.tm_hour);
+ alarm_data[4] = bin2bcd(alm->time.tm_mday);
+ alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
+ alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
+
+ /* update all the alarm registers in one shot */
+ ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data,
+ REG_ALARM_SECONDS_REG, ALL_TIME_REGS);
+ if (ret) {
+ dev_err(dev, "rtc_set_alarm error %d\n", ret);
+ goto out;
+ }
+
+ if (alm->enabled)
+ ret = twl4030_rtc_alarm_irq_set_state(1);
+out:
+ return ret;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ return twl4030_rtc_alarm_irq_set_state(0);
+ case RTC_AIE_ON:
+ return twl4030_rtc_alarm_irq_set_state(1);
+ case RTC_UIE_OFF:
+ return twl4030_rtc_irq_set_state(0);
+ case RTC_UIE_ON:
+ return twl4030_rtc_irq_set_state(1);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+#else
+#define omap_rtc_ioctl NULL
+#endif
+
+static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
+{
+ unsigned long events = 0;
+ int ret = IRQ_NONE;
+ int res;
+ u8 rd_reg;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate. Although it might be
+ * friendlier not to borrow this thread context...
+ */
+ local_irq_enable();
+#endif
+
+ res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
+ if (res)
+ goto out;
+ /*
+ * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
+ * only one (ALARM or RTC) interrupt source may be enabled
+ * at time, we also could check our results
+ * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
+ */
+ if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
+ events |= RTC_IRQF | RTC_AF;
+ else
+ events |= RTC_IRQF | RTC_UF;
+
+ res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
+ REG_RTC_STATUS_REG);
+ if (res)
+ goto out;
+
+ /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1
+ * needs 2 reads to clear the interrupt. One read is done in
+ * do_twl4030_pwrirq(). Doing the second read, to clear
+ * the bit.
+ *
+ * FIXME the reason PWR_ISR1 needs an extra read is that
+ * RTC_IF retriggered until we cleared REG_ALARM_M above.
+ * But re-reading like this is a bad hack; by doing so we
+ * risk wrongly clearing status for some other IRQ (losing
+ * the interrupt). Be smarter about handling RTC_UF ...
+ */
+ res = twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &rd_reg, TWL4030_INT_PWR_ISR1);
+ if (res)
+ goto out;
+
+ /* Notify RTC core on event */
+ rtc_update_irq(rtc, 1, events);
+
+ ret = IRQ_HANDLED;
+out:
+ return ret;
+}
+
+static struct rtc_class_ops twl4030_rtc_ops = {
+ .ioctl = twl4030_rtc_ioctl,
+ .read_time = twl4030_rtc_read_time,
+ .set_time = twl4030_rtc_set_time,
+ .read_alarm = twl4030_rtc_read_alarm,
+ .set_alarm = twl4030_rtc_set_alarm,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ int ret = 0;
+ int irq = platform_get_irq(pdev, 0);
+ u8 rd_reg;
+
+ if (irq < 0)
+ return irq;
+
+ rtc = rtc_device_register(pdev->name,
+ &pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
+ PTR_ERR(rtc));
+ goto out0;
+
+ }
+
+ platform_set_drvdata(pdev, rtc);
+
+ ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
+
+ if (ret < 0)
+ goto out1;
+
+ if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M)
+ dev_warn(&pdev->dev, "Power up reset detected.\n");
+
+ if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
+ dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
+
+ /* Clear RTC Power up reset and pending alarm interrupts */
+ ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
+ if (ret < 0)
+ goto out1;
+
+ ret = request_irq(irq, twl4030_rtc_interrupt,
+ IRQF_TRIGGER_RISING,
+ rtc->dev.bus_id, rtc);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "IRQ is not free.\n");
+ goto out1;
+ }
+
+ /* Check RTC module status, Enable if it is off */
+ ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
+ if (ret < 0)
+ goto out2;
+
+ if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
+ dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n");
+ rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
+ ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
+ if (ret < 0)
+ goto out2;
+ }
+
+ /* init cached IRQ enable bits */
+ ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
+ if (ret < 0)
+ goto out2;
+
+ return ret;
+
+
+out2:
+ free_irq(irq, rtc);
+out1:
+ rtc_device_unregister(rtc);
+out0:
+ return ret;
+}
+
+/*
+ * Disable all TWL4030 RTC module interrupts.
+ * Sets status flag to free.
+ */
+static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
+{
+ /* leave rtc running, but disable irqs */
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+
+ mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+ mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+
+ free_irq(irq, rtc);
+
+ rtc_device_unregister(rtc);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static void twl4030_rtc_shutdown(struct platform_device *pdev)
+{
+ mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M |
+ BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+}
+
+#ifdef CONFIG_PM
+
+static unsigned char irqstat;
+
+static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ irqstat = rtc_irq_bits;
+
+ /* REVISIT alarm may need to wake us from sleep */
+ mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M |
+ BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+ return 0;
+}
+
+static int twl4030_rtc_resume(struct platform_device *pdev)
+{
+ set_rtc_irq_bit(irqstat);
+ return 0;
+}
+
+#else
+#define twl4030_rtc_suspend NULL
+#define twl4030_rtc_resume NULL
+#endif
+
+MODULE_ALIAS("platform:twl4030_rtc");
+
+static struct platform_driver twl4030rtc_driver = {
+ .probe = twl4030_rtc_probe,
+ .remove = __devexit_p(twl4030_rtc_remove),
+ .shutdown = twl4030_rtc_shutdown,
+ .suspend = twl4030_rtc_suspend,
+ .resume = twl4030_rtc_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "twl4030_rtc",
+ },
+};
+
+static int __init twl4030_rtc_init(void)
+{
+ return platform_driver_register(&twl4030rtc_driver);
+}
+module_init(twl4030_rtc_init);
+
+static void __exit twl4030_rtc_exit(void)
+{
+ platform_driver_unregister(&twl4030rtc_driver);
+}
+module_exit(twl4030_rtc_exit);
+
+MODULE_AUTHOR("Texas Instruments, MontaVista Software");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index 10025d84026..14d4f036a76 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -92,19 +92,19 @@ static int v3020_read_time(struct device *dev, struct rtc_time *dt)
/* ...and then read constant values. */
tmp = v3020_get_reg(chip, V3020_SECONDS);
- dt->tm_sec = BCD2BIN(tmp);
+ dt->tm_sec = bcd2bin(tmp);
tmp = v3020_get_reg(chip, V3020_MINUTES);
- dt->tm_min = BCD2BIN(tmp);
+ dt->tm_min = bcd2bin(tmp);
tmp = v3020_get_reg(chip, V3020_HOURS);
- dt->tm_hour = BCD2BIN(tmp);
+ dt->tm_hour = bcd2bin(tmp);
tmp = v3020_get_reg(chip, V3020_MONTH_DAY);
- dt->tm_mday = BCD2BIN(tmp);
+ dt->tm_mday = bcd2bin(tmp);
tmp = v3020_get_reg(chip, V3020_MONTH);
- dt->tm_mon = BCD2BIN(tmp) - 1;
+ dt->tm_mon = bcd2bin(tmp) - 1;
tmp = v3020_get_reg(chip, V3020_WEEK_DAY);
- dt->tm_wday = BCD2BIN(tmp);
+ dt->tm_wday = bcd2bin(tmp);
tmp = v3020_get_reg(chip, V3020_YEAR);
- dt->tm_year = BCD2BIN(tmp)+100;
+ dt->tm_year = bcd2bin(tmp)+100;
#ifdef DEBUG
printk("\n%s : Read RTC values\n",__func__);
@@ -136,13 +136,13 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt)
#endif
/* Write all the values to ram... */
- v3020_set_reg(chip, V3020_SECONDS, BIN2BCD(dt->tm_sec));
- v3020_set_reg(chip, V3020_MINUTES, BIN2BCD(dt->tm_min));
- v3020_set_reg(chip, V3020_HOURS, BIN2BCD(dt->tm_hour));
- v3020_set_reg(chip, V3020_MONTH_DAY, BIN2BCD(dt->tm_mday));
- v3020_set_reg(chip, V3020_MONTH, BIN2BCD(dt->tm_mon + 1));
- v3020_set_reg(chip, V3020_WEEK_DAY, BIN2BCD(dt->tm_wday));
- v3020_set_reg(chip, V3020_YEAR, BIN2BCD(dt->tm_year % 100));
+ v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec));
+ v3020_set_reg(chip, V3020_MINUTES, bin2bcd(dt->tm_min));
+ v3020_set_reg(chip, V3020_HOURS, bin2bcd(dt->tm_hour));
+ v3020_set_reg(chip, V3020_MONTH_DAY, bin2bcd(dt->tm_mday));
+ v3020_set_reg(chip, V3020_MONTH, bin2bcd(dt->tm_mon + 1));
+ v3020_set_reg(chip, V3020_WEEK_DAY, bin2bcd(dt->tm_wday));
+ v3020_set_reg(chip, V3020_YEAR, bin2bcd(dt->tm_year % 100));
/* ...and set the clock. */
v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0);
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 884b635f028..834dcc6d785 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -360,7 +360,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
spin_unlock_irq(&rtc_lock);
aie_irq = platform_get_irq(pdev, 0);
- if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+ if (aie_irq < 0 || aie_irq >= nr_irqs) {
retval = -EBUSY;
goto err_device_unregister;
}
@@ -371,7 +371,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
goto err_device_unregister;
pie_irq = platform_get_irq(pdev, 1);
- if (pie_irq < 0 || pie_irq >= NR_IRQS)
+ if (pie_irq < 0 || pie_irq >= nr_irqs)
goto err_free_irq;
retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 7dcfba1bbfe..310c10795e9 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -118,13 +118,13 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
for (i = 0; i <= 4; i++)
buf[i] &= 0x7F;
- tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
- tm->tm_min = BCD2BIN(buf[CCR_MIN]);
- tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
- tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
- tm->tm_year = BCD2BIN(buf[CCR_YEAR])
- + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900;
+ tm->tm_sec = bcd2bin(buf[CCR_SEC]);
+ tm->tm_min = bcd2bin(buf[CCR_MIN]);
+ tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = bcd2bin(buf[CCR_MDAY]);
+ tm->tm_mon = bcd2bin(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
+ tm->tm_year = bcd2bin(buf[CCR_YEAR])
+ + (bcd2bin(buf[CCR_Y2K]) * 100) - 1900;
tm->tm_wday = buf[CCR_WDAY];
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
@@ -174,11 +174,11 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour);
- buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
- buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+ buf[CCR_SEC] = bin2bcd(tm->tm_sec);
+ buf[CCR_MIN] = bin2bcd(tm->tm_min);
/* set hour and 24hr bit */
- buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+ buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
/* should we also set the date? */
if (datetoo) {
@@ -187,15 +187,15 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
__func__,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+ buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
/* month, 1 - 12 */
- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1);
+ buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1);
/* year, since the rtc epoch*/
- buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
+ buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
buf[CCR_WDAY] = tm->tm_wday & 0x07;
- buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
+ buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100);
}
/* If writing alarm registers, set compare bits on registers 0-4 */
@@ -437,7 +437,7 @@ static int x1205_validate_client(struct i2c_client *client)
return -EIO;
}
- value = BCD2BIN(reg & probe_limits_pattern[i].mask);
+ value = bcd2bin(reg & probe_limits_pattern[i].mask);
if (value > probe_limits_pattern[i].max ||
value < probe_limits_pattern[i].min) {
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0a225ccda02..4b76fca64a6 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2011,10 +2011,9 @@ static void dasd_flush_request_queue(struct dasd_block *block)
spin_unlock_irq(&block->request_queue_lock);
}
-static int dasd_open(struct inode *inp, struct file *filp)
+static int dasd_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inp->i_bdev->bd_disk;
- struct dasd_block *block = disk->private_data;
+ struct dasd_block *block = bdev->bd_disk->private_data;
struct dasd_device *base = block->base;
int rc;
@@ -2052,9 +2051,8 @@ unlock:
return rc;
}
-static int dasd_release(struct inode *inp, struct file *filp)
+static int dasd_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inp->i_bdev->bd_disk;
struct dasd_block *block = disk->private_data;
atomic_dec(&block->open_count);
@@ -2089,8 +2087,7 @@ dasd_device_operations = {
.owner = THIS_MODULE,
.open = dasd_open,
.release = dasd_release,
- .ioctl = dasd_ioctl,
- .compat_ioctl = dasd_compat_ioctl,
+ .locked_ioctl = dasd_ioctl,
.getgeo = dasd_getgeo,
};
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index aee6565aaf9..e99d566b69c 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -99,7 +99,7 @@ int dasd_scan_partitions(struct dasd_block *block)
struct block_device *bdev;
bdev = bdget_disk(block->gdp, 0);
- if (!bdev || blkdev_get(bdev, FMODE_READ, 1) < 0)
+ if (!bdev || blkdev_get(bdev, FMODE_READ) < 0)
return -ENODEV;
/*
* See fs/partition/check.c:register_disk,rescan_partitions
@@ -152,7 +152,7 @@ void dasd_destroy_partitions(struct dasd_block *block)
invalidate_partition(block->gdp, 0);
/* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
- blkdev_put(bdev);
+ blkdev_put(bdev, FMODE_READ);
set_capacity(block->gdp, 0);
}
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 489d5fe488f..05a14536c36 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -610,8 +610,7 @@ int dasd_scan_partitions(struct dasd_block *);
void dasd_destroy_partitions(struct dasd_block *);
/* externals in dasd_ioctl.c */
-int dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-long dasd_compat_ioctl(struct file *, unsigned int, unsigned long);
+int dasd_ioctl(struct block_device *, fmode_t, unsigned int, unsigned long);
/* externals in dasd_proc.c */
int dasd_proc_init(void);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 91a64630cb0..b82d816d9ef 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -366,10 +366,9 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
}
int
-dasd_ioctl(struct inode *inode, struct file *file,
+dasd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct dasd_block *block = bdev->bd_disk->private_data;
void __user *argp = (void __user *)arg;
@@ -421,15 +420,3 @@ dasd_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
}
-
-long
-dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int rval;
-
- lock_kernel();
- rval = dasd_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
- unlock_kernel();
-
- return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
-}
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index a7ff167d5b8..63f26a135fe 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -31,8 +31,8 @@
#define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x)
#define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x)
-static int dcssblk_open(struct inode *inode, struct file *filp);
-static int dcssblk_release(struct inode *inode, struct file *filp);
+static int dcssblk_open(struct block_device *bdev, fmode_t mode);
+static int dcssblk_release(struct gendisk *disk, fmode_t mode);
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
void **kaddr, unsigned long *pfn);
@@ -776,32 +776,31 @@ out_buf:
}
static int
-dcssblk_open(struct inode *inode, struct file *filp)
+dcssblk_open(struct block_device *bdev, fmode_t mode)
{
struct dcssblk_dev_info *dev_info;
int rc;
- dev_info = inode->i_bdev->bd_disk->private_data;
+ dev_info = bdev->bd_disk->private_data;
if (NULL == dev_info) {
rc = -ENODEV;
goto out;
}
atomic_inc(&dev_info->use_count);
- inode->i_bdev->bd_block_size = 4096;
+ bdev->bd_block_size = 4096;
rc = 0;
out:
return rc;
}
static int
-dcssblk_release(struct inode *inode, struct file *filp)
+dcssblk_release(struct gendisk *disk, fmode_t mode)
{
- struct dcssblk_dev_info *dev_info;
+ struct dcssblk_dev_info *dev_info = disk->private_data;
struct segment_info *entry;
int rc;
- dev_info = inode->i_bdev->bd_disk->private_data;
- if (NULL == dev_info) {
+ if (!dev_info) {
rc = -ENODEV;
goto out;
}
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index a25b8bf54f4..023803dbb0c 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -43,9 +43,9 @@
/*
* file operation structure for tape block frontend
*/
-static int tapeblock_open(struct inode *, struct file *);
-static int tapeblock_release(struct inode *, struct file *);
-static int tapeblock_ioctl(struct inode *, struct file *, unsigned int,
+static int tapeblock_open(struct block_device *, fmode_t);
+static int tapeblock_release(struct gendisk *, fmode_t);
+static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int,
unsigned long);
static int tapeblock_medium_changed(struct gendisk *);
static int tapeblock_revalidate_disk(struct gendisk *);
@@ -54,7 +54,7 @@ static struct block_device_operations tapeblock_fops = {
.owner = THIS_MODULE,
.open = tapeblock_open,
.release = tapeblock_release,
- .ioctl = tapeblock_ioctl,
+ .locked_ioctl = tapeblock_ioctl,
.media_changed = tapeblock_medium_changed,
.revalidate_disk = tapeblock_revalidate_disk,
};
@@ -364,13 +364,12 @@ tapeblock_medium_changed(struct gendisk *disk)
* Block frontend tape device open function.
*/
static int
-tapeblock_open(struct inode *inode, struct file *filp)
+tapeblock_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk * disk;
+ struct gendisk * disk = bdev->bd_disk;
struct tape_device * device;
int rc;
- disk = inode->i_bdev->bd_disk;
device = tape_get_device_reference(disk->private_data);
if (device->required_tapemarks) {
@@ -410,9 +409,8 @@ release:
* we just get the pointer here and release the reference.
*/
static int
-tapeblock_release(struct inode *inode, struct file *filp)
+tapeblock_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
struct tape_device *device = disk->private_data;
tape_state_set(device, TS_IN_USE);
@@ -427,22 +425,21 @@ tapeblock_release(struct inode *inode, struct file *filp)
*/
static int
tapeblock_ioctl(
- struct inode * inode,
- struct file * file,
+ struct block_device * bdev,
+ fmode_t mode,
unsigned int command,
unsigned long arg
) {
int rc;
int minor;
- struct gendisk *disk;
+ struct gendisk *disk = bdev->bd_disk;
struct tape_device *device;
rc = 0;
- disk = inode->i_bdev->bd_disk;
BUG_ON(!disk);
device = disk->private_data;
BUG_ON(!device);
- minor = iminor(inode);
+ minor = MINOR(bdev->bd_dev);
DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor);
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 326db1e827c..e3fe6838293 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -659,9 +659,9 @@ static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
hr_time = ktime_set(0, poll_timeout);
if (!hrtimer_is_queued(&ap_poll_timer) ||
- !hrtimer_forward(&ap_poll_timer, ap_poll_timer.expires, hr_time)) {
- ap_poll_timer.expires = hr_time;
- hrtimer_start(&ap_poll_timer, hr_time, HRTIMER_MODE_ABS);
+ !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
+ hrtimer_set_expires(&ap_poll_timer, hr_time);
+ hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
}
return count;
}
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index b92c19bb687..5311317c2e4 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1924,12 +1924,9 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
(cmd->sc_data_direction == DMA_FROM_DEVICE ||
cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
if (scsi_sg_count(cmd) == 1) {
- unsigned long flags;
void *buf = tw_dev->generic_buffer_virt[request_id];
- local_irq_save(flags);
scsi_sg_copy_from_buffer(cmd, buf, TW_SECTOR_SIZE);
- local_irq_restore(flags);
}
}
} /* End twa_scsiop_execute_scsi_complete() */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index a0537f09aa2..c03f1d2c9e2 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1466,12 +1466,7 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
void *data, unsigned int len)
{
- struct scsi_cmnd *cmd = tw_dev->srb[request_id];
- unsigned long flags;
-
- local_irq_save(flags);
- scsi_sg_copy_from_buffer(cmd, data, len);
- local_irq_restore(flags);
+ scsi_sg_copy_from_buffer(tw_dev->srb[request_id], data, len);
}
/* This function is called by the isr to complete an inquiry command */
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index b5a868d85eb..1e5478abd90 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -337,7 +337,7 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
#else
#define IRQ_MIN 9
#if defined(__PPC)
-#define IRQ_MAX (NR_IRQS-1)
+#define IRQ_MAX (nr_irqs-1)
#else
#define IRQ_MAX 12
#endif
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index cca16fc5b4a..0666c22ab55 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -80,6 +80,17 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $"
}
/*
+ * Registers marked "dont_generate_debug_code" are not (yet) referenced
+ * from the driver code, and this keyword inhibit generation
+ * of debug code for them.
+ *
+ * REG_PRETTY_PRINT config will complain if dont_generate_debug_code
+ * is added to the register which is referenced in the driver.
+ * Unreferenced register with no dont_generate_debug_code will result
+ * in dead code. No warning is issued.
+ */
+
+/*
* Mode Pointer
* Controls which of the 5, 512byte, address spaces should be used
* as the source and destination of any register accesses in our
@@ -91,6 +102,7 @@ register MODE_PTR {
field DST_MODE 0x70
field SRC_MODE 0x07
mode_pointer
+ dont_generate_debug_code
}
const SRC_MODE_SHIFT 0
@@ -190,6 +202,7 @@ register SEQINTCODE {
SAW_HWERR,
BAD_SCB_STATUS
}
+ dont_generate_debug_code
}
/*
@@ -207,6 +220,7 @@ register CLRINT {
field CLRSEQINT 0x04
field CLRCMDINT 0x02
field CLRSPLTINT 0x01
+ dont_generate_debug_code
}
/*
@@ -222,6 +236,7 @@ register ERROR {
field SQPARERR 0x08
field ILLOPCODE 0x04
field DSCTMOUT 0x02
+ dont_generate_debug_code
}
/*
@@ -255,6 +270,7 @@ register HCNTRL {
field INTEN 0x02
field CHIPRST 0x01
field CHIPRSTACK 0x01
+ dont_generate_debug_code
}
/*
@@ -265,6 +281,7 @@ register HNSCB_QOFF {
access_mode RW
size 2
count 2
+ dont_generate_debug_code
}
/*
@@ -274,6 +291,7 @@ register HESCB_QOFF {
address 0x008
access_mode RW
count 2
+ dont_generate_debug_code
}
/*
@@ -311,6 +329,7 @@ register CLRSEQINTSTAT {
field CLRSEQ_SCSIINT 0x04
field CLRSEQ_PCIINT 0x02
field CLRSEQ_SPLTINT 0x01
+ dont_generate_debug_code
}
/*
@@ -320,6 +339,7 @@ register SWTIMER {
address 0x00E
access_mode RW
size 2
+ dont_generate_debug_code
}
/*
@@ -330,6 +350,7 @@ register SNSCB_QOFF {
access_mode RW
size 2
modes M_CCHAN
+ dont_generate_debug_code
}
/*
@@ -340,6 +361,7 @@ register SESCB_QOFF {
count 2
access_mode RW
modes M_CCHAN
+ dont_generate_debug_code
}
/*
@@ -350,6 +372,7 @@ register SDSCB_QOFF {
access_mode RW
modes M_CCHAN
size 2
+ dont_generate_debug_code
}
/*
@@ -378,6 +401,7 @@ register QOFF_CTLSTA {
SCB_QSIZE_8192,
SCB_QSIZE_16384
}
+ dont_generate_debug_code
}
/*
@@ -431,6 +455,7 @@ register DSCOMMAND0 {
field EXTREQLCK 0x10 /* External Request Lock */
field DISABLE_TWATE 0x02 /* Rev B or greater */
field CIOPARCKEN 0x01 /* Internal bus parity error enable */
+ dont_generate_debug_code
}
/*
@@ -459,6 +484,7 @@ register SG_CACHE_PRE {
field SG_ADDR_MASK 0xf8
field ODD_SEG 0x04
field LAST_SEG 0x02
+ dont_generate_debug_code
}
register SG_CACHE_SHADOW {
@@ -491,6 +517,7 @@ register HADDR {
access_mode RW
size 8
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -522,6 +549,7 @@ register HCNT {
access_mode RW
size 3
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -551,6 +579,7 @@ register SGHADDR {
access_mode RW
size 8
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -561,6 +590,7 @@ register SCBHADDR {
access_mode RW
size 8
modes M_CCHAN
+ dont_generate_debug_code
}
/*
@@ -570,6 +600,7 @@ register SGHCNT {
address 0x084
access_mode RW
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -579,6 +610,7 @@ register SCBHCNT {
address 0x084
access_mode RW
modes M_CCHAN
+ dont_generate_debug_code
}
/*
@@ -609,6 +641,7 @@ register DFF_THRSH {
RD_DFTHRSH_90,
RD_DFTHRSH_MAX
}
+ dont_generate_debug_code
}
/*
@@ -817,6 +850,7 @@ register PCIXCTL {
field SRSPDPEEN 0x04
field TSCSERREN 0x02
field CMPABCDIS 0x01
+ dont_generate_debug_code
}
/*
@@ -863,6 +897,7 @@ register DCHSPLTSTAT0 {
field RXOVRUN 0x04
field RXSCEMSG 0x02
field RXSPLTRSP 0x01
+ dont_generate_debug_code
}
/*
@@ -908,6 +943,7 @@ register DCHSPLTSTAT1 {
modes M_DFF0, M_DFF1
count 2
field RXDATABUCKET 0x01
+ dont_generate_debug_code
}
/*
@@ -1069,6 +1105,7 @@ register SGSPLTSTAT0 {
field RXOVRUN 0x04
field RXSCEMSG 0x02
field RXSPLTRSP 0x01
+ dont_generate_debug_code
}
/*
@@ -1080,6 +1117,7 @@ register SGSPLTSTAT1 {
modes M_DFF0, M_DFF1
count 2
field RXDATABUCKET 0x01
+ dont_generate_debug_code
}
/*
@@ -1091,6 +1129,7 @@ register SFUNCT {
modes M_CFG
field TEST_GROUP 0xF0
field TEST_NUM 0x0F
+ dont_generate_debug_code
}
/*
@@ -1109,6 +1148,7 @@ register DF0PCISTAT {
field RDPERR 0x04
field TWATERR 0x02
field DPR 0x01
+ dont_generate_debug_code
}
/*
@@ -1204,6 +1244,7 @@ register TARGPCISTAT {
field SSE 0x40
field STA 0x08
field TWATERR 0x02
+ dont_generate_debug_code
}
/*
@@ -1216,6 +1257,7 @@ register LQIN {
size 20
count 2
modes M_DFF0, M_DFF1, M_SCSI
+ dont_generate_debug_code
}
/*
@@ -1247,6 +1289,7 @@ register LUNPTR {
access_mode RW
modes M_CFG
count 2
+ dont_generate_debug_code
}
/*
@@ -1278,6 +1321,7 @@ register CMDLENPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1290,6 +1334,7 @@ register ATTRPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1302,6 +1347,7 @@ register FLAGPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1313,6 +1359,7 @@ register CMDPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1324,6 +1371,7 @@ register QNEXTPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1347,6 +1395,7 @@ register ABRTBYTEPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1358,6 +1407,7 @@ register ABRTBITPTR {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1398,6 +1448,7 @@ register LUNLEN {
count 2
mask ILUNLEN 0x0F
mask TLUNLEN 0xF0
+ dont_generate_debug_code
}
const LUNLEN_SINGLE_LEVEL_LUN 0xF
@@ -1410,6 +1461,7 @@ register CDBLIMIT {
access_mode RW
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -1422,6 +1474,7 @@ register MAXCMD {
access_mode RW
modes M_CFG
count 9
+ dont_generate_debug_code
}
/*
@@ -1432,6 +1485,7 @@ register MAXCMDCNT {
address 0x033
access_mode RW
modes M_CFG
+ dont_generate_debug_code
}
/*
@@ -1490,6 +1544,7 @@ register LQCTL1 {
field PCI2PCI 0x04
field SINGLECMD 0x02
field ABORTPENDING 0x01
+ dont_generate_debug_code
}
/*
@@ -1508,6 +1563,7 @@ register LQCTL2 {
field LQOCONTINUE 0x04
field LQOTOIDLE 0x02
field LQOPAUSE 0x01
+ dont_generate_debug_code
}
/*
@@ -1578,6 +1634,7 @@ register SXFRCTL0 {
field DFPEXP 0x40
field BIOSCANCELEN 0x10
field SPIOEN 0x08
+ dont_generate_debug_code
}
/*
@@ -1594,6 +1651,7 @@ register SXFRCTL1 {
field ENSTIMER 0x04
field ACTNEGEN 0x02
field STPWEN 0x01
+ dont_generate_debug_code
}
/*
@@ -1696,6 +1754,7 @@ register SCSISIGO {
P_STATUS CDO|IOO,
P_MESGIN CDO|IOO|MSGO
}
+ dont_generate_debug_code
}
/*
@@ -1738,6 +1797,7 @@ register MULTARGID {
modes M_CFG
size 2
count 2
+ dont_generate_debug_code
}
/*
@@ -1774,6 +1834,7 @@ register SCSIDAT {
access_mode RW
modes M_DFF0, M_DFF1, M_SCSI
size 2
+ dont_generate_debug_code
}
/*
@@ -1796,6 +1857,7 @@ register TARGIDIN {
count 2
field CLKOUT 0x80
field TARGID 0x0F
+ dont_generate_debug_code
}
/*
@@ -1825,6 +1887,7 @@ register SBLKCTL {
field ENAB40 0x08 /* LVD transceiver active */
field ENAB20 0x04 /* SE/HVD transceiver active */
field SELWIDE 0x02
+ dont_generate_debug_code
}
/*
@@ -1842,6 +1905,7 @@ register OPTIONMODE {
field ENDGFORMCHK 0x04
field AUTO_MSGOUT_DE 0x02
mask OPTIONMODE_DEFAULTS AUTO_MSGOUT_DE
+ dont_generate_debug_code
}
/*
@@ -1876,6 +1940,7 @@ register CLRSINT0 {
field CLROVERRUN 0x04
field CLRSPIORDY 0x02
field CLRARBDO 0x01
+ dont_generate_debug_code
}
/*
@@ -1929,6 +1994,7 @@ register CLRSINT1 {
field CLRSCSIPERR 0x04
field CLRSTRB2FAST 0x02
field CLRREQINIT 0x01
+ dont_generate_debug_code
}
/*
@@ -1962,6 +2028,7 @@ register CLRSINT2 {
field CLRWIDE_RES 0x04 /* Modes 0 and 1 only */
field CLRSDONE 0x02 /* Modes 0 and 1 only */
field CLRDMADONE 0x01 /* Modes 0 and 1 only */
+ dont_generate_debug_code
}
/*
@@ -2002,6 +2069,7 @@ register LQISTATE {
access_mode RO
modes M_CFG
count 6
+ dont_generate_debug_code
}
/*
@@ -2022,6 +2090,7 @@ register LQOSTATE {
access_mode RO
modes M_CFG
count 2
+ dont_generate_debug_code
}
/*
@@ -2054,6 +2123,7 @@ register CLRLQIINT0 {
field CLRLQIBADLQT 0x04
field CLRLQIATNLQ 0x02
field CLRLQIATNCMD 0x01
+ dont_generate_debug_code
}
/*
@@ -2070,6 +2140,7 @@ register LQIMODE0 {
field ENLQIBADLQT 0x04
field ENLQIATNLQ 0x02
field ENLQIATNCMD 0x01
+ dont_generate_debug_code
}
/*
@@ -2106,6 +2177,7 @@ register CLRLQIINT1 {
field CLRLQIBADLQI 0x04
field CLRLQIOVERI_LQ 0x02
field CLRLQIOVERI_NLQ 0x01
+ dont_generate_debug_code
}
/*
@@ -2124,6 +2196,7 @@ register LQIMODE1 {
field ENLQIBADLQI 0x04
field ENLQIOVERI_LQ 0x02 /* LQIOVERI1 */
field ENLQIOVERI_NLQ 0x01 /* LQIOVERI2 */
+ dont_generate_debug_code
}
/*
@@ -2165,6 +2238,7 @@ register CLRSINT3 {
count 3
field CLRNTRAMPERR 0x02
field CLROSRAMPERR 0x01
+ dont_generate_debug_code
}
/*
@@ -2177,6 +2251,7 @@ register SIMODE3 {
count 4
field ENNTRAMPERR 0x02
field ENOSRAMPERR 0x01
+ dont_generate_debug_code
}
/*
@@ -2207,6 +2282,7 @@ register CLRLQOINT0 {
field CLRLQOATNLQ 0x04
field CLRLQOATNPKT 0x02
field CLRLQOTCRC 0x01
+ dont_generate_debug_code
}
/*
@@ -2222,6 +2298,7 @@ register LQOMODE0 {
field ENLQOATNLQ 0x04
field ENLQOATNPKT 0x02
field ENLQOTCRC 0x01
+ dont_generate_debug_code
}
/*
@@ -2251,6 +2328,7 @@ register CLRLQOINT1 {
field CLRLQOBADQAS 0x04
field CLRLQOBUSFREE 0x02
field CLRLQOPHACHGINPKT 0x01
+ dont_generate_debug_code
}
/*
@@ -2266,6 +2344,7 @@ register LQOMODE1 {
field ENLQOBADQAS 0x04
field ENLQOBUSFREE 0x02
field ENLQOPHACHGINPKT 0x01
+ dont_generate_debug_code
}
/*
@@ -2289,6 +2368,7 @@ register OS_SPACE_CNT {
access_mode RO
modes M_CFG
count 2
+ dont_generate_debug_code
}
/*
@@ -2318,6 +2398,7 @@ register GSFIFO {
access_mode RO
size 2
modes M_DFF0, M_DFF1, M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2341,6 +2422,7 @@ register NEXTSCB {
access_mode RW
size 2
modes M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2357,6 +2439,7 @@ register LQOSCSCTL {
field LQOBUSETDLY 0x40
field LQONOHOLDLACK 0x02
field LQONOCHKOVER 0x01
+ dont_generate_debug_code
}
/*
@@ -2389,6 +2472,7 @@ register CLRSEQINTSRC {
field CLRCFG4TSTAT 0x04
field CLRCFG4ICMD 0x02
field CLRCFG4TCMD 0x01
+ dont_generate_debug_code
}
/*
@@ -2415,6 +2499,7 @@ register CURRSCB {
access_mode RW
size 2
modes M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2472,6 +2557,7 @@ register LASTSCB {
access_mode RW
size 2
modes M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2494,6 +2580,7 @@ register SHADDR {
access_mode RO
size 8
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -2513,6 +2600,7 @@ register NEGOADDR {
address 0x060
access_mode RW
modes M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2523,6 +2611,7 @@ register NEGPERIOD {
access_mode RW
modes M_SCSI
count 1
+ dont_generate_debug_code
}
/*
@@ -2543,6 +2632,7 @@ register NEGOFFSET {
access_mode RW
modes M_SCSI
count 1
+ dont_generate_debug_code
}
/*
@@ -2557,6 +2647,7 @@ register NEGPPROPTS {
field PPROPT_QAS 0x04
field PPROPT_DT 0x02
field PPROPT_IUT 0x01
+ dont_generate_debug_code
}
/*
@@ -2573,6 +2664,7 @@ register NEGCONOPTS {
field ENAUTOATNI 0x04
field ENAUTOATNO 0x02
field WIDEXFER 0x01
+ dont_generate_debug_code
}
/*
@@ -2583,6 +2675,7 @@ register ANNEXCOL {
access_mode RW
modes M_SCSI
count 7
+ dont_generate_debug_code
}
/*
@@ -2602,6 +2695,7 @@ register SCSCHKN {
field DFFACTCLR 0x04
field SHVALIDSTDIS 0x02
field LSTSGCLRDIS 0x01
+ dont_generate_debug_code
}
const AHD_ANNEXCOL_PER_DEV0 4
@@ -2635,6 +2729,7 @@ register ANNEXDAT {
access_mode RW
modes M_SCSI
count 3
+ dont_generate_debug_code
}
/*
@@ -2645,6 +2740,7 @@ register IOWNID {
address 0x067
access_mode RW
modes M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2671,6 +2767,7 @@ register TOWNID {
access_mode RW
modes M_SCSI
count 2
+ dont_generate_debug_code
}
/*
@@ -2702,6 +2799,7 @@ register SHCNT {
access_mode RW
size 3
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -2789,6 +2887,7 @@ register SCBPTR {
access_mode RW
size 2
modes M_DFF0, M_DFF1, M_CCHAN, M_SCSI
+ dont_generate_debug_code
}
/*
@@ -2816,6 +2915,7 @@ register SCBAUTOPTR {
field AUSCBPTR_EN 0x80
field SCBPTR_ADDR 0x38
field SCBPTR_OFF 0x07
+ dont_generate_debug_code
}
/*
@@ -2825,6 +2925,7 @@ register CCSGADDR {
address 0x0AC
access_mode RW
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -2834,6 +2935,7 @@ register CCSCBADDR {
address 0x0AC
access_mode RW
modes M_CCHAN
+ dont_generate_debug_code
}
/*
@@ -2899,6 +3001,7 @@ register CCSGRAM {
address 0x0B0
access_mode RW
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -2908,6 +3011,7 @@ register CCSCBRAM {
address 0x0B0
access_mode RW
modes M_CCHAN
+ dont_generate_debug_code
}
/*
@@ -2958,6 +3062,7 @@ register BRDDAT {
access_mode RW
modes M_SCSI
count 2
+ dont_generate_debug_code
}
/*
@@ -2974,6 +3079,7 @@ register BRDCTL {
field BRDEN 0x04
field BRDRW 0x02
field BRDSTB 0x01
+ dont_generate_debug_code
}
/*
@@ -2984,6 +3090,7 @@ register SEEADR {
access_mode RW
modes M_SCSI
count 4
+ dont_generate_debug_code
}
/*
@@ -2995,6 +3102,7 @@ register SEEDAT {
size 2
modes M_SCSI
count 4
+ dont_generate_debug_code
}
/*
@@ -3011,6 +3119,7 @@ register SEESTAT {
field SEEARBACK 0x04
field SEEBUSY 0x02
field SEESTART 0x01
+ dont_generate_debug_code
}
/*
@@ -3036,6 +3145,7 @@ register SEECTL {
mask SEEOP_EWDS 0x40
field SEERST 0x02
field SEESTART 0x01
+ dont_generate_debug_code
}
const SEEOP_ERAL_ADDR 0x80
@@ -3050,6 +3160,7 @@ register SCBCNT {
address 0x0BF
access_mode RW
modes M_SCSI
+ dont_generate_debug_code
}
/*
@@ -3061,6 +3172,7 @@ register DFWADDR {
access_mode RW
size 2
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -3087,6 +3199,7 @@ register DSPDATACTL {
field DESQDIS 0x10
field RCVROFFSTDIS 0x04
field XMITOFFSTDIS 0x02
+ dont_generate_debug_code
}
/*
@@ -3132,6 +3245,7 @@ register DFDAT {
address 0x0C4
access_mode RW
modes M_DFF0, M_DFF1
+ dont_generate_debug_code
}
/*
@@ -3144,6 +3258,7 @@ register DSPSELECT {
count 1
field AUTOINCEN 0x80
field DSPSEL 0x1F
+ dont_generate_debug_code
}
const NUMDSPS 0x14
@@ -3158,6 +3273,7 @@ register WRTBIASCTL {
count 3
field AUTOXBCDIS 0x80
field XMITMANVAL 0x3F
+ dont_generate_debug_code
}
/*
@@ -3316,6 +3432,7 @@ register FLAGS {
count 23
field ZERO 0x02
field CARRY 0x01
+ dont_generate_debug_code
}
/*
@@ -3344,6 +3461,7 @@ register SEQRAM {
address 0x0DA
access_mode RW
count 2
+ dont_generate_debug_code
}
/*
@@ -3355,6 +3473,7 @@ register PRGMCNT {
access_mode RW
size 2
count 5
+ dont_generate_debug_code
}
/*
@@ -3364,6 +3483,7 @@ register ACCUM {
address 0x0E0
access_mode RW
accumulator
+ dont_generate_debug_code
}
/*
@@ -3380,6 +3500,7 @@ register SINDEX {
access_mode RW
size 2
sindex
+ dont_generate_debug_code
}
/*
@@ -3390,6 +3511,7 @@ register DINDEX {
address 0x0E4
access_mode RW
size 2
+ dont_generate_debug_code
}
/*
@@ -3415,6 +3537,7 @@ register ALLONES {
address 0x0E8
access_mode RO
allones
+ dont_generate_debug_code
}
/*
@@ -3425,6 +3548,7 @@ register ALLZEROS {
address 0x0EA
access_mode RO
allzeros
+ dont_generate_debug_code
}
/*
@@ -3435,6 +3559,7 @@ register NONE {
address 0x0EA
access_mode WO
none
+ dont_generate_debug_code
}
/*
@@ -3445,6 +3570,7 @@ register NONE {
register SINDIR {
address 0x0EC
access_mode RO
+ dont_generate_debug_code
}
/*
@@ -3455,6 +3581,7 @@ register SINDIR {
register DINDIR {
address 0x0ED
access_mode WO
+ dont_generate_debug_code
}
/*
@@ -3479,6 +3606,7 @@ register FUNCTION1 {
register STACK {
address 0x0F2
access_mode RW
+ dont_generate_debug_code
}
/*
@@ -3491,6 +3619,7 @@ register INTVEC1_ADDR {
size 2
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -3503,6 +3632,7 @@ register CURADDR {
size 2
modes M_SCSI
count 2
+ dont_generate_debug_code
}
/*
@@ -3515,6 +3645,7 @@ register INTVEC2_ADDR {
size 2
modes M_CFG
count 1
+ dont_generate_debug_code
}
/*
@@ -3543,12 +3674,14 @@ scratch_ram {
modes 0, 1, 2, 3
REG0 {
size 2
+ dont_generate_debug_code
}
REG1 {
size 2
}
REG_ISR {
size 2
+ dont_generate_debug_code
}
SG_STATE {
size 1
@@ -3572,9 +3705,11 @@ scratch_ram {
modes 0, 1, 2, 3
LONGJMP_ADDR {
size 2
+ dont_generate_debug_code
}
ACCUM_SAVE {
size 1
+ dont_generate_debug_code
}
}
@@ -3591,18 +3726,22 @@ scratch_ram {
*/
WAITING_SCB_TAILS {
size 32
+ dont_generate_debug_code
}
WAITING_TID_HEAD {
size 2
+ dont_generate_debug_code
}
WAITING_TID_TAIL {
size 2
+ dont_generate_debug_code
}
/*
* SCBID of the next SCB in the new SCB queue.
*/
NEXT_QUEUED_SCB_ADDR {
size 4
+ dont_generate_debug_code
}
/*
* head of list of SCBs that have
@@ -3611,6 +3750,7 @@ scratch_ram {
*/
COMPLETE_SCB_HEAD {
size 2
+ dont_generate_debug_code
}
/*
* The list of completed SCBs in
@@ -3618,6 +3758,7 @@ scratch_ram {
*/
COMPLETE_SCB_DMAINPROG_HEAD {
size 2
+ dont_generate_debug_code
}
/*
* head of list of SCBs that have
@@ -3626,6 +3767,7 @@ scratch_ram {
*/
COMPLETE_DMA_SCB_HEAD {
size 2
+ dont_generate_debug_code
}
/*
* tail of list of SCBs that have
@@ -3634,6 +3776,7 @@ scratch_ram {
*/
COMPLETE_DMA_SCB_TAIL {
size 2
+ dont_generate_debug_code
}
/*
* head of list of SCBs that have
@@ -3643,6 +3786,7 @@ scratch_ram {
*/
COMPLETE_ON_QFREEZE_HEAD {
size 2
+ dont_generate_debug_code
}
/*
* Counting semaphore to prevent new select-outs
@@ -3667,6 +3811,7 @@ scratch_ram {
*/
MSG_OUT {
size 1
+ dont_generate_debug_code
}
/* Parameters for DMA Logic */
DMAPARAMS {
@@ -3682,6 +3827,7 @@ scratch_ram {
field DIRECTION 0x04 /* Set indicates PCI->SCSI */
field FIFOFLUSH 0x02
field FIFORESET 0x01
+ dont_generate_debug_code
}
SEQ_FLAGS {
size 1
@@ -3703,9 +3849,11 @@ scratch_ram {
*/
SAVED_SCSIID {
size 1
+ dont_generate_debug_code
}
SAVED_LUN {
size 1
+ dont_generate_debug_code
}
/*
* The last bus phase as seen by the sequencer.
@@ -3733,6 +3881,7 @@ scratch_ram {
*/
QOUTFIFO_ENTRY_VALID_TAG {
size 1
+ dont_generate_debug_code
}
/*
* Kernel and sequencer offsets into the queue of
@@ -3742,10 +3891,12 @@ scratch_ram {
KERNEL_TQINPOS {
size 1
count 1
+ dont_generate_debug_code
}
TQINPOS {
size 1
count 8
+ dont_generate_debug_code
}
/*
* Base address of our shared data with the kernel driver in host
@@ -3754,6 +3905,7 @@ scratch_ram {
*/
SHARED_DATA_ADDR {
size 4
+ dont_generate_debug_code
}
/*
* Pointer to location in host memory for next
@@ -3761,6 +3913,7 @@ scratch_ram {
*/
QOUTFIFO_NEXT_ADDR {
size 4
+ dont_generate_debug_code
}
ARG_1 {
size 1
@@ -3773,11 +3926,13 @@ scratch_ram {
mask CONT_MSG_LOOP_READ 0x03
mask CONT_MSG_LOOP_TARG 0x02
alias RETURN_1
+ dont_generate_debug_code
}
ARG_2 {
size 1
count 1
alias RETURN_2
+ dont_generate_debug_code
}
/*
@@ -3785,6 +3940,7 @@ scratch_ram {
*/
LAST_MSG {
size 1
+ dont_generate_debug_code
}
/*
@@ -3801,6 +3957,7 @@ scratch_ram {
field MANUALP 0x0C
field ENAUTOATNP 0x02
field ALTSTIM 0x01
+ dont_generate_debug_code
}
/*
@@ -3809,6 +3966,7 @@ scratch_ram {
INITIATOR_TAG {
size 1
count 1
+ dont_generate_debug_code
}
SEQ_FLAGS2 {
@@ -3820,6 +3978,7 @@ scratch_ram {
ALLOCFIFO_SCBPTR {
size 2
+ dont_generate_debug_code
}
/*
@@ -3829,6 +3988,7 @@ scratch_ram {
*/
INT_COALESCING_TIMER {
size 2
+ dont_generate_debug_code
}
/*
@@ -3838,6 +3998,7 @@ scratch_ram {
*/
INT_COALESCING_MAXCMDS {
size 1
+ dont_generate_debug_code
}
/*
@@ -3846,6 +4007,7 @@ scratch_ram {
*/
INT_COALESCING_MINCMDS {
size 1
+ dont_generate_debug_code
}
/*
@@ -3853,6 +4015,7 @@ scratch_ram {
*/
CMDS_PENDING {
size 2
+ dont_generate_debug_code
}
/*
@@ -3860,6 +4023,7 @@ scratch_ram {
*/
INT_COALESCING_CMDCOUNT {
size 1
+ dont_generate_debug_code
}
/*
@@ -3868,6 +4032,7 @@ scratch_ram {
*/
LOCAL_HS_MAILBOX {
size 1
+ dont_generate_debug_code
}
/*
* Target-mode CDB type to CDB length table used
@@ -3876,6 +4041,7 @@ scratch_ram {
CMDSIZE_TABLE {
size 8
count 8
+ dont_generate_debug_code
}
/*
* When an SCB with the MK_MESSAGE flag is
@@ -3908,25 +4074,31 @@ scb {
size 4
alias SCB_CDB_STORE
alias SCB_HOST_CDB_PTR
+ dont_generate_debug_code
}
SCB_RESIDUAL_SGPTR {
size 4
field SG_ADDR_MASK 0xf8 /* In the last byte */
field SG_OVERRUN_RESID 0x02 /* In the first byte */
field SG_LIST_NULL 0x01 /* In the first byte */
+ dont_generate_debug_code
}
SCB_SCSI_STATUS {
size 1
alias SCB_HOST_CDB_LEN
+ dont_generate_debug_code
}
SCB_TARGET_PHASES {
size 1
+ dont_generate_debug_code
}
SCB_TARGET_DATA_DIR {
size 1
+ dont_generate_debug_code
}
SCB_TARGET_ITAG {
size 1
+ dont_generate_debug_code
}
SCB_SENSE_BUSADDR {
/*
@@ -3936,10 +4108,12 @@ scb {
*/
size 4
alias SCB_NEXT_COMPLETE
+ dont_generate_debug_code
}
SCB_TAG {
alias SCB_FIFO_USE_COUNT
size 2
+ dont_generate_debug_code
}
SCB_CONTROL {
size 1
@@ -3959,6 +4133,7 @@ scb {
SCB_LUN {
size 1
field LID 0xff
+ dont_generate_debug_code
}
SCB_TASK_ATTRIBUTE {
size 1
@@ -3967,16 +4142,20 @@ scb {
* ignore wide residue message handling.
*/
field SCB_XFERLEN_ODD 0x01
+ dont_generate_debug_code
}
SCB_CDB_LEN {
size 1
field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */
+ dont_generate_debug_code
}
SCB_TASK_MANAGEMENT {
size 1
+ dont_generate_debug_code
}
SCB_DATAPTR {
size 8
+ dont_generate_debug_code
}
SCB_DATACNT {
/*
@@ -3986,22 +4165,27 @@ scb {
size 4
field SG_LAST_SEG 0x80 /* In the fourth byte */
field SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */
+ dont_generate_debug_code
}
SCB_SGPTR {
size 4
field SG_STATUS_VALID 0x04 /* In the first byte */
field SG_FULL_RESID 0x02 /* In the first byte */
field SG_LIST_NULL 0x01 /* In the first byte */
+ dont_generate_debug_code
}
SCB_BUSADDR {
size 4
+ dont_generate_debug_code
}
SCB_NEXT {
alias SCB_NEXT_SCB_BUSADDR
size 2
+ dont_generate_debug_code
}
SCB_NEXT2 {
size 2
+ dont_generate_debug_code
}
SCB_SPARE {
size 8
@@ -4009,6 +4193,7 @@ scb {
}
SCB_DISCONNECTED_LISTS {
size 8
+ dont_generate_debug_code
}
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 55508b0fcec..bdad54ec088 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -2472,8 +2472,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
ahd_outb(ahd, CLRLQOINT1, 0);
} else if ((status & SELTO) != 0) {
- u_int scbid;
-
/* Stop the selection */
ahd_outb(ahd, SCSISEQ0, 0);
@@ -2583,9 +2581,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
case BUSFREE_DFF0:
case BUSFREE_DFF1:
{
- u_int scbid;
- struct scb *scb;
-
mode = busfreetime == BUSFREE_DFF0
? AHD_MODE_DFF0 : AHD_MODE_DFF1;
ahd_set_modes(ahd, mode, mode);
@@ -3689,7 +3684,7 @@ ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force)
* by the capabilities of the bus connectivity of and sync settings for
* the target.
*/
-void
+static void
ahd_devlimited_syncrate(struct ahd_softc *ahd,
struct ahd_initiator_tinfo *tinfo,
u_int *period, u_int *ppr_options, role_t role)
@@ -4136,7 +4131,7 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
/*
* Harpoon2A assumed that there would be a
- * fallback rate between 160MHz and 80Mhz,
+ * fallback rate between 160MHz and 80MHz,
* so 7 is used as the period factor rather
* than 8 for 160MHz.
*/
@@ -8708,7 +8703,7 @@ ahd_reset_current_bus(struct ahd_softc *ahd)
int
ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
{
- struct ahd_devinfo devinfo;
+ struct ahd_devinfo caminfo;
u_int initiator;
u_int target;
u_int max_scsiid;
@@ -8729,7 +8724,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
ahd->pending_device = NULL;
- ahd_compile_devinfo(&devinfo,
+ ahd_compile_devinfo(&caminfo,
CAM_TARGET_WILDCARD,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD,
@@ -8868,7 +8863,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
}
/* Notify the XPT that a bus reset occurred */
- ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
+ ahd_send_async(ahd, caminfo.channel, CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD, AC_BUS_RESET);
ahd_restart(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index c25b6adffbf..a734d77e880 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -223,10 +223,10 @@ static const char *pci_bus_modes[] =
"PCI bus mode unknown",
"PCI bus mode unknown",
"PCI bus mode unknown",
- "PCI-X 101-133Mhz",
- "PCI-X 67-100Mhz",
- "PCI-X 50-66Mhz",
- "PCI 33 or 66Mhz"
+ "PCI-X 101-133MHz",
+ "PCI-X 67-100MHz",
+ "PCI-X 50-66MHz",
+ "PCI 33 or 66MHz"
};
#define TESTMODE 0x00000800ul
@@ -337,8 +337,6 @@ ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
* 64bit bus (PCI64BIT set in devconfig).
*/
if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {
- uint32_t devconfig;
-
if (bootverbose)
printf("%s: Enabling 39Bit Addressing\n",
ahd_name(ahd));
@@ -483,8 +481,6 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
goto fail;
if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
- u_int targpcistat;
-
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
targpcistat = ahd_inb(ahd, TARGPCISTAT);
if ((targpcistat & STA) != 0)
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index c21ceab8e91..cdcead071ef 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -34,13 +34,6 @@ ahd_reg_print_t ahd_seqintcode_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrint_print;
-#else
-#define ahd_clrint_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRINT", 0x03, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_error_print;
#else
#define ahd_error_print(regvalue, cur_col, wrap) \
@@ -48,20 +41,6 @@ ahd_reg_print_t ahd_error_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_hcntrl_print;
-#else
-#define ahd_hcntrl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "HCNTRL", 0x05, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_hnscb_qoff_print;
-#else
-#define ahd_hnscb_qoff_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "HNSCB_QOFF", 0x06, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_hescb_qoff_print;
#else
#define ahd_hescb_qoff_print(regvalue, cur_col, wrap) \
@@ -97,13 +76,6 @@ ahd_reg_print_t ahd_swtimer_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_snscb_qoff_print;
-#else
-#define ahd_snscb_qoff_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SNSCB_QOFF", 0x10, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_sescb_qoff_print;
#else
#define ahd_sescb_qoff_print(regvalue, cur_col, wrap) \
@@ -111,20 +83,6 @@ ahd_reg_print_t ahd_sescb_qoff_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sdscb_qoff_print;
-#else
-#define ahd_sdscb_qoff_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SDSCB_QOFF", 0x14, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_qoff_ctlsta_print;
-#else
-#define ahd_qoff_ctlsta_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QOFF_CTLSTA", 0x16, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_intctl_print;
#else
#define ahd_intctl_print(regvalue, cur_col, wrap) \
@@ -139,13 +97,6 @@ ahd_reg_print_t ahd_dfcntrl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dscommand0_print;
-#else
-#define ahd_dscommand0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DSCOMMAND0", 0x19, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dfstatus_print;
#else
#define ahd_dfstatus_print(regvalue, cur_col, wrap) \
@@ -160,13 +111,6 @@ ahd_reg_print_t ahd_sg_cache_shadow_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sg_cache_pre_print;
-#else
-#define ahd_sg_cache_pre_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SG_CACHE_PRE", 0x1b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqin_print;
#else
#define ahd_lqin_print(regvalue, cur_col, wrap) \
@@ -293,13 +237,6 @@ ahd_reg_print_t ahd_sxfrctl0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sxfrctl1_print;
-#else
-#define ahd_sxfrctl1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SXFRCTL1", 0x3d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dffstat_print;
#else
#define ahd_dffstat_print(regvalue, cur_col, wrap) \
@@ -314,13 +251,6 @@ ahd_reg_print_t ahd_multargid_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scsisigo_print;
-#else
-#define ahd_scsisigo_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCSISIGO", 0x40, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scsisigi_print;
#else
#define ahd_scsisigi_print(regvalue, cur_col, wrap) \
@@ -363,13 +293,6 @@ ahd_reg_print_t ahd_selid_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_optionmode_print;
-#else
-#define ahd_optionmode_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OPTIONMODE", 0x4a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_sblkctl_print;
#else
#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
@@ -391,13 +314,6 @@ ahd_reg_print_t ahd_simode0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint0_print;
-#else
-#define ahd_clrsint0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRSINT0", 0x4b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_sstat1_print;
#else
#define ahd_sstat1_print(regvalue, cur_col, wrap) \
@@ -405,13 +321,6 @@ ahd_reg_print_t ahd_sstat1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint1_print;
-#else
-#define ahd_clrsint1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRSINT1", 0x4c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_sstat2_print;
#else
#define ahd_sstat2_print(regvalue, cur_col, wrap) \
@@ -461,17 +370,17 @@ ahd_reg_print_t ahd_lqistat0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqimode0_print;
+ahd_reg_print_t ahd_clrlqiint0_print;
#else
-#define ahd_lqimode0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LQIMODE0", 0x50, regvalue, cur_col, wrap)
+#define ahd_clrlqiint0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CLRLQIINT0", 0x50, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrlqiint0_print;
+ahd_reg_print_t ahd_lqimode0_print;
#else
-#define ahd_clrlqiint0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRLQIINT0", 0x50, regvalue, cur_col, wrap)
+#define ahd_lqimode0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "LQIMODE0", 0x50, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -629,17 +538,17 @@ ahd_reg_print_t ahd_seqintsrc_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_seqimode_print;
+ahd_reg_print_t ahd_currscb_print;
#else
-#define ahd_seqimode_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQIMODE", 0x5c, regvalue, cur_col, wrap)
+#define ahd_currscb_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CURRSCB", 0x5c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_currscb_print;
+ahd_reg_print_t ahd_seqimode_print;
#else
-#define ahd_currscb_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CURRSCB", 0x5c, regvalue, cur_col, wrap)
+#define ahd_seqimode_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SEQIMODE", 0x5c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -657,13 +566,6 @@ ahd_reg_print_t ahd_lastscb_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_shaddr_print;
-#else
-#define ahd_shaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SHADDR", 0x60, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_negoaddr_print;
#else
#define ahd_negoaddr_print(regvalue, cur_col, wrap) \
@@ -748,27 +650,6 @@ ahd_reg_print_t ahd_seloid_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_haddr_print;
-#else
-#define ahd_haddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "HADDR", 0x70, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_hcnt_print;
-#else
-#define ahd_hcnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "HCNT", 0x78, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghaddr_print;
-#else
-#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scbhaddr_print;
#else
#define ahd_scbhaddr_print(regvalue, cur_col, wrap) \
@@ -776,10 +657,10 @@ ahd_reg_print_t ahd_scbhaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghcnt_print;
+ahd_reg_print_t ahd_sghaddr_print;
#else
-#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -790,10 +671,10 @@ ahd_reg_print_t ahd_scbhcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dff_thrsh_print;
+ahd_reg_print_t ahd_sghcnt_print;
#else
-#define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DFF_THRSH", 0x88, regvalue, cur_col, wrap)
+#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -867,13 +748,6 @@ ahd_reg_print_t ahd_targpcistat_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scbptr_print;
-#else
-#define ahd_scbptr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCBPTR", 0xa8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scbautoptr_print;
#else
#define ahd_scbautoptr_print(regvalue, cur_col, wrap) \
@@ -881,13 +755,6 @@ ahd_reg_print_t ahd_scbautoptr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccsgaddr_print;
-#else
-#define ahd_ccsgaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSGADDR", 0xac, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_ccscbaddr_print;
#else
#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
@@ -909,13 +776,6 @@ ahd_reg_print_t ahd_ccsgctl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccsgram_print;
-#else
-#define ahd_ccsgram_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSGRAM", 0xb0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_ccscbram_print;
#else
#define ahd_ccscbram_print(regvalue, cur_col, wrap) \
@@ -930,13 +790,6 @@ ahd_reg_print_t ahd_brddat_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brdctl_print;
-#else
-#define ahd_brdctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BRDCTL", 0xb9, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seeadr_print;
#else
#define ahd_seeadr_print(regvalue, cur_col, wrap) \
@@ -972,13 +825,6 @@ ahd_reg_print_t ahd_dspdatactl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfdat_print;
-#else
-#define ahd_dfdat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DFDAT", 0xc4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dspselect_print;
#else
#define ahd_dspselect_print(regvalue, cur_col, wrap) \
@@ -1000,13 +846,6 @@ ahd_reg_print_t ahd_seqctl0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_flags_print;
-#else
-#define ahd_flags_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "FLAGS", 0xd8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seqintctl_print;
#else
#define ahd_seqintctl_print(regvalue, cur_col, wrap) \
@@ -1014,13 +853,6 @@ ahd_reg_print_t ahd_seqintctl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_seqram_print;
-#else
-#define ahd_seqram_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQRAM", 0xda, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_prgmcnt_print;
#else
#define ahd_prgmcnt_print(regvalue, cur_col, wrap) \
@@ -1028,41 +860,6 @@ ahd_reg_print_t ahd_prgmcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_accum_print;
-#else
-#define ahd_accum_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ACCUM", 0xe0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sindex_print;
-#else
-#define ahd_sindex_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SINDEX", 0xe2, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dindex_print;
-#else
-#define ahd_dindex_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DINDEX", 0xe4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_allones_print;
-#else
-#define ahd_allones_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ALLONES", 0xe8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_allzeros_print;
-#else
-#define ahd_allzeros_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ALLZEROS", 0xea, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_none_print;
#else
#define ahd_none_print(regvalue, cur_col, wrap) \
@@ -1070,27 +867,6 @@ ahd_reg_print_t ahd_none_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sindir_print;
-#else
-#define ahd_sindir_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SINDIR", 0xec, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dindir_print;
-#else
-#define ahd_dindir_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DINDIR", 0xed, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_stack_print;
-#else
-#define ahd_stack_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "STACK", 0xf2, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_intvec1_addr_print;
#else
#define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \
@@ -1126,17 +902,17 @@ ahd_reg_print_t ahd_accum_save_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sram_base_print;
+ahd_reg_print_t ahd_waiting_scb_tails_print;
#else
-#define ahd_sram_base_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SRAM_BASE", 0x100, regvalue, cur_col, wrap)
+#define ahd_waiting_scb_tails_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "WAITING_SCB_TAILS", 0x100, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_waiting_scb_tails_print;
+ahd_reg_print_t ahd_sram_base_print;
#else
-#define ahd_waiting_scb_tails_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "WAITING_SCB_TAILS", 0x100, regvalue, cur_col, wrap)
+#define ahd_sram_base_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SRAM_BASE", 0x100, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1224,13 +1000,6 @@ ahd_reg_print_t ahd_msg_out_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dmaparams_print;
-#else
-#define ahd_dmaparams_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seq_flags_print;
#else
#define ahd_seq_flags_print(regvalue, cur_col, wrap) \
@@ -1238,20 +1007,6 @@ ahd_reg_print_t ahd_seq_flags_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_saved_scsiid_print;
-#else
-#define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_saved_lun_print;
-#else
-#define ahd_saved_lun_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lastphase_print;
#else
#define ahd_lastphase_print(regvalue, cur_col, wrap) \
@@ -1273,20 +1028,6 @@ ahd_reg_print_t ahd_kernel_tqinpos_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_tqinpos_print;
-#else
-#define ahd_tqinpos_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_shared_data_addr_print;
-#else
-#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_qoutfifo_next_addr_print;
#else
#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
@@ -1294,20 +1035,6 @@ ahd_reg_print_t ahd_qoutfifo_next_addr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_arg_1_print;
-#else
-#define ahd_arg_1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_arg_2_print;
-#else
-#define ahd_arg_2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_last_msg_print;
#else
#define ahd_last_msg_print(regvalue, cur_col, wrap) \
@@ -1406,13 +1133,6 @@ ahd_reg_print_t ahd_mk_message_scsiid_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_residual_datacnt_print;
-#else
-#define ahd_scb_residual_datacnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT", 0x180, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_base_print;
#else
#define ahd_scb_base_print(regvalue, cur_col, wrap) \
@@ -1420,17 +1140,10 @@ ahd_reg_print_t ahd_scb_base_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_residual_sgptr_print;
-#else
-#define ahd_scb_residual_sgptr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCB_RESIDUAL_SGPTR", 0x184, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_scsi_status_print;
+ahd_reg_print_t ahd_scb_residual_datacnt_print;
#else
-#define ahd_scb_scsi_status_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCB_SCSI_STATUS", 0x188, regvalue, cur_col, wrap)
+#define ahd_scb_residual_datacnt_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT", 0x180, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1476,13 +1189,6 @@ ahd_reg_print_t ahd_scb_task_attribute_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_cdb_len_print;
-#else
-#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x196, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_task_management_print;
#else
#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
@@ -1518,13 +1224,6 @@ ahd_reg_print_t ahd_scb_busaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_next_print;
-#else
-#define ahd_scb_next_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCB_NEXT", 0x1ac, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_next2_print;
#else
#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
@@ -1717,10 +1416,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SG_CACHE_PRE 0x1b
-#define TYPEPTR 0x20
-
#define LQIN 0x20
+#define TYPEPTR 0x20
+
#define TAGPTR 0x21
#define LUNPTR 0x22
@@ -1780,6 +1479,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SINGLECMD 0x02
#define ABORTPENDING 0x01
+#define SCSBIST0 0x39
+#define GSBISTERR 0x40
+#define GSBISTDONE 0x20
+#define GSBISTRUN 0x10
+#define OSBISTERR 0x04
+#define OSBISTDONE 0x02
+#define OSBISTRUN 0x01
+
#define LQCTL2 0x39
#define LQIRETRY 0x80
#define LQICONTINUE 0x40
@@ -1790,13 +1497,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define LQOTOIDLE 0x02
#define LQOPAUSE 0x01
-#define SCSBIST0 0x39
-#define GSBISTERR 0x40
-#define GSBISTDONE 0x20
-#define GSBISTRUN 0x10
-#define OSBISTERR 0x04
-#define OSBISTDONE 0x02
-#define OSBISTRUN 0x01
+#define SCSBIST1 0x3a
+#define NTBISTERR 0x04
+#define NTBISTDONE 0x02
+#define NTBISTRUN 0x01
#define SCSISEQ0 0x3a
#define TEMODEO 0x80
@@ -1805,15 +1509,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define FORCEBUSFREE 0x10
#define SCSIRSTO 0x01
-#define SCSBIST1 0x3a
-#define NTBISTERR 0x04
-#define NTBISTDONE 0x02
-#define NTBISTRUN 0x01
-
#define SCSISEQ1 0x3b
-#define BUSINITID 0x3c
-
#define SXFRCTL0 0x3c
#define DFON 0x80
#define DFPEXP 0x40
@@ -1822,6 +1519,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DLCOUNT 0x3c
+#define BUSINITID 0x3c
+
#define SXFRCTL1 0x3d
#define BITBUCKET 0x80
#define ENSACHK 0x40
@@ -1846,8 +1545,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CURRFIFO_1 0x01
#define CURRFIFO_0 0x00
-#define MULTARGID 0x40
-
#define SCSISIGO 0x40
#define CDO 0x80
#define IOO 0x40
@@ -1858,6 +1555,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define REQO 0x02
#define ACKO 0x01
+#define MULTARGID 0x40
+
#define SCSISIGI 0x41
#define ATNI 0x10
#define SELI 0x08
@@ -1904,6 +1603,15 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENAB20 0x04
#define SELWIDE 0x02
+#define CLRSINT0 0x4b
+#define CLRSELDO 0x40
+#define CLRSELDI 0x20
+#define CLRSELINGO 0x10
+#define CLRIOERR 0x08
+#define CLROVERRUN 0x04
+#define CLRSPIORDY 0x02
+#define CLRARBDO 0x01
+
#define SSTAT0 0x4b
#define TARGET 0x80
#define SELDO 0x40
@@ -1923,14 +1631,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENSPIORDY 0x02
#define ENARBDO 0x01
-#define CLRSINT0 0x4b
-#define CLRSELDO 0x40
-#define CLRSELDI 0x20
-#define CLRSELINGO 0x10
-#define CLRIOERR 0x08
-#define CLROVERRUN 0x04
-#define CLRSPIORDY 0x02
-#define CLRARBDO 0x01
+#define CLRSINT1 0x4c
+#define CLRSELTIMEO 0x80
+#define CLRATNO 0x40
+#define CLRSCSIRSTI 0x20
+#define CLRBUSFREE 0x08
+#define CLRSCSIPERR 0x04
+#define CLRSTRB2FAST 0x02
+#define CLRREQINIT 0x01
#define SSTAT1 0x4c
#define SELTO 0x80
@@ -1942,15 +1650,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define STRB2FAST 0x02
#define REQINIT 0x01
-#define CLRSINT1 0x4c
-#define CLRSELTIMEO 0x80
-#define CLRATNO 0x40
-#define CLRSCSIRSTI 0x20
-#define CLRBUSFREE 0x08
-#define CLRSCSIPERR 0x04
-#define CLRSTRB2FAST 0x02
-#define CLRREQINIT 0x01
-
#define SSTAT2 0x4d
#define BUSFREETIME 0xc0
#define NONPACKREQ 0x20
@@ -1998,14 +1697,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define LQIATNLQ 0x02
#define LQIATNCMD 0x01
-#define LQIMODE0 0x50
-#define ENLQIATNQASK 0x20
-#define ENLQICRCT1 0x10
-#define ENLQICRCT2 0x08
-#define ENLQIBADLQT 0x04
-#define ENLQIATNLQ 0x02
-#define ENLQIATNCMD 0x01
-
#define CLRLQIINT0 0x50
#define CLRLQIATNQAS 0x20
#define CLRLQICRCT1 0x10
@@ -2014,6 +1705,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRLQIATNLQ 0x02
#define CLRLQIATNCMD 0x01
+#define LQIMODE0 0x50
+#define ENLQIATNQASK 0x20
+#define ENLQICRCT1 0x10
+#define ENLQICRCT2 0x08
+#define ENLQIBADLQT 0x04
+#define ENLQIATNLQ 0x02
+#define ENLQIATNCMD 0x01
+
#define LQIMODE1 0x51
#define ENLQIPHASE_LQ 0x80
#define ENLQIPHASE_NLQ 0x40
@@ -2160,6 +1859,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CFG4ICMD 0x02
#define CFG4TCMD 0x01
+#define CURRSCB 0x5c
+
#define SEQIMODE 0x5c
#define ENCTXTDONE 0x40
#define ENSAVEPTRS 0x20
@@ -2169,8 +1870,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENCFG4ICMD 0x02
#define ENCFG4TCMD 0x01
-#define CURRSCB 0x5c
-
#define MDFFSTAT 0x5d
#define SHCNTNEGATIVE 0x40
#define SHCNTMINUS1 0x20
@@ -2185,29 +1884,29 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DFFTAG 0x5e
+#define LASTSCB 0x5e
+
#define SCSITEST 0x5e
#define CNTRTEST 0x08
#define SEL_TXPLL_DEBUG 0x04
-#define LASTSCB 0x5e
-
#define IOPDNCTL 0x5f
#define DISABLE_OE 0x80
#define PDN_IDIST 0x04
#define PDN_DIFFSENSE 0x01
-#define DGRPCRCI 0x60
-
#define SHADDR 0x60
#define NEGOADDR 0x60
-#define NEGPERIOD 0x61
+#define DGRPCRCI 0x60
-#define NEGOFFSET 0x62
+#define NEGPERIOD 0x61
#define PACKCRCI 0x62
+#define NEGOFFSET 0x62
+
#define NEGPPROPTS 0x63
#define PPROPT_PACE 0x08
#define PPROPT_QAS 0x04
@@ -2253,8 +1952,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SELOID 0x6b
-#define FAIRNESS 0x6c
-
#define PLL400CTL0 0x6c
#define PLL_VCOSEL 0x80
#define PLL_PWDN 0x40
@@ -2264,6 +1961,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define PLL_DLPF 0x02
#define PLL_ENFBM 0x01
+#define FAIRNESS 0x6c
+
#define PLL400CTL1 0x6d
#define PLL_CNTEN 0x80
#define PLL_CNTCLR 0x40
@@ -2275,25 +1974,25 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define HADDR 0x70
-#define HODMAADR 0x70
-
#define PLLDELAY 0x70
#define SPLIT_DROP_REQ 0x80
-#define HCNT 0x78
+#define HODMAADR 0x70
#define HODMACNT 0x78
-#define HODMAEN 0x7a
+#define HCNT 0x78
-#define SGHADDR 0x7c
+#define HODMAEN 0x7a
#define SCBHADDR 0x7c
-#define SGHCNT 0x84
+#define SGHADDR 0x7c
#define SCBHCNT 0x84
+#define SGHCNT 0x84
+
#define DFF_THRSH 0x88
#define WR_DFTHRSH 0x70
#define RD_DFTHRSH 0x07
@@ -2326,10 +2025,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CMCRXMSG0 0x90
-#define OVLYRXMSG0 0x90
-
-#define DCHRXMSG0 0x90
-
#define ROENABLE 0x90
#define MSIROEN 0x20
#define OVLYROEN 0x10
@@ -2338,11 +2033,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DCH1ROEN 0x02
#define DCH0ROEN 0x01
-#define OVLYRXMSG1 0x91
+#define OVLYRXMSG0 0x90
-#define CMCRXMSG1 0x91
+#define DCHRXMSG0 0x90
-#define DCHRXMSG1 0x91
+#define OVLYRXMSG1 0x91
#define NSENABLE 0x91
#define MSINSEN 0x20
@@ -2352,6 +2047,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DCH1NSEN 0x02
#define DCH0NSEN 0x01
+#define CMCRXMSG1 0x91
+
+#define DCHRXMSG1 0x91
+
#define DCHRXMSG2 0x92
#define CMCRXMSG2 0x92
@@ -2375,24 +2074,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define TSCSERREN 0x02
#define CMPABCDIS 0x01
-#define CMCSEQBCNT 0x94
-
#define OVLYSEQBCNT 0x94
#define DCHSEQBCNT 0x94
+#define CMCSEQBCNT 0x94
+
+#define CMCSPLTSTAT0 0x96
+
#define DCHSPLTSTAT0 0x96
#define OVLYSPLTSTAT0 0x96
-#define CMCSPLTSTAT0 0x96
+#define CMCSPLTSTAT1 0x97
#define OVLYSPLTSTAT1 0x97
#define DCHSPLTSTAT1 0x97
-#define CMCSPLTSTAT1 0x97
-
#define SGRXMSG0 0x98
#define CDNUM 0xf8
#define CFNUM 0x07
@@ -2420,15 +2119,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define TAG_NUM 0x1f
#define RLXORD 0x10
+#define SGSEQBCNT 0x9c
+
#define SLVSPLTOUTATTR0 0x9c
#define LOWER_BCNT 0xff
-#define SGSEQBCNT 0x9c
-
#define SLVSPLTOUTATTR1 0x9d
#define CMPLT_DNUM 0xf8
#define CMPLT_FNUM 0x07
+#define SLVSPLTOUTATTR2 0x9e
+#define CMPLT_BNUM 0xff
+
#define SGSPLTSTAT0 0x9e
#define STAETERM 0x80
#define SCBCERR 0x40
@@ -2439,9 +2141,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define RXSCEMSG 0x02
#define RXSPLTRSP 0x01
-#define SLVSPLTOUTATTR2 0x9e
-#define CMPLT_BNUM 0xff
-
#define SGSPLTSTAT1 0x9f
#define RXDATABUCKET 0x01
@@ -2497,10 +2196,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CCSGADDR 0xac
-#define CCSCBADDR 0xac
-
#define CCSCBADR_BK 0xac
+#define CCSCBADDR 0xac
+
#define CMC_RAMBIST 0xad
#define SG_ELEMENT_SIZE 0x80
#define SCBRAMBIST_FAIL 0x40
@@ -2554,9 +2253,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SEEDAT 0xbc
#define SEECTL 0xbe
-#define SEEOP_EWDS 0x40
#define SEEOP_WALL 0x40
#define SEEOP_EWEN 0x40
+#define SEEOP_EWDS 0x40
#define SEEOPCODE 0x70
#define SEERST 0x02
#define SEESTART 0x01
@@ -2573,25 +2272,25 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCBCNT 0xbf
+#define DFWADDR 0xc0
+
#define DSPFLTRCTL 0xc0
#define FLTRDISABLE 0x20
#define EDGESENSE 0x10
#define DSPFCNTSEL 0x0f
-#define DFWADDR 0xc0
-
#define DSPDATACTL 0xc1
#define BYPASSENAB 0x80
#define DESQDIS 0x10
#define RCVROFFSTDIS 0x04
#define XMITOFFSTDIS 0x02
+#define DFRADDR 0xc2
+
#define DSPREQCTL 0xc2
#define MANREQCTL 0xc0
#define MANREQDLY 0x3f
-#define DFRADDR 0xc2
-
#define DSPACKCTL 0xc3
#define MANACKCTL 0xc0
#define MANACKDLY 0x3f
@@ -2612,14 +2311,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define WRTBIASCALC 0xc7
-#define DFPTRS 0xc8
-
#define RCVRBIASCALC 0xc8
-#define DFBKPTR 0xc9
+#define DFPTRS 0xc8
#define SKEWCALC 0xc9
+#define DFBKPTR 0xc9
+
#define DFDBCTL 0xcb
#define DFF_CIO_WR_RDY 0x20
#define DFF_CIO_RD_RDY 0x10
@@ -2704,12 +2403,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ACCUM_SAVE 0xfa
+#define WAITING_SCB_TAILS 0x100
+
#define AHD_PCI_CONFIG_BASE 0x100
#define SRAM_BASE 0x100
-#define WAITING_SCB_TAILS 0x100
-
#define WAITING_TID_HEAD 0x120
#define WAITING_TID_TAIL 0x122
@@ -2738,8 +2437,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define PRELOADEN 0x80
#define WIDEODD 0x40
#define SCSIEN 0x20
-#define SDMAENACK 0x10
#define SDMAEN 0x10
+#define SDMAENACK 0x10
#define HDMAEN 0x08
#define HDMAENACK 0x08
#define DIRECTION 0x04
@@ -2837,12 +2536,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define MK_MESSAGE_SCSIID 0x162
+#define SCB_BASE 0x180
+
#define SCB_RESIDUAL_DATACNT 0x180
#define SCB_CDB_STORE 0x180
#define SCB_HOST_CDB_PTR 0x180
-#define SCB_BASE 0x180
-
#define SCB_RESIDUAL_SGPTR 0x184
#define SG_ADDR_MASK 0xf8
#define SG_OVERRUN_RESID 0x02
@@ -2910,17 +2609,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_DISCONNECTED_LISTS 0x1b8
-#define CMD_GROUP_CODE_SHIFT 0x05
-#define STIMESEL_MIN 0x18
-#define STIMESEL_SHIFT 0x03
-#define INVALID_ADDR 0x80
-#define AHD_PRECOMP_MASK 0x07
-#define TARGET_DATA_IN 0x01
-#define CCSCBADDR_MAX 0x80
-#define NUMDSPS 0x14
-#define SEEOP_EWEN_ADDR 0xc0
-#define AHD_ANNEXCOL_PER_DEV0 0x04
-#define DST_MODE_SHIFT 0x04
#define AHD_TIMER_MAX_US 0x18ffe7
#define AHD_TIMER_MAX_TICKS 0xffff
#define AHD_SENSE_BUFSIZE 0x100
@@ -2955,32 +2643,43 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define LUNLEN_SINGLE_LEVEL_LUN 0x0f
#define NVRAM_SCB_OFFSET 0x2c
#define STATUS_PKT_SENSE 0xff
+#define CMD_GROUP_CODE_SHIFT 0x05
#define MAX_OFFSET_PACED_BUG 0x7f
#define STIMESEL_BUG_ADJ 0x08
+#define STIMESEL_MIN 0x18
+#define STIMESEL_SHIFT 0x03
#define CCSGRAM_MAXSEGS 0x10
+#define INVALID_ADDR 0x80
#define SEEOP_ERAL_ADDR 0x80
#define AHD_SLEWRATE_DEF_REVB 0x08
#define AHD_PRECOMP_CUTBACK_17 0x04
+#define AHD_PRECOMP_MASK 0x07
#define SRC_MODE_SHIFT 0x00
#define PKT_OVERRUN_BUFSIZE 0x200
#define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30
+#define TARGET_DATA_IN 0x01
#define HOST_MSG 0xff
#define MAX_OFFSET 0xfe
#define BUS_16_BIT 0x01
+#define CCSCBADDR_MAX 0x80
+#define NUMDSPS 0x14
+#define SEEOP_EWEN_ADDR 0xc0
+#define AHD_ANNEXCOL_PER_DEV0 0x04
+#define DST_MODE_SHIFT 0x04
/* Downloaded Constant Definitions */
-#define SG_SIZEOF 0x04
-#define SG_PREFETCH_ALIGN_MASK 0x02
-#define SG_PREFETCH_CNT_LIMIT 0x01
#define CACHELINE_MASK 0x07
#define SCB_TRANSFER_SIZE 0x06
#define PKT_OVERRUN_BUFOFFSET 0x05
+#define SG_SIZEOF 0x04
#define SG_PREFETCH_ADDR_MASK 0x03
+#define SG_PREFETCH_ALIGN_MASK 0x02
+#define SG_PREFETCH_CNT_LIMIT 0x01
#define SG_PREFETCH_CNT 0x00
#define DOWNLOAD_CONST_COUNT 0x08
/* Exported Labels */
-#define LABEL_timer_isr 0x28b
#define LABEL_seq_isr 0x28f
+#define LABEL_timer_isr 0x28b
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index c4c8a96bf5a..f5ea715d6ac 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
@@ -8,18 +8,6 @@
#include "aic79xx_osm.h"
-static const ahd_reg_parse_entry_t MODE_PTR_parse_table[] = {
- { "SRC_MODE", 0x07, 0x07 },
- { "DST_MODE", 0x70, 0x70 }
-};
-
-int
-ahd_mode_ptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(MODE_PTR_parse_table, 2, "MODE_PTR",
- 0x00, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t INTSTAT_parse_table[] = {
{ "SPLTINT", 0x01, 0x01 },
{ "CMDCMPLT", 0x02, 0x02 },
@@ -39,110 +27,6 @@ ahd_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x01, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
- { "NO_SEQINT", 0x00, 0xff },
- { "BAD_PHASE", 0x01, 0xff },
- { "SEND_REJECT", 0x02, 0xff },
- { "PROTO_VIOLATION", 0x03, 0xff },
- { "NO_MATCH", 0x04, 0xff },
- { "IGN_WIDE_RES", 0x05, 0xff },
- { "PDATA_REINIT", 0x06, 0xff },
- { "HOST_MSG_LOOP", 0x07, 0xff },
- { "BAD_STATUS", 0x08, 0xff },
- { "DATA_OVERRUN", 0x09, 0xff },
- { "MKMSG_FAILED", 0x0a, 0xff },
- { "MISSED_BUSFREE", 0x0b, 0xff },
- { "DUMP_CARD_STATE", 0x0c, 0xff },
- { "ILLEGAL_PHASE", 0x0d, 0xff },
- { "INVALID_SEQINT", 0x0e, 0xff },
- { "CFG4ISTAT_INTR", 0x0f, 0xff },
- { "STATUS_OVERRUN", 0x10, 0xff },
- { "CFG4OVERRUN", 0x11, 0xff },
- { "ENTERING_NONPACK", 0x12, 0xff },
- { "TASKMGMT_FUNC_COMPLETE",0x13, 0xff },
- { "TASKMGMT_CMD_CMPLT_OKAY",0x14, 0xff },
- { "TRACEPOINT0", 0x15, 0xff },
- { "TRACEPOINT1", 0x16, 0xff },
- { "TRACEPOINT2", 0x17, 0xff },
- { "TRACEPOINT3", 0x18, 0xff },
- { "SAW_HWERR", 0x19, 0xff },
- { "BAD_SCB_STATUS", 0x1a, 0xff }
-};
-
-int
-ahd_seqintcode_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SEQINTCODE_parse_table, 27, "SEQINTCODE",
- 0x02, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t CLRINT_parse_table[] = {
- { "CLRSPLTINT", 0x01, 0x01 },
- { "CLRCMDINT", 0x02, 0x02 },
- { "CLRSEQINT", 0x04, 0x04 },
- { "CLRSCSIINT", 0x08, 0x08 },
- { "CLRPCIINT", 0x10, 0x10 },
- { "CLRSWTMINT", 0x20, 0x20 },
- { "CLRBRKADRINT", 0x40, 0x40 },
- { "CLRHWERRINT", 0x80, 0x80 }
-};
-
-int
-ahd_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRINT_parse_table, 8, "CLRINT",
- 0x03, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t ERROR_parse_table[] = {
- { "DSCTMOUT", 0x02, 0x02 },
- { "ILLOPCODE", 0x04, 0x04 },
- { "SQPARERR", 0x08, 0x08 },
- { "DPARERR", 0x10, 0x10 },
- { "MPARERR", 0x20, 0x20 },
- { "CIOACCESFAIL", 0x40, 0x40 },
- { "CIOPARERR", 0x80, 0x80 }
-};
-
-int
-ahd_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(ERROR_parse_table, 7, "ERROR",
- 0x04, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t HCNTRL_parse_table[] = {
- { "CHIPRST", 0x01, 0x01 },
- { "CHIPRSTACK", 0x01, 0x01 },
- { "INTEN", 0x02, 0x02 },
- { "PAUSE", 0x04, 0x04 },
- { "SWTIMER_START_B", 0x08, 0x08 },
- { "SWINT", 0x10, 0x10 },
- { "POWRDN", 0x40, 0x40 },
- { "SEQ_RESET", 0x80, 0x80 }
-};
-
-int
-ahd_hcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(HCNTRL_parse_table, 8, "HCNTRL",
- 0x05, regvalue, cur_col, wrap));
-}
-
-int
-ahd_hnscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "HNSCB_QOFF",
- 0x06, regvalue, cur_col, wrap));
-}
-
-int
-ahd_hescb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "HESCB_QOFF",
- 0x08, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
{ "ENINT_COALESCE", 0x40, 0x40 },
{ "HOST_TQINPOS", 0x80, 0x80 }
@@ -170,77 +54,6 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0c, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
- { "CLRSEQ_SPLTINT", 0x01, 0x01 },
- { "CLRSEQ_PCIINT", 0x02, 0x02 },
- { "CLRSEQ_SCSIINT", 0x04, 0x04 },
- { "CLRSEQ_SEQINT", 0x08, 0x08 },
- { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
-};
-
-int
-ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
- 0x0c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SWTIMER",
- 0x0e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_snscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SNSCB_QOFF",
- 0x10, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sescb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SESCB_QOFF",
- 0x12, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SDSCB_QOFF",
- 0x14, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
- { "SCB_QSIZE_4", 0x00, 0x0f },
- { "SCB_QSIZE_8", 0x01, 0x0f },
- { "SCB_QSIZE_16", 0x02, 0x0f },
- { "SCB_QSIZE_32", 0x03, 0x0f },
- { "SCB_QSIZE_64", 0x04, 0x0f },
- { "SCB_QSIZE_128", 0x05, 0x0f },
- { "SCB_QSIZE_256", 0x06, 0x0f },
- { "SCB_QSIZE_512", 0x07, 0x0f },
- { "SCB_QSIZE_1024", 0x08, 0x0f },
- { "SCB_QSIZE_2048", 0x09, 0x0f },
- { "SCB_QSIZE_4096", 0x0a, 0x0f },
- { "SCB_QSIZE_8192", 0x0b, 0x0f },
- { "SCB_QSIZE_16384", 0x0c, 0x0f },
- { "SCB_QSIZE", 0x0f, 0x0f },
- { "HS_MAILBOX_ACT", 0x10, 0x10 },
- { "SDSCB_ROLLOVR", 0x20, 0x20 },
- { "NEW_SCB_AVAIL", 0x40, 0x40 },
- { "EMPTY_SCB_AVAIL", 0x80, 0x80 }
-};
-
-int
-ahd_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(QOFF_CTLSTA_parse_table, 18, "QOFF_CTLSTA",
- 0x16, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t INTCTL_parse_table[] = {
{ "SPLTINTEN", 0x01, 0x01 },
{ "SEQINTEN", 0x02, 0x02 },
@@ -280,22 +93,6 @@ ahd_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x19, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
- { "CIOPARCKEN", 0x01, 0x01 },
- { "DISABLE_TWATE", 0x02, 0x02 },
- { "EXTREQLCK", 0x10, 0x10 },
- { "MPARCKEN", 0x20, 0x20 },
- { "DPARCKEN", 0x40, 0x40 },
- { "CACHETHEN", 0x80, 0x80 }
-};
-
-int
-ahd_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DSCOMMAND0_parse_table, 6, "DSCOMMAND0",
- 0x19, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t DFSTATUS_parse_table[] = {
{ "FIFOEMP", 0x01, 0x01 },
{ "FIFOFULL", 0x02, 0x02 },
@@ -327,146 +124,6 @@ ahd_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1b, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
- { "LAST_SEG", 0x02, 0x02 },
- { "ODD_SEG", 0x04, 0x04 },
- { "SG_ADDR_MASK", 0xf8, 0xf8 }
-};
-
-int
-ahd_sg_cache_pre_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SG_CACHE_PRE_parse_table, 3, "SG_CACHE_PRE",
- 0x1b, regvalue, cur_col, wrap));
-}
-
-int
-ahd_lqin_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LQIN",
- 0x20, regvalue, cur_col, wrap));
-}
-
-int
-ahd_lunptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LUNPTR",
- 0x22, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cmdlenptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CMDLENPTR",
- 0x25, regvalue, cur_col, wrap));
-}
-
-int
-ahd_attrptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ATTRPTR",
- 0x26, regvalue, cur_col, wrap));
-}
-
-int
-ahd_flagptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "FLAGPTR",
- 0x27, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cmdptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CMDPTR",
- 0x28, regvalue, cur_col, wrap));
-}
-
-int
-ahd_qnextptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "QNEXTPTR",
- 0x29, regvalue, cur_col, wrap));
-}
-
-int
-ahd_abrtbyteptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ABRTBYTEPTR",
- 0x2b, regvalue, cur_col, wrap));
-}
-
-int
-ahd_abrtbitptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ABRTBITPTR",
- 0x2c, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t LUNLEN_parse_table[] = {
- { "ILUNLEN", 0x0f, 0x0f },
- { "TLUNLEN", 0xf0, 0xf0 }
-};
-
-int
-ahd_lunlen_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LUNLEN_parse_table, 2, "LUNLEN",
- 0x30, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cdblimit_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CDBLIMIT",
- 0x31, regvalue, cur_col, wrap));
-}
-
-int
-ahd_maxcmd_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "MAXCMD",
- 0x32, regvalue, cur_col, wrap));
-}
-
-int
-ahd_maxcmdcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "MAXCMDCNT",
- 0x33, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t LQCTL1_parse_table[] = {
- { "ABORTPENDING", 0x01, 0x01 },
- { "SINGLECMD", 0x02, 0x02 },
- { "PCI2PCI", 0x04, 0x04 }
-};
-
-int
-ahd_lqctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQCTL1_parse_table, 3, "LQCTL1",
- 0x38, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t LQCTL2_parse_table[] = {
- { "LQOPAUSE", 0x01, 0x01 },
- { "LQOTOIDLE", 0x02, 0x02 },
- { "LQOCONTINUE", 0x04, 0x04 },
- { "LQORETRY", 0x08, 0x08 },
- { "LQIPAUSE", 0x10, 0x10 },
- { "LQITOIDLE", 0x20, 0x20 },
- { "LQICONTINUE", 0x40, 0x40 },
- { "LQIRETRY", 0x80, 0x80 }
-};
-
-int
-ahd_lqctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQCTL2_parse_table, 8, "LQCTL2",
- 0x39, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SCSISEQ0_parse_table[] = {
{ "SCSIRSTO", 0x01, 0x01 },
{ "FORCEBUSFREE", 0x10, 0x10 },
@@ -498,37 +155,6 @@ ahd_scsiseq1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3b, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t SXFRCTL0_parse_table[] = {
- { "SPIOEN", 0x08, 0x08 },
- { "BIOSCANCELEN", 0x10, 0x10 },
- { "DFPEXP", 0x40, 0x40 },
- { "DFON", 0x80, 0x80 }
-};
-
-int
-ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SXFRCTL0_parse_table, 4, "SXFRCTL0",
- 0x3c, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SXFRCTL1_parse_table[] = {
- { "STPWEN", 0x01, 0x01 },
- { "ACTNEGEN", 0x02, 0x02 },
- { "ENSTIMER", 0x04, 0x04 },
- { "STIMESEL", 0x18, 0x18 },
- { "ENSPCHK", 0x20, 0x20 },
- { "ENSACHK", 0x40, 0x40 },
- { "BITBUCKET", 0x80, 0x80 }
-};
-
-int
-ahd_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SXFRCTL1_parse_table, 7, "SXFRCTL1",
- 0x3d, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t DFFSTAT_parse_table[] = {
{ "CURRFIFO_0", 0x00, 0x03 },
{ "CURRFIFO_1", 0x01, 0x03 },
@@ -545,40 +171,6 @@ ahd_dffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3f, regvalue, cur_col, wrap));
}
-int
-ahd_multargid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "MULTARGID",
- 0x40, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCSISIGO_parse_table[] = {
- { "P_DATAOUT", 0x00, 0xe0 },
- { "P_DATAOUT_DT", 0x20, 0xe0 },
- { "P_DATAIN", 0x40, 0xe0 },
- { "P_DATAIN_DT", 0x60, 0xe0 },
- { "P_COMMAND", 0x80, 0xe0 },
- { "P_MESGOUT", 0xa0, 0xe0 },
- { "P_STATUS", 0xc0, 0xe0 },
- { "P_MESGIN", 0xe0, 0xe0 },
- { "ACKO", 0x01, 0x01 },
- { "REQO", 0x02, 0x02 },
- { "BSYO", 0x04, 0x04 },
- { "SELO", 0x08, 0x08 },
- { "ATNO", 0x10, 0x10 },
- { "MSGO", 0x20, 0x20 },
- { "IOO", 0x40, 0x40 },
- { "CDO", 0x80, 0x80 },
- { "PHASE_MASK", 0xe0, 0xe0 }
-};
-
-int
-ahd_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCSISIGO_parse_table, 17, "SCSISIGO",
- 0x40, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SCSISIGI_parse_table[] = {
{ "P_DATAOUT", 0x00, 0xe0 },
{ "P_DATAOUT_DT", 0x20, 0xe0 },
@@ -624,31 +216,12 @@ ahd_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_scsidat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCSIDAT",
- 0x44, regvalue, cur_col, wrap));
-}
-
-int
ahd_scsibus_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCSIBUS",
0x46, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t TARGIDIN_parse_table[] = {
- { "TARGID", 0x0f, 0x0f },
- { "CLKOUT", 0x80, 0x80 }
-};
-
-int
-ahd_targidin_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(TARGIDIN_parse_table, 2, "TARGIDIN",
- 0x48, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SELID_parse_table[] = {
{ "ONEBIT", 0x08, 0x08 },
{ "SELID_MASK", 0xf0, 0xf0 }
@@ -661,38 +234,6 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x49, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
- { "AUTO_MSGOUT_DE", 0x02, 0x02 },
- { "ENDGFORMCHK", 0x04, 0x04 },
- { "BUSFREEREV", 0x10, 0x10 },
- { "BIASCANCTL", 0x20, 0x20 },
- { "AUTOACKEN", 0x40, 0x40 },
- { "BIOSCANCTL", 0x80, 0x80 },
- { "OPTIONMODE_DEFAULTS",0x02, 0x02 }
-};
-
-int
-ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(OPTIONMODE_parse_table, 7, "OPTIONMODE",
- 0x4a, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
- { "SELWIDE", 0x02, 0x02 },
- { "ENAB20", 0x04, 0x04 },
- { "ENAB40", 0x08, 0x08 },
- { "DIAGLEDON", 0x40, 0x40 },
- { "DIAGLEDEN", 0x80, 0x80 }
-};
-
-int
-ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
- 0x4a, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
{ "ARBDO", 0x01, 0x01 },
{ "SPIORDY", 0x02, 0x02 },
@@ -728,23 +269,6 @@ ahd_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4b, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
- { "CLRARBDO", 0x01, 0x01 },
- { "CLRSPIORDY", 0x02, 0x02 },
- { "CLROVERRUN", 0x04, 0x04 },
- { "CLRIOERR", 0x08, 0x08 },
- { "CLRSELINGO", 0x10, 0x10 },
- { "CLRSELDI", 0x20, 0x20 },
- { "CLRSELDO", 0x40, 0x40 }
-};
-
-int
-ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSINT0_parse_table, 7, "CLRSINT0",
- 0x4b, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SSTAT1_parse_table[] = {
{ "REQINIT", 0x01, 0x01 },
{ "STRB2FAST", 0x02, 0x02 },
@@ -763,23 +287,6 @@ ahd_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4c, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRSINT1_parse_table[] = {
- { "CLRREQINIT", 0x01, 0x01 },
- { "CLRSTRB2FAST", 0x02, 0x02 },
- { "CLRSCSIPERR", 0x04, 0x04 },
- { "CLRBUSFREE", 0x08, 0x08 },
- { "CLRSCSIRSTI", 0x20, 0x20 },
- { "CLRATNO", 0x40, 0x40 },
- { "CLRSELTIMEO", 0x80, 0x80 }
-};
-
-int
-ahd_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSINT1_parse_table, 7, "CLRSINT1",
- 0x4c, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SSTAT2_parse_table[] = {
{ "BUSFREE_LQO", 0x40, 0xc0 },
{ "BUSFREE_DFF0", 0x80, 0xc0 },
@@ -800,20 +307,6 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4d, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
- { "CLRDMADONE", 0x01, 0x01 },
- { "CLRSDONE", 0x02, 0x02 },
- { "CLRWIDE_RES", 0x04, 0x04 },
- { "CLRNONPACKREQ", 0x20, 0x20 }
-};
-
-int
-ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2",
- 0x4d, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
{ "DTERR", 0x01, 0x01 },
{ "DGFORMERR", 0x02, 0x02 },
@@ -833,26 +326,12 @@ ahd_perrdiag_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_lqistate_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LQISTATE",
- 0x4e, regvalue, cur_col, wrap));
-}
-
-int
ahd_soffcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SOFFCNT",
0x4f, regvalue, cur_col, wrap));
}
-int
-ahd_lqostate_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LQOSTATE",
- 0x4f, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LQISTAT0_parse_table[] = {
{ "LQIATNCMD", 0x01, 0x01 },
{ "LQIATNLQ", 0x02, 0x02 },
@@ -869,56 +348,6 @@ ahd_lqistat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x50, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t LQIMODE0_parse_table[] = {
- { "ENLQIATNCMD", 0x01, 0x01 },
- { "ENLQIATNLQ", 0x02, 0x02 },
- { "ENLQIBADLQT", 0x04, 0x04 },
- { "ENLQICRCT2", 0x08, 0x08 },
- { "ENLQICRCT1", 0x10, 0x10 },
- { "ENLQIATNQASK", 0x20, 0x20 }
-};
-
-int
-ahd_lqimode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQIMODE0_parse_table, 6, "LQIMODE0",
- 0x50, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t CLRLQIINT0_parse_table[] = {
- { "CLRLQIATNCMD", 0x01, 0x01 },
- { "CLRLQIATNLQ", 0x02, 0x02 },
- { "CLRLQIBADLQT", 0x04, 0x04 },
- { "CLRLQICRCT2", 0x08, 0x08 },
- { "CLRLQICRCT1", 0x10, 0x10 },
- { "CLRLQIATNQAS", 0x20, 0x20 }
-};
-
-int
-ahd_clrlqiint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRLQIINT0_parse_table, 6, "CLRLQIINT0",
- 0x50, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t LQIMODE1_parse_table[] = {
- { "ENLQIOVERI_NLQ", 0x01, 0x01 },
- { "ENLQIOVERI_LQ", 0x02, 0x02 },
- { "ENLQIBADLQI", 0x04, 0x04 },
- { "ENLQICRCI_NLQ", 0x08, 0x08 },
- { "ENLQICRCI_LQ", 0x10, 0x10 },
- { "ENLIQABORT", 0x20, 0x20 },
- { "ENLQIPHASE_NLQ", 0x40, 0x40 },
- { "ENLQIPHASE_LQ", 0x80, 0x80 }
-};
-
-int
-ahd_lqimode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQIMODE1_parse_table, 8, "LQIMODE1",
- 0x51, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LQISTAT1_parse_table[] = {
{ "LQIOVERI_NLQ", 0x01, 0x01 },
{ "LQIOVERI_LQ", 0x02, 0x02 },
@@ -937,24 +366,6 @@ ahd_lqistat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x51, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRLQIINT1_parse_table[] = {
- { "CLRLQIOVERI_NLQ", 0x01, 0x01 },
- { "CLRLQIOVERI_LQ", 0x02, 0x02 },
- { "CLRLQIBADLQI", 0x04, 0x04 },
- { "CLRLQICRCI_NLQ", 0x08, 0x08 },
- { "CLRLQICRCI_LQ", 0x10, 0x10 },
- { "CLRLIQABORT", 0x20, 0x20 },
- { "CLRLQIPHASE_NLQ", 0x40, 0x40 },
- { "CLRLQIPHASE_LQ", 0x80, 0x80 }
-};
-
-int
-ahd_clrlqiint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRLQIINT1_parse_table, 8, "CLRLQIINT1",
- 0x51, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LQISTAT2_parse_table[] = {
{ "LQIGSAVAIL", 0x01, 0x01 },
{ "LQISTOPCMD", 0x02, 0x02 },
@@ -985,30 +396,6 @@ ahd_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x53, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t SIMODE3_parse_table[] = {
- { "ENOSRAMPERR", 0x01, 0x01 },
- { "ENNTRAMPERR", 0x02, 0x02 }
-};
-
-int
-ahd_simode3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SIMODE3_parse_table, 2, "SIMODE3",
- 0x53, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t CLRSINT3_parse_table[] = {
- { "CLROSRAMPERR", 0x01, 0x01 },
- { "CLRNTRAMPERR", 0x02, 0x02 }
-};
-
-int
-ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSINT3_parse_table, 2, "CLRSINT3",
- 0x53, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
{ "LQOTCRC", 0x01, 0x01 },
{ "LQOATNPKT", 0x02, 0x02 },
@@ -1024,51 +411,6 @@ ahd_lqostat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x54, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRLQOINT0_parse_table[] = {
- { "CLRLQOTCRC", 0x01, 0x01 },
- { "CLRLQOATNPKT", 0x02, 0x02 },
- { "CLRLQOATNLQ", 0x04, 0x04 },
- { "CLRLQOSTOPT2", 0x08, 0x08 },
- { "CLRLQOTARGSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRLQOINT0_parse_table, 5, "CLRLQOINT0",
- 0x54, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
- { "ENLQOTCRC", 0x01, 0x01 },
- { "ENLQOATNPKT", 0x02, 0x02 },
- { "ENLQOATNLQ", 0x04, 0x04 },
- { "ENLQOSTOPT2", 0x08, 0x08 },
- { "ENLQOTARGSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
- 0x54, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
- { "ENLQOPHACHGINPKT", 0x01, 0x01 },
- { "ENLQOBUSFREE", 0x02, 0x02 },
- { "ENLQOBADQAS", 0x04, 0x04 },
- { "ENLQOSTOPI2", 0x08, 0x08 },
- { "ENLQOINITSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
- 0x55, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
{ "LQOPHACHGINPKT", 0x01, 0x01 },
{ "LQOBUSFREE", 0x02, 0x02 },
@@ -1084,21 +426,6 @@ ahd_lqostat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x55, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t CLRLQOINT1_parse_table[] = {
- { "CLRLQOPHACHGINPKT", 0x01, 0x01 },
- { "CLRLQOBUSFREE", 0x02, 0x02 },
- { "CLRLQOBADQAS", 0x04, 0x04 },
- { "CLRLQOSTOPI2", 0x08, 0x08 },
- { "CLRLQOINITSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRLQOINT1_parse_table, 5, "CLRLQOINT1",
- 0x55, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
{ "LQOSTOP0", 0x01, 0x01 },
{ "LQOPHACHGOUTPKT", 0x02, 0x02 },
@@ -1113,13 +440,6 @@ ahd_lqostat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x56, regvalue, cur_col, wrap));
}
-int
-ahd_os_space_cnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "OS_SPACE_CNT",
- 0x56, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SIMODE1_parse_table[] = {
{ "ENREQINIT", 0x01, 0x01 },
{ "ENSTRB2FAST", 0x02, 0x02 },
@@ -1138,13 +458,6 @@ ahd_simode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x57, regvalue, cur_col, wrap));
}
-int
-ahd_gsfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "GSFIFO",
- 0x58, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t DFFSXFRCTL_parse_table[] = {
{ "RSTCHN", 0x01, 0x01 },
{ "CLRCHN", 0x02, 0x02 },
@@ -1159,44 +472,6 @@ ahd_dffsxfrctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x5a, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t LQOSCSCTL_parse_table[] = {
- { "LQONOCHKOVER", 0x01, 0x01 },
- { "LQONOHOLDLACK", 0x02, 0x02 },
- { "LQOBUSETDLY", 0x40, 0x40 },
- { "LQOH2A_VERSION", 0x80, 0x80 }
-};
-
-int
-ahd_lqoscsctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOSCSCTL_parse_table, 4, "LQOSCSCTL",
- 0x5a, regvalue, cur_col, wrap));
-}
-
-int
-ahd_nextscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "NEXTSCB",
- 0x5a, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t CLRSEQINTSRC_parse_table[] = {
- { "CLRCFG4TCMD", 0x01, 0x01 },
- { "CLRCFG4ICMD", 0x02, 0x02 },
- { "CLRCFG4TSTAT", 0x04, 0x04 },
- { "CLRCFG4ISTAT", 0x08, 0x08 },
- { "CLRCFG4DATA", 0x10, 0x10 },
- { "CLRSAVEPTRS", 0x20, 0x20 },
- { "CLRCTXTDONE", 0x40, 0x40 }
-};
-
-int
-ahd_clrseqintsrc_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSEQINTSRC_parse_table, 7, "CLRSEQINTSRC",
- 0x5b, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SEQINTSRC_parse_table[] = {
{ "CFG4TCMD", 0x01, 0x01 },
{ "CFG4ICMD", 0x02, 0x02 },
@@ -1231,13 +506,6 @@ ahd_seqimode_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x5c, regvalue, cur_col, wrap));
}
-int
-ahd_currscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CURRSCB",
- 0x5c, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t MDFFSTAT_parse_table[] = {
{ "FIFOFREE", 0x01, 0x01 },
{ "DATAINFIFO", 0x02, 0x02 },
@@ -1256,308 +524,12 @@ ahd_mdffstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_lastscb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LASTSCB",
- 0x5e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SHADDR",
- 0x60, regvalue, cur_col, wrap));
-}
-
-int
-ahd_negoaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "NEGOADDR",
- 0x60, regvalue, cur_col, wrap));
-}
-
-int
-ahd_negperiod_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "NEGPERIOD",
- 0x61, regvalue, cur_col, wrap));
-}
-
-int
-ahd_negoffset_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "NEGOFFSET",
- 0x62, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t NEGPPROPTS_parse_table[] = {
- { "PPROPT_IUT", 0x01, 0x01 },
- { "PPROPT_DT", 0x02, 0x02 },
- { "PPROPT_QAS", 0x04, 0x04 },
- { "PPROPT_PACE", 0x08, 0x08 }
-};
-
-int
-ahd_negppropts_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NEGPPROPTS_parse_table, 4, "NEGPPROPTS",
- 0x63, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t NEGCONOPTS_parse_table[] = {
- { "WIDEXFER", 0x01, 0x01 },
- { "ENAUTOATNO", 0x02, 0x02 },
- { "ENAUTOATNI", 0x04, 0x04 },
- { "ENSLOWCRC", 0x08, 0x08 },
- { "RTI_OVRDTRN", 0x10, 0x10 },
- { "RTI_WRTDIS", 0x20, 0x20 },
- { "ENSNAPSHOT", 0x40, 0x40 }
-};
-
-int
-ahd_negconopts_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NEGCONOPTS_parse_table, 7, "NEGCONOPTS",
- 0x64, regvalue, cur_col, wrap));
-}
-
-int
-ahd_annexcol_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ANNEXCOL",
- 0x65, regvalue, cur_col, wrap));
-}
-
-int
-ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ANNEXDAT",
- 0x66, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
- { "LSTSGCLRDIS", 0x01, 0x01 },
- { "SHVALIDSTDIS", 0x02, 0x02 },
- { "DFFACTCLR", 0x04, 0x04 },
- { "SDONEMSKDIS", 0x08, 0x08 },
- { "WIDERESEN", 0x10, 0x10 },
- { "CURRFIFODEF", 0x20, 0x20 },
- { "STSELSKIDDIS", 0x40, 0x40 },
- { "BIDICHKDIS", 0x80, 0x80 }
-};
-
-int
-ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCSCHKN_parse_table, 8, "SCSCHKN",
- 0x66, regvalue, cur_col, wrap));
-}
-
-int
-ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "IOWNID",
- 0x67, regvalue, cur_col, wrap));
-}
-
-int
-ahd_shcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SHCNT",
- 0x68, regvalue, cur_col, wrap));
-}
-
-int
-ahd_townid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "TOWNID",
- 0x69, regvalue, cur_col, wrap));
-}
-
-int
ahd_seloid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SELOID",
0x6b, regvalue, cur_col, wrap));
}
-int
-ahd_haddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "HADDR",
- 0x70, regvalue, cur_col, wrap));
-}
-
-int
-ahd_hcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "HCNT",
- 0x78, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SGHADDR",
- 0x7c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCBHADDR",
- 0x7c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SGHCNT",
- 0x84, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCBHCNT",
- 0x84, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DFF_THRSH_parse_table[] = {
- { "WR_DFTHRSH_MIN", 0x00, 0x70 },
- { "RD_DFTHRSH_MIN", 0x00, 0x07 },
- { "RD_DFTHRSH_25", 0x01, 0x07 },
- { "RD_DFTHRSH_50", 0x02, 0x07 },
- { "RD_DFTHRSH_63", 0x03, 0x07 },
- { "RD_DFTHRSH_75", 0x04, 0x07 },
- { "RD_DFTHRSH_85", 0x05, 0x07 },
- { "RD_DFTHRSH_90", 0x06, 0x07 },
- { "RD_DFTHRSH_MAX", 0x07, 0x07 },
- { "WR_DFTHRSH_25", 0x10, 0x70 },
- { "WR_DFTHRSH_50", 0x20, 0x70 },
- { "WR_DFTHRSH_63", 0x30, 0x70 },
- { "WR_DFTHRSH_75", 0x40, 0x70 },
- { "WR_DFTHRSH_85", 0x50, 0x70 },
- { "WR_DFTHRSH_90", 0x60, 0x70 },
- { "WR_DFTHRSH_MAX", 0x70, 0x70 },
- { "RD_DFTHRSH", 0x07, 0x07 },
- { "WR_DFTHRSH", 0x70, 0x70 }
-};
-
-int
-ahd_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DFF_THRSH_parse_table, 18, "DFF_THRSH",
- 0x88, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t PCIXCTL_parse_table[] = {
- { "CMPABCDIS", 0x01, 0x01 },
- { "TSCSERREN", 0x02, 0x02 },
- { "SRSPDPEEN", 0x04, 0x04 },
- { "SPLTSTADIS", 0x08, 0x08 },
- { "SPLTSMADIS", 0x10, 0x10 },
- { "UNEXPSCIEN", 0x20, 0x20 },
- { "SERRPULSE", 0x80, 0x80 }
-};
-
-int
-ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(PCIXCTL_parse_table, 7, "PCIXCTL",
- 0x93, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
- { "RXSPLTRSP", 0x01, 0x01 },
- { "RXSCEMSG", 0x02, 0x02 },
- { "RXOVRUN", 0x04, 0x04 },
- { "CNTNOTCMPLT", 0x08, 0x08 },
- { "SCDATBUCKET", 0x10, 0x10 },
- { "SCADERR", 0x20, 0x20 },
- { "SCBCERR", 0x40, 0x40 },
- { "STAETERM", 0x80, 0x80 }
-};
-
-int
-ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0",
- 0x96, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
- { "RXDATABUCKET", 0x01, 0x01 }
-};
-
-int
-ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
- 0x97, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SGSPLTSTAT0_parse_table[] = {
- { "RXSPLTRSP", 0x01, 0x01 },
- { "RXSCEMSG", 0x02, 0x02 },
- { "RXOVRUN", 0x04, 0x04 },
- { "CNTNOTCMPLT", 0x08, 0x08 },
- { "SCDATBUCKET", 0x10, 0x10 },
- { "SCADERR", 0x20, 0x20 },
- { "SCBCERR", 0x40, 0x40 },
- { "STAETERM", 0x80, 0x80 }
-};
-
-int
-ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SGSPLTSTAT0_parse_table, 8, "SGSPLTSTAT0",
- 0x9e, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
- { "RXDATABUCKET", 0x01, 0x01 }
-};
-
-int
-ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
- 0x9f, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DF0PCISTAT_parse_table[] = {
- { "DPR", 0x01, 0x01 },
- { "TWATERR", 0x02, 0x02 },
- { "RDPERR", 0x04, 0x04 },
- { "SCAAPERR", 0x08, 0x08 },
- { "RTA", 0x10, 0x10 },
- { "RMA", 0x20, 0x20 },
- { "SSE", 0x40, 0x40 },
- { "DPE", 0x80, 0x80 }
-};
-
-int
-ahd_df0pcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DF0PCISTAT_parse_table, 8, "DF0PCISTAT",
- 0xa0, regvalue, cur_col, wrap));
-}
-
-int
-ahd_reg0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "REG0",
- 0xa0, regvalue, cur_col, wrap));
-}
-
-int
-ahd_reg_isr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "REG_ISR",
- 0xa4, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SG_STATE_parse_table[] = {
{ "SEGS_AVAIL", 0x01, 0x01 },
{ "LOADING_NEEDED", 0x02, 0x02 },
@@ -1571,54 +543,6 @@ ahd_sg_state_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xa6, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t TARGPCISTAT_parse_table[] = {
- { "TWATERR", 0x02, 0x02 },
- { "STA", 0x08, 0x08 },
- { "SSE", 0x40, 0x40 },
- { "DPE", 0x80, 0x80 }
-};
-
-int
-ahd_targpcistat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(TARGPCISTAT_parse_table, 4, "TARGPCISTAT",
- 0xa7, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCBPTR",
- 0xa8, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCBAUTOPTR_parse_table[] = {
- { "SCBPTR_OFF", 0x07, 0x07 },
- { "SCBPTR_ADDR", 0x38, 0x38 },
- { "AUSCBPTR_EN", 0x80, 0x80 }
-};
-
-int
-ahd_scbautoptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCBAUTOPTR_parse_table, 3, "SCBAUTOPTR",
- 0xab, regvalue, cur_col, wrap));
-}
-
-int
-ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CCSGADDR",
- 0xac, regvalue, cur_col, wrap));
-}
-
-int
-ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CCSCBADDR",
- 0xac, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
{ "CCSCBRESET", 0x01, 0x01 },
{ "CCSCBDIR", 0x04, 0x04 },
@@ -1651,138 +575,6 @@ ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xad, regvalue, cur_col, wrap));
}
-int
-ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CCSGRAM",
- 0xb0, regvalue, cur_col, wrap));
-}
-
-int
-ahd_ccscbram_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CCSCBRAM",
- 0xb0, regvalue, cur_col, wrap));
-}
-
-int
-ahd_brddat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "BRDDAT",
- 0xb8, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t BRDCTL_parse_table[] = {
- { "BRDSTB", 0x01, 0x01 },
- { "BRDRW", 0x02, 0x02 },
- { "BRDEN", 0x04, 0x04 },
- { "BRDADDR", 0x38, 0x38 },
- { "FLXARBREQ", 0x40, 0x40 },
- { "FLXARBACK", 0x80, 0x80 }
-};
-
-int
-ahd_brdctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(BRDCTL_parse_table, 6, "BRDCTL",
- 0xb9, regvalue, cur_col, wrap));
-}
-
-int
-ahd_seeadr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SEEADR",
- 0xba, regvalue, cur_col, wrap));
-}
-
-int
-ahd_seedat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SEEDAT",
- 0xbc, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SEECTL_parse_table[] = {
- { "SEEOP_ERAL", 0x40, 0x70 },
- { "SEEOP_WRITE", 0x50, 0x70 },
- { "SEEOP_READ", 0x60, 0x70 },
- { "SEEOP_ERASE", 0x70, 0x70 },
- { "SEESTART", 0x01, 0x01 },
- { "SEERST", 0x02, 0x02 },
- { "SEEOPCODE", 0x70, 0x70 },
- { "SEEOP_EWEN", 0x40, 0x40 },
- { "SEEOP_WALL", 0x40, 0x40 },
- { "SEEOP_EWDS", 0x40, 0x40 }
-};
-
-int
-ahd_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SEECTL_parse_table, 10, "SEECTL",
- 0xbe, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SEESTAT_parse_table[] = {
- { "SEESTART", 0x01, 0x01 },
- { "SEEBUSY", 0x02, 0x02 },
- { "SEEARBACK", 0x04, 0x04 },
- { "LDALTID_L", 0x08, 0x08 },
- { "SEEOPCODE", 0x70, 0x70 },
- { "INIT_DONE", 0x80, 0x80 }
-};
-
-int
-ahd_seestat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SEESTAT_parse_table, 6, "SEESTAT",
- 0xbe, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DSPDATACTL_parse_table[] = {
- { "XMITOFFSTDIS", 0x02, 0x02 },
- { "RCVROFFSTDIS", 0x04, 0x04 },
- { "DESQDIS", 0x10, 0x10 },
- { "BYPASSENAB", 0x80, 0x80 }
-};
-
-int
-ahd_dspdatactl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DSPDATACTL_parse_table, 4, "DSPDATACTL",
- 0xc1, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "DFDAT",
- 0xc4, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DSPSELECT_parse_table[] = {
- { "DSPSEL", 0x1f, 0x1f },
- { "AUTOINCEN", 0x80, 0x80 }
-};
-
-int
-ahd_dspselect_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DSPSELECT_parse_table, 2, "DSPSELECT",
- 0xc4, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t WRTBIASCTL_parse_table[] = {
- { "XMITMANVAL", 0x3f, 0x3f },
- { "AUTOXBCDIS", 0x80, 0x80 }
-};
-
-int
-ahd_wrtbiasctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(WRTBIASCTL_parse_table, 2, "WRTBIASCTL",
- 0xc5, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SEQCTL0_parse_table[] = {
{ "LOADRAM", 0x01, 0x01 },
{ "SEQRESET", 0x02, 0x02 },
@@ -1801,18 +593,6 @@ ahd_seqctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xd6, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t FLAGS_parse_table[] = {
- { "CARRY", 0x01, 0x01 },
- { "ZERO", 0x02, 0x02 }
-};
-
-int
-ahd_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(FLAGS_parse_table, 2, "FLAGS",
- 0xd8, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SEQINTCTL_parse_table[] = {
{ "IRET", 0x01, 0x01 },
{ "INTMASK1", 0x02, 0x02 },
@@ -1831,118 +611,6 @@ ahd_seqintctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_seqram_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SEQRAM",
- 0xda, regvalue, cur_col, wrap));
-}
-
-int
-ahd_prgmcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "PRGMCNT",
- 0xde, regvalue, cur_col, wrap));
-}
-
-int
-ahd_accum_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ACCUM",
- 0xe0, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SINDEX",
- 0xe2, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "DINDEX",
- 0xe4, regvalue, cur_col, wrap));
-}
-
-int
-ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ALLONES",
- 0xe8, regvalue, cur_col, wrap));
-}
-
-int
-ahd_allzeros_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ALLZEROS",
- 0xea, regvalue, cur_col, wrap));
-}
-
-int
-ahd_none_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "NONE",
- 0xea, regvalue, cur_col, wrap));
-}
-
-int
-ahd_sindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SINDIR",
- 0xec, regvalue, cur_col, wrap));
-}
-
-int
-ahd_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "DINDIR",
- 0xed, regvalue, cur_col, wrap));
-}
-
-int
-ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "STACK",
- 0xf2, regvalue, cur_col, wrap));
-}
-
-int
-ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
- 0xf4, regvalue, cur_col, wrap));
-}
-
-int
-ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CURADDR",
- 0xf4, regvalue, cur_col, wrap));
-}
-
-int
-ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
- 0xf6, regvalue, cur_col, wrap));
-}
-
-int
-ahd_longjmp_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LONGJMP_ADDR",
- 0xf8, regvalue, cur_col, wrap));
-}
-
-int
-ahd_accum_save_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ACCUM_SAVE",
- 0xfa, regvalue, cur_col, wrap));
-}
-
-int
ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SRAM_BASE",
@@ -1950,69 +618,6 @@ ahd_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_waiting_scb_tails_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "WAITING_SCB_TAILS",
- 0x100, regvalue, cur_col, wrap));
-}
-
-int
-ahd_waiting_tid_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "WAITING_TID_HEAD",
- 0x120, regvalue, cur_col, wrap));
-}
-
-int
-ahd_waiting_tid_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "WAITING_TID_TAIL",
- 0x122, regvalue, cur_col, wrap));
-}
-
-int
-ahd_next_queued_scb_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "NEXT_QUEUED_SCB_ADDR",
- 0x124, regvalue, cur_col, wrap));
-}
-
-int
-ahd_complete_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "COMPLETE_SCB_HEAD",
- 0x128, regvalue, cur_col, wrap));
-}
-
-int
-ahd_complete_scb_dmainprog_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "COMPLETE_SCB_DMAINPROG_HEAD",
- 0x12a, regvalue, cur_col, wrap));
-}
-
-int
-ahd_complete_dma_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_HEAD",
- 0x12c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL",
- 0x12e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD",
- 0x130, regvalue, cur_col, wrap));
-}
-
-int
ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "QFREEZE_COUNT",
@@ -2033,33 +638,6 @@ ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x136, regvalue, cur_col, wrap));
}
-int
-ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "MSG_OUT",
- 0x137, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
- { "FIFORESET", 0x01, 0x01 },
- { "FIFOFLUSH", 0x02, 0x02 },
- { "DIRECTION", 0x04, 0x04 },
- { "HDMAEN", 0x08, 0x08 },
- { "HDMAENACK", 0x08, 0x08 },
- { "SDMAEN", 0x10, 0x10 },
- { "SDMAENACK", 0x10, 0x10 },
- { "SCSIEN", 0x20, 0x20 },
- { "WIDEODD", 0x40, 0x40 },
- { "PRELOADEN", 0x80, 0x80 }
-};
-
-int
-ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS",
- 0x138, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
{ "NO_DISCONNECT", 0x01, 0x01 },
{ "SPHASE_PENDING", 0x02, 0x02 },
@@ -2079,20 +657,6 @@ ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x139, regvalue, cur_col, wrap));
}
-int
-ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SAVED_SCSIID",
- 0x13a, regvalue, cur_col, wrap));
-}
-
-int
-ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SAVED_LUN",
- 0x13b, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
{ "P_DATAOUT", 0x00, 0xe0 },
{ "P_DATAOUT_DT", 0x20, 0xe0 },
@@ -2116,96 +680,6 @@ ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x13c, regvalue, cur_col, wrap));
}
-int
-ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG",
- 0x13d, regvalue, cur_col, wrap));
-}
-
-int
-ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
- 0x13e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "TQINPOS",
- 0x13f, regvalue, cur_col, wrap));
-}
-
-int
-ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
- 0x140, regvalue, cur_col, wrap));
-}
-
-int
-ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
- 0x144, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t ARG_1_parse_table[] = {
- { "CONT_MSG_LOOP_TARG", 0x02, 0x02 },
- { "CONT_MSG_LOOP_READ", 0x03, 0x03 },
- { "CONT_MSG_LOOP_WRITE",0x04, 0x04 },
- { "EXIT_MSG_LOOP", 0x08, 0x08 },
- { "MSGOUT_PHASEMIS", 0x10, 0x10 },
- { "SEND_REJ", 0x20, 0x20 },
- { "SEND_SENSE", 0x40, 0x40 },
- { "SEND_MSG", 0x80, 0x80 }
-};
-
-int
-ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1",
- 0x148, regvalue, cur_col, wrap));
-}
-
-int
-ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ARG_2",
- 0x149, regvalue, cur_col, wrap));
-}
-
-int
-ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LAST_MSG",
- 0x14a, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
- { "ALTSTIM", 0x01, 0x01 },
- { "ENAUTOATNP", 0x02, 0x02 },
- { "MANUALP", 0x0c, 0x0c },
- { "ENRSELI", 0x10, 0x10 },
- { "ENSELI", 0x20, 0x20 },
- { "MANUALCTL", 0x40, 0x40 }
-};
-
-int
-ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE",
- 0x14b, regvalue, cur_col, wrap));
-}
-
-int
-ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INITIATOR_TAG",
- 0x14c, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
{ "PENDING_MK_MESSAGE", 0x01, 0x01 },
{ "TARGET_MSG_PENDING", 0x02, 0x02 },
@@ -2220,62 +694,6 @@ ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR",
- 0x14e, regvalue, cur_col, wrap));
-}
-
-int
-ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER",
- 0x150, regvalue, cur_col, wrap));
-}
-
-int
-ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS",
- 0x152, regvalue, cur_col, wrap));
-}
-
-int
-ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS",
- 0x153, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CMDS_PENDING",
- 0x154, regvalue, cur_col, wrap));
-}
-
-int
-ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT",
- 0x156, regvalue, cur_col, wrap));
-}
-
-int
-ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX",
- 0x157, regvalue, cur_col, wrap));
-}
-
-int
-ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE",
- 0x158, regvalue, cur_col, wrap));
-}
-
-int
ahd_mk_message_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCB",
@@ -2290,53 +708,12 @@ ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_scb_residual_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_RESIDUAL_DATACNT",
- 0x180, regvalue, cur_col, wrap));
-}
-
-int
ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_BASE",
0x180, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t SCB_RESIDUAL_SGPTR_parse_table[] = {
- { "SG_LIST_NULL", 0x01, 0x01 },
- { "SG_OVERRUN_RESID", 0x02, 0x02 },
- { "SG_ADDR_MASK", 0xf8, 0xf8 }
-};
-
-int
-ahd_scb_residual_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCB_RESIDUAL_SGPTR_parse_table, 3, "SCB_RESIDUAL_SGPTR",
- 0x184, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_scsi_status_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_SCSI_STATUS",
- 0x188, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_sense_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_SENSE_BUSADDR",
- 0x18c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_TAG",
- 0x190, regvalue, cur_col, wrap));
-}
-
static const ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
{ "SCB_TAG_TYPE", 0x03, 0x03 },
{ "DISCONNECTED", 0x04, 0x04 },
@@ -2366,103 +743,3 @@ ahd_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x193, regvalue, cur_col, wrap));
}
-static const ahd_reg_parse_entry_t SCB_LUN_parse_table[] = {
- { "LID", 0xff, 0xff }
-};
-
-int
-ahd_scb_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCB_LUN_parse_table, 1, "SCB_LUN",
- 0x194, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCB_TASK_ATTRIBUTE_parse_table[] = {
- { "SCB_XFERLEN_ODD", 0x01, 0x01 }
-};
-
-int
-ahd_scb_task_attribute_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCB_TASK_ATTRIBUTE_parse_table, 1, "SCB_TASK_ATTRIBUTE",
- 0x195, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
- { "SCB_CDB_LEN_PTR", 0x80, 0x80 }
-};
-
-int
-ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN",
- 0x196, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT",
- 0x197, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_DATAPTR",
- 0x198, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
- { "SG_HIGH_ADDR_BITS", 0x7f, 0x7f },
- { "SG_LAST_SEG", 0x80, 0x80 }
-};
-
-int
-ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT",
- 0x1a0, regvalue, cur_col, wrap));
-}
-
-static const ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
- { "SG_LIST_NULL", 0x01, 0x01 },
- { "SG_FULL_RESID", 0x02, 0x02 },
- { "SG_STATUS_VALID", 0x04, 0x04 }
-};
-
-int
-ahd_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR",
- 0x1a4, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
- 0x1a8, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_NEXT",
- 0x1ac, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_NEXT2",
- 0x1ae, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_disconnected_lists_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "SCB_DISCONNECTED_LISTS",
- 0x1b8, regvalue, cur_col, wrap));
-}
-
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index 0d2f763c342..9a96e55da39 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -51,6 +51,17 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
*/
/*
+ * Registers marked "dont_generate_debug_code" are not (yet) referenced
+ * from the driver code, and this keyword inhibit generation
+ * of debug code for them.
+ *
+ * REG_PRETTY_PRINT config will complain if dont_generate_debug_code
+ * is added to the register which is referenced in the driver.
+ * Unreferenced register with no dont_generate_debug_code will result
+ * in dead code. No warning is issued.
+ */
+
+/*
* SCSI Sequence Control (p. 3-11).
* Each bit, when set starts a specific SCSI sequence on the bus
*/
@@ -97,6 +108,7 @@ register SXFRCTL1 {
field ENSTIMER 0x04
field ACTNEGEN 0x02
field STPWEN 0x01 /* Powered Termination */
+ dont_generate_debug_code
}
/*
@@ -155,6 +167,7 @@ register SCSISIGO {
mask P_MESGOUT CDI|MSGI
mask P_STATUS CDI|IOI
mask P_MESGIN CDI|IOI|MSGI
+ dont_generate_debug_code
}
/*
@@ -194,6 +207,7 @@ register SCSIID {
*/
alias SCSIOFFSET
mask SOFS_ULTRA2 0x7f /* Sync offset U2 chips */
+ dont_generate_debug_code
}
/*
@@ -205,6 +219,7 @@ register SCSIID {
register SCSIDATL {
address 0x006
access_mode RW
+ dont_generate_debug_code
}
register SCSIDATH {
@@ -223,6 +238,7 @@ register STCNT {
address 0x008
size 3
access_mode RW
+ dont_generate_debug_code
}
/* ALT_MODE registers (Ultra2 and Ultra160 chips) */
@@ -248,6 +264,7 @@ register OPTIONMODE {
field AUTO_MSGOUT_DE 0x02
field DIS_MSGIN_DUALEDGE 0x01
mask OPTIONMODE_DEFAULTS AUTO_MSGOUT_DE|DIS_MSGIN_DUALEDGE
+ dont_generate_debug_code
}
/* ALT_MODE register on Ultra160 chips */
@@ -256,6 +273,7 @@ register TARGCRCCNT {
size 2
access_mode RW
count 2
+ dont_generate_debug_code
}
/*
@@ -271,6 +289,7 @@ register CLRSINT0 {
field CLRSWRAP 0x08
field CLRIOERR 0x08 /* Ultra2 Only */
field CLRSPIORDY 0x02
+ dont_generate_debug_code
}
/*
@@ -306,6 +325,7 @@ register CLRSINT1 {
field CLRSCSIPERR 0x04
field CLRPHASECHG 0x02
field CLRREQINIT 0x01
+ dont_generate_debug_code
}
/*
@@ -360,6 +380,7 @@ register SCSIID_ULTRA2 {
access_mode RW
mask TID 0xf0 /* Target ID mask */
mask OID 0x0f /* Our ID mask */
+ dont_generate_debug_code
}
/*
@@ -425,6 +446,7 @@ register SHADDR {
address 0x014
size 4
access_mode RO
+ dont_generate_debug_code
}
/*
@@ -441,6 +463,7 @@ register SELTIMER {
field STAGE2 0x02
field STAGE1 0x01
alias TARGIDIN
+ dont_generate_debug_code
}
/*
@@ -453,6 +476,7 @@ register SELID {
access_mode RW
mask SELID_MASK 0xf0
field ONEBIT 0x08
+ dont_generate_debug_code
}
register SCAMCTL {
@@ -473,6 +497,7 @@ register TARGID {
size 2
access_mode RW
count 14
+ dont_generate_debug_code
}
/*
@@ -495,6 +520,7 @@ register SPIOCAP {
field EEPROM 0x04 /* Writable external BIOS ROM */
field ROM 0x02 /* Logic for accessing external ROM */
field SSPIOCPS 0x01 /* Termination and cable detection */
+ dont_generate_debug_code
}
register BRDCTL {
@@ -514,6 +540,7 @@ register BRDCTL {
field BRDDAT2 0x04
field BRDRW_ULTRA2 0x02
field BRDSTB_ULTRA2 0x01
+ dont_generate_debug_code
}
/*
@@ -551,6 +578,7 @@ register SEECTL {
field SEECK 0x04
field SEEDO 0x02
field SEEDI 0x01
+ dont_generate_debug_code
}
/*
* SCSI Block Control (p. 3-32)
@@ -601,6 +629,7 @@ register SEQRAM {
address 0x061
access_mode RW
count 2
+ dont_generate_debug_code
}
/*
@@ -610,6 +639,7 @@ register SEQRAM {
register SEQADDR0 {
address 0x062
access_mode RW
+ dont_generate_debug_code
}
register SEQADDR1 {
@@ -617,6 +647,7 @@ register SEQADDR1 {
access_mode RW
count 8
mask SEQADDR1_MASK 0x01
+ dont_generate_debug_code
}
/*
@@ -627,35 +658,41 @@ register ACCUM {
address 0x064
access_mode RW
accumulator
+ dont_generate_debug_code
}
register SINDEX {
address 0x065
access_mode RW
sindex
+ dont_generate_debug_code
}
register DINDEX {
address 0x066
access_mode RW
+ dont_generate_debug_code
}
register ALLONES {
address 0x069
access_mode RO
allones
+ dont_generate_debug_code
}
register ALLZEROS {
address 0x06a
access_mode RO
allzeros
+ dont_generate_debug_code
}
register NONE {
address 0x06a
access_mode WO
none
+ dont_generate_debug_code
}
register FLAGS {
@@ -664,16 +701,19 @@ register FLAGS {
count 18
field ZERO 0x02
field CARRY 0x01
+ dont_generate_debug_code
}
register SINDIR {
address 0x06c
access_mode RO
+ dont_generate_debug_code
}
register DINDIR {
address 0x06d
access_mode WO
+ dont_generate_debug_code
}
register FUNCTION1 {
@@ -685,6 +725,7 @@ register STACK {
address 0x06f
access_mode RO
count 5
+ dont_generate_debug_code
}
const STACK_SIZE 4
@@ -716,6 +757,7 @@ register DSCOMMAND0 {
field RAMPS 0x04 /* External SCB RAM Present */
field USCBSIZE32 0x02 /* Use 32byte SCB Page Size */
field CIOPARCKEN 0x01 /* Internal bus parity error enable */
+ dont_generate_debug_code
}
register DSCOMMAND1 {
@@ -724,6 +766,7 @@ register DSCOMMAND1 {
mask DSLATT 0xfc /* PCI latency timer (non-ultra2) */
field HADDLDSEL1 0x02 /* Host Address Load Select Bits */
field HADDLDSEL0 0x01
+ dont_generate_debug_code
}
/*
@@ -735,6 +778,7 @@ register BUSTIME {
count 2
mask BOFF 0xf0
mask BON 0x0f
+ dont_generate_debug_code
}
/*
@@ -749,6 +793,7 @@ register BUSSPD {
mask STBON 0x07
mask DFTHRSH_100 0xc0
mask DFTHRSH_75 0x80
+ dont_generate_debug_code
}
/* aic7850/55/60/70/80/95 only */
@@ -756,6 +801,7 @@ register DSPCISTATUS {
address 0x086
count 4
mask DFTHRSH_100 0xc0
+ dont_generate_debug_code
}
/* aic7890/91/96/97 only */
@@ -764,6 +810,7 @@ register HS_MAILBOX {
mask HOST_MAILBOX 0xF0
mask SEQ_MAILBOX 0x0F
mask HOST_TQINPOS 0x80 /* Boundary at either 0 or 128 */
+ dont_generate_debug_code
}
const HOST_MAILBOX_SHIFT 4
@@ -784,6 +831,7 @@ register HCNTRL {
field INTEN 0x02
field CHIPRST 0x01
field CHIPRSTACK 0x01
+ dont_generate_debug_code
}
/*
@@ -795,12 +843,14 @@ register HADDR {
address 0x088
size 4
access_mode RW
+ dont_generate_debug_code
}
register HCNT {
address 0x08c
size 3
access_mode RW
+ dont_generate_debug_code
}
/*
@@ -810,6 +860,7 @@ register HCNT {
register SCBPTR {
address 0x090
access_mode RW
+ dont_generate_debug_code
}
/*
@@ -878,6 +929,7 @@ register INTSTAT {
mask SEQINT_MASK 0xf0|SEQINT /* SEQINT Status Codes */
mask INT_PEND (BRKADRINT|SEQINT|SCSIINT|CMDCMPLT)
+ dont_generate_debug_code
}
/*
@@ -911,6 +963,7 @@ register CLRINT {
field CLRSCSIINT 0x04
field CLRCMDINT 0x02
field CLRSEQINT 0x01
+ dont_generate_debug_code
}
register DFCNTRL {
@@ -944,6 +997,7 @@ register DFSTATUS {
register DFWADDR {
address 0x95
access_mode RW
+ dont_generate_debug_code
}
register DFRADDR {
@@ -954,6 +1008,7 @@ register DFRADDR {
register DFDAT {
address 0x099
access_mode RW
+ dont_generate_debug_code
}
/*
@@ -967,6 +1022,7 @@ register SCBCNT {
count 1
field SCBAUTO 0x80
mask SCBCNT_MASK 0x1f
+ dont_generate_debug_code
}
/*
@@ -977,6 +1033,7 @@ register QINFIFO {
address 0x09b
access_mode RW
count 12
+ dont_generate_debug_code
}
/*
@@ -996,6 +1053,7 @@ register QOUTFIFO {
address 0x09d
access_mode WO
count 7
+ dont_generate_debug_code
}
register CRCCONTROL1 {
@@ -1008,6 +1066,7 @@ register CRCCONTROL1 {
field CRCREQCHKEN 0x10
field TARGCRCENDEN 0x08
field TARGCRCCNTEN 0x04
+ dont_generate_debug_code
}
@@ -1040,6 +1099,7 @@ register SFUNCT {
access_mode RW
count 4
field ALT_MODE 0x80
+ dont_generate_debug_code
}
/*
@@ -1053,24 +1113,31 @@ scb {
size 4
alias SCB_RESIDUAL_DATACNT
alias SCB_CDB_STORE
+ dont_generate_debug_code
}
SCB_RESIDUAL_SGPTR {
size 4
+ dont_generate_debug_code
}
SCB_SCSI_STATUS {
size 1
+ dont_generate_debug_code
}
SCB_TARGET_PHASES {
size 1
+ dont_generate_debug_code
}
SCB_TARGET_DATA_DIR {
size 1
+ dont_generate_debug_code
}
SCB_TARGET_ITAG {
size 1
+ dont_generate_debug_code
}
SCB_DATAPTR {
size 4
+ dont_generate_debug_code
}
SCB_DATACNT {
/*
@@ -1080,12 +1147,14 @@ scb {
size 4
field SG_LAST_SEG 0x80 /* In the fourth byte */
mask SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */
+ dont_generate_debug_code
}
SCB_SGPTR {
size 4
field SG_RESID_VALID 0x04 /* In the first byte */
field SG_FULL_RESID 0x02 /* In the first byte */
field SG_LIST_NULL 0x01 /* In the first byte */
+ dont_generate_debug_code
}
SCB_CONTROL {
size 1
@@ -1115,22 +1184,27 @@ scb {
}
SCB_CDB_LEN {
size 1
+ dont_generate_debug_code
}
SCB_SCSIRATE {
size 1
+ dont_generate_debug_code
}
SCB_SCSIOFFSET {
size 1
count 1
+ dont_generate_debug_code
}
SCB_NEXT {
size 1
+ dont_generate_debug_code
}
SCB_64_SPARE {
size 16
}
SCB_64_BTT {
size 16
+ dont_generate_debug_code
}
}
@@ -1149,6 +1223,7 @@ register SEECTL_2840 {
field CS_2840 0x04
field CK_2840 0x02
field DO_2840 0x01
+ dont_generate_debug_code
}
register STATUS_2840 {
@@ -1159,6 +1234,7 @@ register STATUS_2840 {
mask BIOS_SEL 0x60
mask ADSEL 0x1e
field DI_2840 0x01
+ dont_generate_debug_code
}
/* --------------------- AIC-7870-only definitions -------------------- */
@@ -1166,18 +1242,22 @@ register STATUS_2840 {
register CCHADDR {
address 0x0E0
size 8
+ dont_generate_debug_code
}
register CCHCNT {
address 0x0E8
+ dont_generate_debug_code
}
register CCSGRAM {
address 0x0E9
+ dont_generate_debug_code
}
register CCSGADDR {
address 0x0EA
+ dont_generate_debug_code
}
register CCSGCTL {
@@ -1186,11 +1266,13 @@ register CCSGCTL {
field CCSGEN 0x08
field SG_FETCH_NEEDED 0x02 /* Bit used for software state */
field CCSGRESET 0x01
+ dont_generate_debug_code
}
register CCSCBCNT {
address 0xEF
count 1
+ dont_generate_debug_code
}
register CCSCBCTL {
@@ -1201,14 +1283,17 @@ register CCSCBCTL {
field CCSCBEN 0x08
field CCSCBDIR 0x04
field CCSCBRESET 0x01
+ dont_generate_debug_code
}
register CCSCBADDR {
address 0x0ED
+ dont_generate_debug_code
}
register CCSCBRAM {
address 0xEC
+ dont_generate_debug_code
}
/*
@@ -1218,23 +1303,28 @@ register SCBBADDR {
address 0x0F0
access_mode RW
count 3
+ dont_generate_debug_code
}
register CCSCBPTR {
address 0x0F1
+ dont_generate_debug_code
}
register HNSCB_QOFF {
address 0x0F4
count 4
+ dont_generate_debug_code
}
register SNSCB_QOFF {
address 0x0F6
+ dont_generate_debug_code
}
register SDSCB_QOFF {
address 0x0F8
+ dont_generate_debug_code
}
register QOFF_CTLSTA {
@@ -1244,6 +1334,7 @@ register QOFF_CTLSTA {
field SDSCB_ROLLOVER 0x10
mask SCB_QSIZE 0x07
mask SCB_QSIZE_256 0x06
+ dont_generate_debug_code
}
register DFF_THRSH {
@@ -1267,6 +1358,7 @@ register DFF_THRSH {
mask WR_DFTHRSH_90 0x60
mask WR_DFTHRSH_MAX 0x70
count 4
+ dont_generate_debug_code
}
register SG_CACHE_PRE {
@@ -1275,6 +1367,7 @@ register SG_CACHE_PRE {
mask SG_ADDR_MASK 0xf8
field LAST_SEG 0x02
field LAST_SEG_DONE 0x01
+ dont_generate_debug_code
}
register SG_CACHE_SHADOW {
@@ -1283,6 +1376,7 @@ register SG_CACHE_SHADOW {
mask SG_ADDR_MASK 0xf8
field LAST_SEG 0x02
field LAST_SEG_DONE 0x01
+ dont_generate_debug_code
}
/* ---------------------- Scratch RAM Offsets ------------------------- */
/* These offsets are either to values that are initialized by the board's
@@ -1309,6 +1403,7 @@ scratch_ram {
BUSY_TARGETS {
alias TARG_SCSIRATE
size 16
+ dont_generate_debug_code
}
/*
* Bit vector of targets that have ULTRA enabled as set by
@@ -1321,6 +1416,7 @@ scratch_ram {
alias CMDSIZE_TABLE
size 2
count 2
+ dont_generate_debug_code
}
/*
* Bit vector of targets that have disconnection disabled as set by
@@ -1331,6 +1427,7 @@ scratch_ram {
DISC_DSB {
size 2
count 6
+ dont_generate_debug_code
}
CMDSIZE_TABLE_TAIL {
size 4
@@ -1341,12 +1438,14 @@ scratch_ram {
*/
MWI_RESIDUAL {
size 1
+ dont_generate_debug_code
}
/*
* SCBID of the next SCB to be started by the controller.
*/
NEXT_QUEUED_SCB {
size 1
+ dont_generate_debug_code
}
/*
* Single byte buffer used to designate the type or message
@@ -1354,6 +1453,7 @@ scratch_ram {
*/
MSG_OUT {
size 1
+ dont_generate_debug_code
}
/* Parameters for DMA Logic */
DMAPARAMS {
@@ -1369,6 +1469,7 @@ scratch_ram {
field DIRECTION 0x04 /* Set indicates PCI->SCSI */
field FIFOFLUSH 0x02
field FIFORESET 0x01
+ dont_generate_debug_code
}
SEQ_FLAGS {
size 1
@@ -1390,9 +1491,11 @@ scratch_ram {
*/
SAVED_SCSIID {
size 1
+ dont_generate_debug_code
}
SAVED_LUN {
size 1
+ dont_generate_debug_code
}
/*
* The last bus phase as seen by the sequencer.
@@ -1417,6 +1520,7 @@ scratch_ram {
*/
WAITING_SCBH {
size 1
+ dont_generate_debug_code
}
/*
* head of list of SCBs that are
@@ -1425,6 +1529,7 @@ scratch_ram {
*/
DISCONNECTED_SCBH {
size 1
+ dont_generate_debug_code
}
/*
* head of list of SCBs that are
@@ -1432,6 +1537,7 @@ scratch_ram {
*/
FREE_SCBH {
size 1
+ dont_generate_debug_code
}
/*
* head of list of SCBs that have
@@ -1446,6 +1552,7 @@ scratch_ram {
*/
HSCB_ADDR {
size 4
+ dont_generate_debug_code
}
/*
* Base address of our shared data with the kernel driver in host
@@ -1454,15 +1561,19 @@ scratch_ram {
*/
SHARED_DATA_ADDR {
size 4
+ dont_generate_debug_code
}
KERNEL_QINPOS {
size 1
+ dont_generate_debug_code
}
QINPOS {
size 1
+ dont_generate_debug_code
}
QOUTPOS {
size 1
+ dont_generate_debug_code
}
/*
* Kernel and sequencer offsets into the queue of
@@ -1471,9 +1582,11 @@ scratch_ram {
*/
KERNEL_TQINPOS {
size 1
+ dont_generate_debug_code
}
TQINPOS {
size 1
+ dont_generate_debug_code
}
ARG_1 {
size 1
@@ -1486,10 +1599,12 @@ scratch_ram {
mask CONT_MSG_LOOP 0x04
mask CONT_TARG_SESSION 0x02
alias RETURN_1
+ dont_generate_debug_code
}
ARG_2 {
size 1
alias RETURN_2
+ dont_generate_debug_code
}
/*
@@ -1498,6 +1613,7 @@ scratch_ram {
LAST_MSG {
size 1
alias TARG_IMMEDIATE_SCB
+ dont_generate_debug_code
}
/*
@@ -1513,6 +1629,7 @@ scratch_ram {
field ENAUTOATNO 0x08
field ENAUTOATNI 0x04
field ENAUTOATNP 0x02
+ dont_generate_debug_code
}
}
@@ -1533,12 +1650,14 @@ scratch_ram {
field HA_274_EXTENDED_TRANS 0x01
alias INITIATOR_TAG
count 1
+ dont_generate_debug_code
}
SEQ_FLAGS2 {
size 1
field SCB_DMA 0x01
field TARGET_MSG_PENDING 0x02
+ dont_generate_debug_code
}
}
@@ -1562,6 +1681,7 @@ scratch_ram {
field ENSPCHK 0x20
mask HSCSIID 0x07 /* our SCSI ID */
mask HWSCSIID 0x0f /* our SCSI ID if Wide Bus */
+ dont_generate_debug_code
}
INTDEF {
address 0x05c
@@ -1569,11 +1689,13 @@ scratch_ram {
count 1
field EDGE_TRIG 0x80
mask VECTOR 0x0f
+ dont_generate_debug_code
}
HOSTCONF {
address 0x05d
size 1
count 1
+ dont_generate_debug_code
}
HA_274_BIOSCTRL {
address 0x05f
@@ -1582,6 +1704,7 @@ scratch_ram {
mask BIOSMODE 0x30
mask BIOSDISABLED 0x30
field CHANNEL_B_PRIMARY 0x08
+ dont_generate_debug_code
}
}
@@ -1595,6 +1718,7 @@ scratch_ram {
TARG_OFFSET {
size 16
count 1
+ dont_generate_debug_code
}
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 0ae2b4605d0..e6f2bb7365e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -814,6 +814,7 @@ ahc_intr(struct ahc_softc *ahc)
static void
ahc_restart(struct ahc_softc *ahc)
{
+ uint8_t sblkctl;
ahc_pause(ahc);
@@ -868,6 +869,12 @@ ahc_restart(struct ahc_softc *ahc)
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
+ /*
+ * Take the LED out of diagnostic mode on PM resume, too
+ */
+ sblkctl = ahc_inb(ahc, SBLKCTL);
+ ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
+
ahc_unpause(ahc);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
index 2ce1febca20..e821082a4f4 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
@@ -27,20 +27,6 @@ ahc_reg_print_t ahc_sxfrctl0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sxfrctl1_print;
-#else
-#define ahc_sxfrctl1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SXFRCTL1", 0x02, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsisigo_print;
-#else
-#define ahc_scsisigo_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSISIGO", 0x03, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_scsisigi_print;
#else
#define ahc_scsisigi_print(regvalue, cur_col, wrap) \
@@ -55,55 +41,6 @@ ahc_reg_print_t ahc_scsirate_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsiid_print;
-#else
-#define ahc_scsiid_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSIID", 0x05, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsidatl_print;
-#else
-#define ahc_scsidatl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSIDATL", 0x06, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsidath_print;
-#else
-#define ahc_scsidath_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSIDATH", 0x07, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_stcnt_print;
-#else
-#define ahc_stcnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "STCNT", 0x08, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_optionmode_print;
-#else
-#define ahc_optionmode_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "OPTIONMODE", 0x08, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_targcrccnt_print;
-#else
-#define ahc_targcrccnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "TARGCRCCNT", 0x0a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_clrsint0_print;
-#else
-#define ahc_clrsint0_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CLRSINT0", 0x0b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_sstat0_print;
#else
#define ahc_sstat0_print(regvalue, cur_col, wrap) \
@@ -111,13 +48,6 @@ ahc_reg_print_t ahc_sstat0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_clrsint1_print;
-#else
-#define ahc_clrsint1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CLRSINT1", 0x0c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_sstat1_print;
#else
#define ahc_sstat1_print(regvalue, cur_col, wrap) \
@@ -139,13 +69,6 @@ ahc_reg_print_t ahc_sstat3_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsiid_ultra2_print;
-#else
-#define ahc_scsiid_ultra2_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSIID_ULTRA2", 0x0f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_simode0_print;
#else
#define ahc_simode0_print(regvalue, cur_col, wrap) \
@@ -167,76 +90,6 @@ ahc_reg_print_t ahc_scsibusl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsibush_print;
-#else
-#define ahc_scsibush_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSIBUSH", 0x13, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sxfrctl2_print;
-#else
-#define ahc_sxfrctl2_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SXFRCTL2", 0x13, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_shaddr_print;
-#else
-#define ahc_shaddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SHADDR", 0x14, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seltimer_print;
-#else
-#define ahc_seltimer_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SELTIMER", 0x18, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_selid_print;
-#else
-#define ahc_selid_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SELID", 0x19, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scamctl_print;
-#else
-#define ahc_scamctl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCAMCTL", 0x1a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_targid_print;
-#else
-#define ahc_targid_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "TARGID", 0x1b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_spiocap_print;
-#else
-#define ahc_spiocap_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SPIOCAP", 0x1b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_brdctl_print;
-#else
-#define ahc_brdctl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "BRDCTL", 0x1d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seectl_print;
-#else
-#define ahc_seectl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SEECTL", 0x1e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_sblkctl_print;
#else
#define ahc_sblkctl_print(regvalue, cur_col, wrap) \
@@ -244,62 +97,6 @@ ahc_reg_print_t ahc_sblkctl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_busy_targets_print;
-#else
-#define ahc_busy_targets_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "BUSY_TARGETS", 0x20, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ultra_enb_print;
-#else
-#define ahc_ultra_enb_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "ULTRA_ENB", 0x30, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_disc_dsb_print;
-#else
-#define ahc_disc_dsb_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DISC_DSB", 0x32, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_cmdsize_table_tail_print;
-#else
-#define ahc_cmdsize_table_tail_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CMDSIZE_TABLE_TAIL", 0x34, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_mwi_residual_print;
-#else
-#define ahc_mwi_residual_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "MWI_RESIDUAL", 0x38, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_next_queued_scb_print;
-#else
-#define ahc_next_queued_scb_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "NEXT_QUEUED_SCB", 0x39, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_msg_out_print;
-#else
-#define ahc_msg_out_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "MSG_OUT", 0x3a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dmaparams_print;
-#else
-#define ahc_dmaparams_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DMAPARAMS", 0x3b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_seq_flags_print;
#else
#define ahc_seq_flags_print(regvalue, cur_col, wrap) \
@@ -307,20 +104,6 @@ ahc_reg_print_t ahc_seq_flags_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_saved_scsiid_print;
-#else
-#define ahc_saved_scsiid_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SAVED_SCSIID", 0x3d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_saved_lun_print;
-#else
-#define ahc_saved_lun_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SAVED_LUN", 0x3e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_lastphase_print;
#else
#define ahc_lastphase_print(regvalue, cur_col, wrap) \
@@ -328,153 +111,6 @@ ahc_reg_print_t ahc_lastphase_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_waiting_scbh_print;
-#else
-#define ahc_waiting_scbh_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "WAITING_SCBH", 0x40, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_disconnected_scbh_print;
-#else
-#define ahc_disconnected_scbh_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DISCONNECTED_SCBH", 0x41, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_free_scbh_print;
-#else
-#define ahc_free_scbh_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "FREE_SCBH", 0x42, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_complete_scbh_print;
-#else
-#define ahc_complete_scbh_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "COMPLETE_SCBH", 0x43, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_hscb_addr_print;
-#else
-#define ahc_hscb_addr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HSCB_ADDR", 0x44, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_shared_data_addr_print;
-#else
-#define ahc_shared_data_addr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x48, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_kernel_qinpos_print;
-#else
-#define ahc_kernel_qinpos_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "KERNEL_QINPOS", 0x4c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qinpos_print;
-#else
-#define ahc_qinpos_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QINPOS", 0x4d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qoutpos_print;
-#else
-#define ahc_qoutpos_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QOUTPOS", 0x4e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_kernel_tqinpos_print;
-#else
-#define ahc_kernel_tqinpos_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "KERNEL_TQINPOS", 0x4f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_tqinpos_print;
-#else
-#define ahc_tqinpos_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "TQINPOS", 0x50, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_arg_1_print;
-#else
-#define ahc_arg_1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "ARG_1", 0x51, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_arg_2_print;
-#else
-#define ahc_arg_2_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "ARG_2", 0x52, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_last_msg_print;
-#else
-#define ahc_last_msg_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "LAST_MSG", 0x53, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsiseq_template_print;
-#else
-#define ahc_scsiseq_template_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x54, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ha_274_biosglobal_print;
-#else
-#define ahc_ha_274_biosglobal_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HA_274_BIOSGLOBAL", 0x56, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seq_flags2_print;
-#else
-#define ahc_seq_flags2_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SEQ_FLAGS2", 0x57, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scsiconf_print;
-#else
-#define ahc_scsiconf_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCSICONF", 0x5a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_intdef_print;
-#else
-#define ahc_intdef_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "INTDEF", 0x5c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_hostconf_print;
-#else
-#define ahc_hostconf_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HOSTCONF", 0x5d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ha_274_biosctrl_print;
-#else
-#define ahc_ha_274_biosctrl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HA_274_BIOSCTRL", 0x5f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_seqctl_print;
#else
#define ahc_seqctl_print(regvalue, cur_col, wrap) \
@@ -482,111 +118,6 @@ ahc_reg_print_t ahc_seqctl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seqram_print;
-#else
-#define ahc_seqram_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SEQRAM", 0x61, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seqaddr0_print;
-#else
-#define ahc_seqaddr0_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SEQADDR0", 0x62, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seqaddr1_print;
-#else
-#define ahc_seqaddr1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SEQADDR1", 0x63, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_accum_print;
-#else
-#define ahc_accum_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "ACCUM", 0x64, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sindex_print;
-#else
-#define ahc_sindex_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SINDEX", 0x65, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dindex_print;
-#else
-#define ahc_dindex_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DINDEX", 0x66, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_allones_print;
-#else
-#define ahc_allones_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "ALLONES", 0x69, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_allzeros_print;
-#else
-#define ahc_allzeros_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "ALLZEROS", 0x6a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_none_print;
-#else
-#define ahc_none_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "NONE", 0x6a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_flags_print;
-#else
-#define ahc_flags_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "FLAGS", 0x6b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sindir_print;
-#else
-#define ahc_sindir_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SINDIR", 0x6c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dindir_print;
-#else
-#define ahc_dindir_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DINDIR", 0x6d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_function1_print;
-#else
-#define ahc_function1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "FUNCTION1", 0x6e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_stack_print;
-#else
-#define ahc_stack_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "STACK", 0x6f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_targ_offset_print;
-#else
-#define ahc_targ_offset_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "TARG_OFFSET", 0x70, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_sram_base_print;
#else
#define ahc_sram_base_print(regvalue, cur_col, wrap) \
@@ -594,97 +125,6 @@ ahc_reg_print_t ahc_sram_base_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_bctl_print;
-#else
-#define ahc_bctl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "BCTL", 0x84, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dscommand0_print;
-#else
-#define ahc_dscommand0_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DSCOMMAND0", 0x84, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_bustime_print;
-#else
-#define ahc_bustime_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "BUSTIME", 0x85, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dscommand1_print;
-#else
-#define ahc_dscommand1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DSCOMMAND1", 0x85, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_busspd_print;
-#else
-#define ahc_busspd_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "BUSSPD", 0x86, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_hs_mailbox_print;
-#else
-#define ahc_hs_mailbox_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HS_MAILBOX", 0x86, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dspcistatus_print;
-#else
-#define ahc_dspcistatus_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DSPCISTATUS", 0x86, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_hcntrl_print;
-#else
-#define ahc_hcntrl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HCNTRL", 0x87, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_haddr_print;
-#else
-#define ahc_haddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HADDR", 0x88, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_hcnt_print;
-#else
-#define ahc_hcnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HCNT", 0x8c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scbptr_print;
-#else
-#define ahc_scbptr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCBPTR", 0x90, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_intstat_print;
-#else
-#define ahc_intstat_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "INTSTAT", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_clrint_print;
-#else
-#define ahc_clrint_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CLRINT", 0x92, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_error_print;
#else
#define ahc_error_print(regvalue, cur_col, wrap) \
@@ -706,69 +146,6 @@ ahc_reg_print_t ahc_dfstatus_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dfwaddr_print;
-#else
-#define ahc_dfwaddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DFWADDR", 0x95, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dfraddr_print;
-#else
-#define ahc_dfraddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DFRADDR", 0x97, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dfdat_print;
-#else
-#define ahc_dfdat_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DFDAT", 0x99, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scbcnt_print;
-#else
-#define ahc_scbcnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCBCNT", 0x9a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qinfifo_print;
-#else
-#define ahc_qinfifo_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QINFIFO", 0x9b, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qincnt_print;
-#else
-#define ahc_qincnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QINCNT", 0x9c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qoutfifo_print;
-#else
-#define ahc_qoutfifo_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QOUTFIFO", 0x9d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_crccontrol1_print;
-#else
-#define ahc_crccontrol1_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CRCCONTROL1", 0x9d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qoutcnt_print;
-#else
-#define ahc_qoutcnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QOUTCNT", 0x9e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_scsiphase_print;
#else
#define ahc_scsiphase_print(regvalue, cur_col, wrap) \
@@ -776,13 +153,6 @@ ahc_reg_print_t ahc_scsiphase_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sfunct_print;
-#else
-#define ahc_sfunct_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_scb_base_print;
#else
#define ahc_scb_base_print(regvalue, cur_col, wrap) \
@@ -790,69 +160,6 @@ ahc_reg_print_t ahc_scb_base_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_cdb_ptr_print;
-#else
-#define ahc_scb_cdb_ptr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_CDB_PTR", 0xa0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_residual_sgptr_print;
-#else
-#define ahc_scb_residual_sgptr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_RESIDUAL_SGPTR", 0xa4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_scsi_status_print;
-#else
-#define ahc_scb_scsi_status_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_SCSI_STATUS", 0xa8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_target_phases_print;
-#else
-#define ahc_scb_target_phases_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_TARGET_PHASES", 0xa9, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_target_data_dir_print;
-#else
-#define ahc_scb_target_data_dir_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_TARGET_DATA_DIR", 0xaa, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_target_itag_print;
-#else
-#define ahc_scb_target_itag_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_TARGET_ITAG", 0xab, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_dataptr_print;
-#else
-#define ahc_scb_dataptr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_DATAPTR", 0xac, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_datacnt_print;
-#else
-#define ahc_scb_datacnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_DATACNT", 0xb0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_sgptr_print;
-#else
-#define ahc_scb_sgptr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_SGPTR", 0xb4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahc_reg_print_t ahc_scb_control_print;
#else
#define ahc_scb_control_print(regvalue, cur_col, wrap) \
@@ -880,188 +187,6 @@ ahc_reg_print_t ahc_scb_tag_print;
ahc_print_register(NULL, 0, "SCB_TAG", 0xbb, regvalue, cur_col, wrap)
#endif
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_cdb_len_print;
-#else
-#define ahc_scb_cdb_len_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_CDB_LEN", 0xbc, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_scsirate_print;
-#else
-#define ahc_scb_scsirate_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_SCSIRATE", 0xbd, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_scsioffset_print;
-#else
-#define ahc_scb_scsioffset_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_SCSIOFFSET", 0xbe, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_next_print;
-#else
-#define ahc_scb_next_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_NEXT", 0xbf, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_64_spare_print;
-#else
-#define ahc_scb_64_spare_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_64_SPARE", 0xc0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_seectl_2840_print;
-#else
-#define ahc_seectl_2840_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SEECTL_2840", 0xc0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_status_2840_print;
-#else
-#define ahc_status_2840_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "STATUS_2840", 0xc1, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scb_64_btt_print;
-#else
-#define ahc_scb_64_btt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCB_64_BTT", 0xd0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_cchaddr_print;
-#else
-#define ahc_cchaddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCHADDR", 0xe0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_cchcnt_print;
-#else
-#define ahc_cchcnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCHCNT", 0xe8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccsgram_print;
-#else
-#define ahc_ccsgram_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSGRAM", 0xe9, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccsgaddr_print;
-#else
-#define ahc_ccsgaddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSGADDR", 0xea, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccsgctl_print;
-#else
-#define ahc_ccsgctl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSGCTL", 0xeb, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccscbram_print;
-#else
-#define ahc_ccscbram_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSCBRAM", 0xec, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccscbaddr_print;
-#else
-#define ahc_ccscbaddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSCBADDR", 0xed, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccscbctl_print;
-#else
-#define ahc_ccscbctl_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSCBCTL", 0xee, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccscbcnt_print;
-#else
-#define ahc_ccscbcnt_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSCBCNT", 0xef, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_scbbaddr_print;
-#else
-#define ahc_scbbaddr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SCBBADDR", 0xf0, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_ccscbptr_print;
-#else
-#define ahc_ccscbptr_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "CCSCBPTR", 0xf1, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_hnscb_qoff_print;
-#else
-#define ahc_hnscb_qoff_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "HNSCB_QOFF", 0xf4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_snscb_qoff_print;
-#else
-#define ahc_snscb_qoff_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SNSCB_QOFF", 0xf6, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sdscb_qoff_print;
-#else
-#define ahc_sdscb_qoff_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SDSCB_QOFF", 0xf8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_qoff_ctlsta_print;
-#else
-#define ahc_qoff_ctlsta_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "QOFF_CTLSTA", 0xfa, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_dff_thrsh_print;
-#else
-#define ahc_dff_thrsh_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "DFF_THRSH", 0xfb, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sg_cache_shadow_print;
-#else
-#define ahc_sg_cache_shadow_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SG_CACHE_SHADOW", 0xfc, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahc_reg_print_t ahc_sg_cache_pre_print;
-#else
-#define ahc_sg_cache_pre_print(regvalue, cur_col, wrap) \
- ahc_print_register(NULL, 0, "SG_CACHE_PRE", 0xfc, regvalue, cur_col, wrap)
-#endif
-
#define SCSISEQ 0x00
#define TEMODE 0x80
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
index 309a562b009..9f9b88047d0 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
@@ -43,48 +43,6 @@ ahc_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x01, regvalue, cur_col, wrap));
}
-static const ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
- { "STPWEN", 0x01, 0x01 },
- { "ACTNEGEN", 0x02, 0x02 },
- { "ENSTIMER", 0x04, 0x04 },
- { "ENSPCHK", 0x20, 0x20 },
- { "SWRAPEN", 0x40, 0x40 },
- { "BITBUCKET", 0x80, 0x80 },
- { "STIMESEL", 0x18, 0x18 }
-};
-
-int
-ahc_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SXFRCTL1_parse_table, 7, "SXFRCTL1",
- 0x02, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
- { "ACKO", 0x01, 0x01 },
- { "REQO", 0x02, 0x02 },
- { "BSYO", 0x04, 0x04 },
- { "SELO", 0x08, 0x08 },
- { "ATNO", 0x10, 0x10 },
- { "MSGO", 0x20, 0x20 },
- { "IOO", 0x40, 0x40 },
- { "CDO", 0x80, 0x80 },
- { "P_DATAOUT", 0x00, 0x00 },
- { "P_DATAIN", 0x40, 0x40 },
- { "P_COMMAND", 0x80, 0x80 },
- { "P_MESGOUT", 0xa0, 0xa0 },
- { "P_STATUS", 0xc0, 0xc0 },
- { "PHASE_MASK", 0xe0, 0xe0 },
- { "P_MESGIN", 0xe0, 0xe0 }
-};
-
-int
-ahc_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCSISIGO_parse_table, 15, "SCSISIGO",
- 0x03, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
{ "ACKI", 0x01, 0x01 },
{ "REQI", 0x02, 0x02 },
@@ -128,77 +86,6 @@ ahc_scsirate_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x04, regvalue, cur_col, wrap));
}
-static const ahc_reg_parse_entry_t SCSIID_parse_table[] = {
- { "TWIN_CHNLB", 0x80, 0x80 },
- { "OID", 0x0f, 0x0f },
- { "TWIN_TID", 0x70, 0x70 },
- { "SOFS_ULTRA2", 0x7f, 0x7f },
- { "TID", 0xf0, 0xf0 }
-};
-
-int
-ahc_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCSIID_parse_table, 5, "SCSIID",
- 0x05, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scsidatl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCSIDATL",
- 0x06, regvalue, cur_col, wrap));
-}
-
-int
-ahc_stcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "STCNT",
- 0x08, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
- { "DIS_MSGIN_DUALEDGE", 0x01, 0x01 },
- { "AUTO_MSGOUT_DE", 0x02, 0x02 },
- { "SCSIDATL_IMGEN", 0x04, 0x04 },
- { "EXPPHASEDIS", 0x08, 0x08 },
- { "BUSFREEREV", 0x10, 0x10 },
- { "ATNMGMNTEN", 0x20, 0x20 },
- { "AUTOACKEN", 0x40, 0x40 },
- { "AUTORATEEN", 0x80, 0x80 },
- { "OPTIONMODE_DEFAULTS",0x03, 0x03 }
-};
-
-int
-ahc_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(OPTIONMODE_parse_table, 9, "OPTIONMODE",
- 0x08, regvalue, cur_col, wrap));
-}
-
-int
-ahc_targcrccnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "TARGCRCCNT",
- 0x0a, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
- { "CLRSPIORDY", 0x02, 0x02 },
- { "CLRSWRAP", 0x08, 0x08 },
- { "CLRIOERR", 0x08, 0x08 },
- { "CLRSELINGO", 0x10, 0x10 },
- { "CLRSELDI", 0x20, 0x20 },
- { "CLRSELDO", 0x40, 0x40 }
-};
-
-int
-ahc_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(CLRSINT0_parse_table, 6, "CLRSINT0",
- 0x0b, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
{ "DMADONE", 0x01, 0x01 },
{ "SPIORDY", 0x02, 0x02 },
@@ -218,23 +105,6 @@ ahc_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0b, regvalue, cur_col, wrap));
}
-static const ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
- { "CLRREQINIT", 0x01, 0x01 },
- { "CLRPHASECHG", 0x02, 0x02 },
- { "CLRSCSIPERR", 0x04, 0x04 },
- { "CLRBUSFREE", 0x08, 0x08 },
- { "CLRSCSIRSTI", 0x20, 0x20 },
- { "CLRATNO", 0x40, 0x40 },
- { "CLRSELTIMEO", 0x80, 0x80 }
-};
-
-int
-ahc_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(CLRSINT1_parse_table, 7, "CLRSINT1",
- 0x0c, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
{ "REQINIT", 0x01, 0x01 },
{ "PHASECHG", 0x02, 0x02 },
@@ -284,18 +154,6 @@ ahc_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0e, regvalue, cur_col, wrap));
}
-static const ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
- { "OID", 0x0f, 0x0f },
- { "TID", 0xf0, 0xf0 }
-};
-
-int
-ahc_scsiid_ultra2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCSIID_ULTRA2_parse_table, 2, "SCSIID_ULTRA2",
- 0x0f, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
{ "ENDMADONE", 0x01, 0x01 },
{ "ENSPIORDY", 0x02, 0x02 },
@@ -339,107 +197,6 @@ ahc_scsibusl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x12, regvalue, cur_col, wrap));
}
-int
-ahc_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SHADDR",
- 0x14, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
- { "STAGE1", 0x01, 0x01 },
- { "STAGE2", 0x02, 0x02 },
- { "STAGE3", 0x04, 0x04 },
- { "STAGE4", 0x08, 0x08 },
- { "STAGE5", 0x10, 0x10 },
- { "STAGE6", 0x20, 0x20 }
-};
-
-int
-ahc_seltimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SELTIMER_parse_table, 6, "SELTIMER",
- 0x18, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SELID_parse_table[] = {
- { "ONEBIT", 0x08, 0x08 },
- { "SELID_MASK", 0xf0, 0xf0 }
-};
-
-int
-ahc_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SELID_parse_table, 2, "SELID",
- 0x19, regvalue, cur_col, wrap));
-}
-
-int
-ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "TARGID",
- 0x1b, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
- { "SSPIOCPS", 0x01, 0x01 },
- { "ROM", 0x02, 0x02 },
- { "EEPROM", 0x04, 0x04 },
- { "SEEPROM", 0x08, 0x08 },
- { "EXT_BRDCTL", 0x10, 0x10 },
- { "SOFTCMDEN", 0x20, 0x20 },
- { "SOFT0", 0x40, 0x40 },
- { "SOFT1", 0x80, 0x80 }
-};
-
-int
-ahc_spiocap_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SPIOCAP_parse_table, 8, "SPIOCAP",
- 0x1b, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
- { "BRDCTL0", 0x01, 0x01 },
- { "BRDSTB_ULTRA2", 0x01, 0x01 },
- { "BRDCTL1", 0x02, 0x02 },
- { "BRDRW_ULTRA2", 0x02, 0x02 },
- { "BRDRW", 0x04, 0x04 },
- { "BRDDAT2", 0x04, 0x04 },
- { "BRDCS", 0x08, 0x08 },
- { "BRDDAT3", 0x08, 0x08 },
- { "BRDSTB", 0x10, 0x10 },
- { "BRDDAT4", 0x10, 0x10 },
- { "BRDDAT5", 0x20, 0x20 },
- { "BRDDAT6", 0x40, 0x40 },
- { "BRDDAT7", 0x80, 0x80 }
-};
-
-int
-ahc_brdctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(BRDCTL_parse_table, 13, "BRDCTL",
- 0x1d, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SEECTL_parse_table[] = {
- { "SEEDI", 0x01, 0x01 },
- { "SEEDO", 0x02, 0x02 },
- { "SEECK", 0x04, 0x04 },
- { "SEECS", 0x08, 0x08 },
- { "SEERDY", 0x10, 0x10 },
- { "SEEMS", 0x20, 0x20 },
- { "EXTARBREQ", 0x40, 0x40 },
- { "EXTARBACK", 0x80, 0x80 }
-};
-
-int
-ahc_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SEECTL_parse_table, 8, "SEECTL",
- 0x1e, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
{ "XCVR", 0x01, 0x01 },
{ "SELWIDE", 0x02, 0x02 },
@@ -458,68 +215,6 @@ ahc_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1f, regvalue, cur_col, wrap));
}
-int
-ahc_busy_targets_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "BUSY_TARGETS",
- 0x20, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ultra_enb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "ULTRA_ENB",
- 0x30, regvalue, cur_col, wrap));
-}
-
-int
-ahc_disc_dsb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "DISC_DSB",
- 0x32, regvalue, cur_col, wrap));
-}
-
-int
-ahc_mwi_residual_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "MWI_RESIDUAL",
- 0x38, regvalue, cur_col, wrap));
-}
-
-int
-ahc_next_queued_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "NEXT_QUEUED_SCB",
- 0x39, regvalue, cur_col, wrap));
-}
-
-int
-ahc_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "MSG_OUT",
- 0x3a, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
- { "FIFORESET", 0x01, 0x01 },
- { "FIFOFLUSH", 0x02, 0x02 },
- { "DIRECTION", 0x04, 0x04 },
- { "HDMAEN", 0x08, 0x08 },
- { "HDMAENACK", 0x08, 0x08 },
- { "SDMAEN", 0x10, 0x10 },
- { "SDMAENACK", 0x10, 0x10 },
- { "SCSIEN", 0x20, 0x20 },
- { "WIDEODD", 0x40, 0x40 },
- { "PRELOADEN", 0x80, 0x80 }
-};
-
-int
-ahc_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS",
- 0x3b, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
{ "NO_DISCONNECT", 0x01, 0x01 },
{ "SPHASE_PENDING", 0x02, 0x02 },
@@ -539,20 +234,6 @@ ahc_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3c, regvalue, cur_col, wrap));
}
-int
-ahc_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SAVED_SCSIID",
- 0x3d, regvalue, cur_col, wrap));
-}
-
-int
-ahc_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SAVED_LUN",
- 0x3e, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
{ "MSGI", 0x20, 0x20 },
{ "IOI", 0x40, 0x40 },
@@ -574,193 +255,6 @@ ahc_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3f, regvalue, cur_col, wrap));
}
-int
-ahc_waiting_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "WAITING_SCBH",
- 0x40, regvalue, cur_col, wrap));
-}
-
-int
-ahc_disconnected_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "DISCONNECTED_SCBH",
- 0x41, regvalue, cur_col, wrap));
-}
-
-int
-ahc_free_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "FREE_SCBH",
- 0x42, regvalue, cur_col, wrap));
-}
-
-int
-ahc_hscb_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "HSCB_ADDR",
- 0x44, regvalue, cur_col, wrap));
-}
-
-int
-ahc_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SHARED_DATA_ADDR",
- 0x48, regvalue, cur_col, wrap));
-}
-
-int
-ahc_kernel_qinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "KERNEL_QINPOS",
- 0x4c, regvalue, cur_col, wrap));
-}
-
-int
-ahc_qinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "QINPOS",
- 0x4d, regvalue, cur_col, wrap));
-}
-
-int
-ahc_qoutpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "QOUTPOS",
- 0x4e, regvalue, cur_col, wrap));
-}
-
-int
-ahc_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "KERNEL_TQINPOS",
- 0x4f, regvalue, cur_col, wrap));
-}
-
-int
-ahc_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "TQINPOS",
- 0x50, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t ARG_1_parse_table[] = {
- { "CONT_TARG_SESSION", 0x02, 0x02 },
- { "CONT_MSG_LOOP", 0x04, 0x04 },
- { "EXIT_MSG_LOOP", 0x08, 0x08 },
- { "MSGOUT_PHASEMIS", 0x10, 0x10 },
- { "SEND_REJ", 0x20, 0x20 },
- { "SEND_SENSE", 0x40, 0x40 },
- { "SEND_MSG", 0x80, 0x80 }
-};
-
-int
-ahc_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(ARG_1_parse_table, 7, "ARG_1",
- 0x51, regvalue, cur_col, wrap));
-}
-
-int
-ahc_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "ARG_2",
- 0x52, regvalue, cur_col, wrap));
-}
-
-int
-ahc_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "LAST_MSG",
- 0x53, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
- { "ENAUTOATNP", 0x02, 0x02 },
- { "ENAUTOATNI", 0x04, 0x04 },
- { "ENAUTOATNO", 0x08, 0x08 },
- { "ENRSELI", 0x10, 0x10 },
- { "ENSELI", 0x20, 0x20 },
- { "ENSELO", 0x40, 0x40 }
-};
-
-int
-ahc_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE",
- 0x54, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
- { "HA_274_EXTENDED_TRANS",0x01, 0x01 }
-};
-
-int
-ahc_ha_274_biosglobal_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(HA_274_BIOSGLOBAL_parse_table, 1, "HA_274_BIOSGLOBAL",
- 0x56, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
- { "SCB_DMA", 0x01, 0x01 },
- { "TARGET_MSG_PENDING", 0x02, 0x02 }
-};
-
-int
-ahc_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
- 0x57, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
- { "ENSPCHK", 0x20, 0x20 },
- { "RESET_SCSI", 0x40, 0x40 },
- { "TERM_ENB", 0x80, 0x80 },
- { "HSCSIID", 0x07, 0x07 },
- { "HWSCSIID", 0x0f, 0x0f }
-};
-
-int
-ahc_scsiconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCSICONF_parse_table, 5, "SCSICONF",
- 0x5a, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t INTDEF_parse_table[] = {
- { "EDGE_TRIG", 0x80, 0x80 },
- { "VECTOR", 0x0f, 0x0f }
-};
-
-int
-ahc_intdef_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(INTDEF_parse_table, 2, "INTDEF",
- 0x5c, regvalue, cur_col, wrap));
-}
-
-int
-ahc_hostconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "HOSTCONF",
- 0x5d, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
- { "CHANNEL_B_PRIMARY", 0x08, 0x08 },
- { "BIOSMODE", 0x30, 0x30 },
- { "BIOSDISABLED", 0x30, 0x30 }
-};
-
-int
-ahc_ha_274_biosctrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(HA_274_BIOSCTRL_parse_table, 3, "HA_274_BIOSCTRL",
- 0x5f, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
{ "LOADRAM", 0x01, 0x01 },
{ "SEQRESET", 0x02, 0x02 },
@@ -780,285 +274,12 @@ ahc_seqctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahc_seqram_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SEQRAM",
- 0x61, regvalue, cur_col, wrap));
-}
-
-int
-ahc_seqaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SEQADDR0",
- 0x62, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
- { "SEQADDR1_MASK", 0x01, 0x01 }
-};
-
-int
-ahc_seqaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SEQADDR1_parse_table, 1, "SEQADDR1",
- 0x63, regvalue, cur_col, wrap));
-}
-
-int
-ahc_accum_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "ACCUM",
- 0x64, regvalue, cur_col, wrap));
-}
-
-int
-ahc_sindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SINDEX",
- 0x65, regvalue, cur_col, wrap));
-}
-
-int
-ahc_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "DINDEX",
- 0x66, regvalue, cur_col, wrap));
-}
-
-int
-ahc_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "ALLONES",
- 0x69, regvalue, cur_col, wrap));
-}
-
-int
-ahc_allzeros_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "ALLZEROS",
- 0x6a, regvalue, cur_col, wrap));
-}
-
-int
-ahc_none_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "NONE",
- 0x6a, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t FLAGS_parse_table[] = {
- { "CARRY", 0x01, 0x01 },
- { "ZERO", 0x02, 0x02 }
-};
-
-int
-ahc_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(FLAGS_parse_table, 2, "FLAGS",
- 0x6b, regvalue, cur_col, wrap));
-}
-
-int
-ahc_sindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SINDIR",
- 0x6c, regvalue, cur_col, wrap));
-}
-
-int
-ahc_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "DINDIR",
- 0x6d, regvalue, cur_col, wrap));
-}
-
-int
-ahc_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "STACK",
- 0x6f, regvalue, cur_col, wrap));
-}
-
-int
-ahc_targ_offset_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "TARG_OFFSET",
- 0x70, regvalue, cur_col, wrap));
-}
-
-int
ahc_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "SRAM_BASE",
0x70, regvalue, cur_col, wrap));
}
-static const ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
- { "CIOPARCKEN", 0x01, 0x01 },
- { "USCBSIZE32", 0x02, 0x02 },
- { "RAMPS", 0x04, 0x04 },
- { "INTSCBRAMSEL", 0x08, 0x08 },
- { "EXTREQLCK", 0x10, 0x10 },
- { "MPARCKEN", 0x20, 0x20 },
- { "DPARCKEN", 0x40, 0x40 },
- { "CACHETHEN", 0x80, 0x80 }
-};
-
-int
-ahc_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(DSCOMMAND0_parse_table, 8, "DSCOMMAND0",
- 0x84, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
- { "BON", 0x0f, 0x0f },
- { "BOFF", 0xf0, 0xf0 }
-};
-
-int
-ahc_bustime_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(BUSTIME_parse_table, 2, "BUSTIME",
- 0x85, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
- { "HADDLDSEL0", 0x01, 0x01 },
- { "HADDLDSEL1", 0x02, 0x02 },
- { "DSLATT", 0xfc, 0xfc }
-};
-
-int
-ahc_dscommand1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(DSCOMMAND1_parse_table, 3, "DSCOMMAND1",
- 0x85, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
- { "STBON", 0x07, 0x07 },
- { "STBOFF", 0x38, 0x38 },
- { "DFTHRSH_75", 0x80, 0x80 },
- { "DFTHRSH", 0xc0, 0xc0 },
- { "DFTHRSH_100", 0xc0, 0xc0 }
-};
-
-int
-ahc_busspd_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(BUSSPD_parse_table, 5, "BUSSPD",
- 0x86, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
- { "SEQ_MAILBOX", 0x0f, 0x0f },
- { "HOST_TQINPOS", 0x80, 0x80 },
- { "HOST_MAILBOX", 0xf0, 0xf0 }
-};
-
-int
-ahc_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(HS_MAILBOX_parse_table, 3, "HS_MAILBOX",
- 0x86, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
- { "DFTHRSH_100", 0xc0, 0xc0 }
-};
-
-int
-ahc_dspcistatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(DSPCISTATUS_parse_table, 1, "DSPCISTATUS",
- 0x86, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
- { "CHIPRST", 0x01, 0x01 },
- { "CHIPRSTACK", 0x01, 0x01 },
- { "INTEN", 0x02, 0x02 },
- { "PAUSE", 0x04, 0x04 },
- { "IRQMS", 0x08, 0x08 },
- { "SWINT", 0x10, 0x10 },
- { "POWRDN", 0x40, 0x40 }
-};
-
-int
-ahc_hcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(HCNTRL_parse_table, 7, "HCNTRL",
- 0x87, regvalue, cur_col, wrap));
-}
-
-int
-ahc_haddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "HADDR",
- 0x88, regvalue, cur_col, wrap));
-}
-
-int
-ahc_hcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "HCNT",
- 0x8c, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCBPTR",
- 0x90, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
- { "SEQINT", 0x01, 0x01 },
- { "CMDCMPLT", 0x02, 0x02 },
- { "SCSIINT", 0x04, 0x04 },
- { "BRKADRINT", 0x08, 0x08 },
- { "BAD_PHASE", 0x01, 0x01 },
- { "INT_PEND", 0x0f, 0x0f },
- { "SEND_REJECT", 0x11, 0x11 },
- { "PROTO_VIOLATION", 0x21, 0x21 },
- { "NO_MATCH", 0x31, 0x31 },
- { "IGN_WIDE_RES", 0x41, 0x41 },
- { "PDATA_REINIT", 0x51, 0x51 },
- { "HOST_MSG_LOOP", 0x61, 0x61 },
- { "BAD_STATUS", 0x71, 0x71 },
- { "PERR_DETECTED", 0x81, 0x81 },
- { "DATA_OVERRUN", 0x91, 0x91 },
- { "MKMSG_FAILED", 0xa1, 0xa1 },
- { "MISSED_BUSFREE", 0xb1, 0xb1 },
- { "SCB_MISMATCH", 0xc1, 0xc1 },
- { "NO_FREE_SCB", 0xd1, 0xd1 },
- { "OUT_OF_RANGE", 0xe1, 0xe1 },
- { "SEQINT_MASK", 0xf1, 0xf1 }
-};
-
-int
-ahc_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(INTSTAT_parse_table, 21, "INTSTAT",
- 0x91, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t CLRINT_parse_table[] = {
- { "CLRSEQINT", 0x01, 0x01 },
- { "CLRCMDINT", 0x02, 0x02 },
- { "CLRSCSIINT", 0x04, 0x04 },
- { "CLRBRKADRINT", 0x08, 0x08 },
- { "CLRPARERR", 0x10, 0x10 }
-};
-
-int
-ahc_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(CLRINT_parse_table, 5, "CLRINT",
- 0x92, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t ERROR_parse_table[] = {
{ "ILLHADDR", 0x01, 0x01 },
{ "ILLSADDR", 0x02, 0x02 },
@@ -1115,62 +336,6 @@ ahc_dfstatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x94, regvalue, cur_col, wrap));
}
-int
-ahc_dfwaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "DFWADDR",
- 0x95, regvalue, cur_col, wrap));
-}
-
-int
-ahc_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "DFDAT",
- 0x99, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
- { "SCBAUTO", 0x80, 0x80 },
- { "SCBCNT_MASK", 0x1f, 0x1f }
-};
-
-int
-ahc_scbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCBCNT_parse_table, 2, "SCBCNT",
- 0x9a, regvalue, cur_col, wrap));
-}
-
-int
-ahc_qinfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "QINFIFO",
- 0x9b, regvalue, cur_col, wrap));
-}
-
-int
-ahc_qoutfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "QOUTFIFO",
- 0x9d, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
- { "TARGCRCCNTEN", 0x04, 0x04 },
- { "TARGCRCENDEN", 0x08, 0x08 },
- { "CRCREQCHKEN", 0x10, 0x10 },
- { "CRCENDCHKEN", 0x20, 0x20 },
- { "CRCVALCHKEN", 0x40, 0x40 },
- { "CRCONSEEN", 0x80, 0x80 }
-};
-
-int
-ahc_crccontrol1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(CRCCONTROL1_parse_table, 6, "CRCCONTROL1",
- 0x9d, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
{ "DATA_OUT_PHASE", 0x01, 0x01 },
{ "DATA_IN_PHASE", 0x02, 0x02 },
@@ -1188,17 +353,6 @@ ahc_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9e, regvalue, cur_col, wrap));
}
-static const ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
- { "ALT_MODE", 0x80, 0x80 }
-};
-
-int
-ahc_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SFUNCT_parse_table, 1, "SFUNCT",
- 0x9f, regvalue, cur_col, wrap));
-}
-
int
ahc_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -1206,80 +360,6 @@ ahc_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xa0, regvalue, cur_col, wrap));
}
-int
-ahc_scb_cdb_ptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_CDB_PTR",
- 0xa0, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_residual_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_RESIDUAL_SGPTR",
- 0xa4, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_scsi_status_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_SCSI_STATUS",
- 0xa8, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_target_phases_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_TARGET_PHASES",
- 0xa9, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_target_data_dir_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_TARGET_DATA_DIR",
- 0xaa, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_target_itag_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_TARGET_ITAG",
- 0xab, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_DATAPTR",
- 0xac, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
- { "SG_LAST_SEG", 0x80, 0x80 },
- { "SG_HIGH_ADDR_BITS", 0x7f, 0x7f }
-};
-
-int
-ahc_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT",
- 0xb0, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
- { "SG_LIST_NULL", 0x01, 0x01 },
- { "SG_FULL_RESID", 0x02, 0x02 },
- { "SG_RESID_VALID", 0x04, 0x04 }
-};
-
-int
-ahc_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR",
- 0xb4, regvalue, cur_col, wrap));
-}
-
static const ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
{ "DISCONNECTED", 0x04, 0x04 },
{ "ULTRAENB", 0x08, 0x08 },
@@ -1331,248 +411,3 @@ ahc_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xbb, regvalue, cur_col, wrap));
}
-int
-ahc_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_CDB_LEN",
- 0xbc, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_scsirate_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_SCSIRATE",
- 0xbd, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_scsioffset_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_SCSIOFFSET",
- 0xbe, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_NEXT",
- 0xbf, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
- { "DO_2840", 0x01, 0x01 },
- { "CK_2840", 0x02, 0x02 },
- { "CS_2840", 0x04, 0x04 }
-};
-
-int
-ahc_seectl_2840_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SEECTL_2840_parse_table, 3, "SEECTL_2840",
- 0xc0, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
- { "DI_2840", 0x01, 0x01 },
- { "EEPROM_TF", 0x80, 0x80 },
- { "ADSEL", 0x1e, 0x1e },
- { "BIOS_SEL", 0x60, 0x60 }
-};
-
-int
-ahc_status_2840_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(STATUS_2840_parse_table, 4, "STATUS_2840",
- 0xc1, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scb_64_btt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCB_64_BTT",
- 0xd0, regvalue, cur_col, wrap));
-}
-
-int
-ahc_cchaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCHADDR",
- 0xe0, regvalue, cur_col, wrap));
-}
-
-int
-ahc_cchcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCHCNT",
- 0xe8, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCSGRAM",
- 0xe9, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCSGADDR",
- 0xea, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
- { "CCSGRESET", 0x01, 0x01 },
- { "SG_FETCH_NEEDED", 0x02, 0x02 },
- { "CCSGEN", 0x08, 0x08 },
- { "CCSGDONE", 0x80, 0x80 }
-};
-
-int
-ahc_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(CCSGCTL_parse_table, 4, "CCSGCTL",
- 0xeb, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ccscbram_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCSCBRAM",
- 0xec, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCSCBADDR",
- 0xed, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
- { "CCSCBRESET", 0x01, 0x01 },
- { "CCSCBDIR", 0x04, 0x04 },
- { "CCSCBEN", 0x08, 0x08 },
- { "CCARREN", 0x10, 0x10 },
- { "ARRDONE", 0x40, 0x40 },
- { "CCSCBDONE", 0x80, 0x80 }
-};
-
-int
-ahc_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(CCSCBCTL_parse_table, 6, "CCSCBCTL",
- 0xee, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ccscbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCSCBCNT",
- 0xef, regvalue, cur_col, wrap));
-}
-
-int
-ahc_scbbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SCBBADDR",
- 0xf0, regvalue, cur_col, wrap));
-}
-
-int
-ahc_ccscbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "CCSCBPTR",
- 0xf1, regvalue, cur_col, wrap));
-}
-
-int
-ahc_hnscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "HNSCB_QOFF",
- 0xf4, regvalue, cur_col, wrap));
-}
-
-int
-ahc_snscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SNSCB_QOFF",
- 0xf6, regvalue, cur_col, wrap));
-}
-
-int
-ahc_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(NULL, 0, "SDSCB_QOFF",
- 0xf8, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
- { "SDSCB_ROLLOVER", 0x10, 0x10 },
- { "SNSCB_ROLLOVER", 0x20, 0x20 },
- { "SCB_AVAIL", 0x40, 0x40 },
- { "SCB_QSIZE_256", 0x06, 0x06 },
- { "SCB_QSIZE", 0x07, 0x07 }
-};
-
-int
-ahc_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(QOFF_CTLSTA_parse_table, 5, "QOFF_CTLSTA",
- 0xfa, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
- { "RD_DFTHRSH_MIN", 0x00, 0x00 },
- { "WR_DFTHRSH_MIN", 0x00, 0x00 },
- { "RD_DFTHRSH_25", 0x01, 0x01 },
- { "RD_DFTHRSH_50", 0x02, 0x02 },
- { "RD_DFTHRSH_63", 0x03, 0x03 },
- { "RD_DFTHRSH_75", 0x04, 0x04 },
- { "RD_DFTHRSH_85", 0x05, 0x05 },
- { "RD_DFTHRSH_90", 0x06, 0x06 },
- { "RD_DFTHRSH", 0x07, 0x07 },
- { "RD_DFTHRSH_MAX", 0x07, 0x07 },
- { "WR_DFTHRSH_25", 0x10, 0x10 },
- { "WR_DFTHRSH_50", 0x20, 0x20 },
- { "WR_DFTHRSH_63", 0x30, 0x30 },
- { "WR_DFTHRSH_75", 0x40, 0x40 },
- { "WR_DFTHRSH_85", 0x50, 0x50 },
- { "WR_DFTHRSH_90", 0x60, 0x60 },
- { "WR_DFTHRSH", 0x70, 0x70 },
- { "WR_DFTHRSH_MAX", 0x70, 0x70 }
-};
-
-int
-ahc_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(DFF_THRSH_parse_table, 18, "DFF_THRSH",
- 0xfb, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
- { "LAST_SEG_DONE", 0x01, 0x01 },
- { "LAST_SEG", 0x02, 0x02 },
- { "SG_ADDR_MASK", 0xf8, 0xf8 }
-};
-
-int
-ahc_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SG_CACHE_SHADOW_parse_table, 3, "SG_CACHE_SHADOW",
- 0xfc, regvalue, cur_col, wrap));
-}
-
-static const ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
- { "LAST_SEG_DONE", 0x01, 0x01 },
- { "LAST_SEG", 0x02, 0x02 },
- { "SG_ADDR_MASK", 0xf8, 0xf8 }
-};
-
-int
-ahc_sg_cache_pre_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahc_print_register(SG_CACHE_PRE_parse_table, 3, "SG_CACHE_PRE",
- 0xfc, regvalue, cur_col, wrap));
-}
-
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
index 81be6a261cc..e4064433842 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -147,6 +147,8 @@ void yyerror(const char *string);
%token T_ACCESS_MODE
+%token T_DONT_GENERATE_DEBUG_CODE
+
%token T_MODES
%token T_DEFINE
@@ -357,6 +359,7 @@ reg_attribute:
| size
| count
| access_mode
+| dont_generate_debug_code
| modes
| field_defn
| enum_defn
@@ -410,6 +413,13 @@ access_mode:
}
;
+dont_generate_debug_code:
+ T_DONT_GENERATE_DEBUG_CODE
+ {
+ cur_symbol->dont_generate_debug_code = 1;
+ }
+;
+
modes:
T_MODES mode_list
{
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
index 2c7f02daf88..93c8667cd70 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
@@ -164,6 +164,7 @@ download { return T_DOWNLOAD; }
address { return T_ADDRESS; }
count { return T_COUNT; }
access_mode { return T_ACCESS_MODE; }
+dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
modes { return T_MODES; }
RW|RO|WO {
if (strcmp(yytext, "RW") == 0)
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
index fcd357872b4..078ed600f47 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
@@ -539,6 +539,9 @@ symtable_dump(FILE *ofile, FILE *dfile)
aic_print_include(dfile, stock_include_file);
SLIST_FOREACH(curnode, &registers, links) {
+ if (curnode->symbol->dont_generate_debug_code)
+ continue;
+
switch(curnode->symbol->type) {
case REGISTER:
case SCBLOC:
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
index 05190c1a2fb..2ba73ae7c77 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
@@ -137,7 +137,8 @@ typedef struct symbol {
struct label_info *linfo;
struct cond_info *condinfo;
struct macro_info *macroinfo;
- }info;
+ } info;
+ int dont_generate_debug_code;
} symbol_t;
typedef struct symbol_ref {
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index 69f8346aa28..5877f29a600 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -189,7 +189,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
.attr = {
.name = "mu_read",
.mode = S_IRUSR ,
- .owner = THIS_MODULE,
},
.size = 1032,
.read = arcmsr_sysfs_iop_message_read,
@@ -199,7 +198,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
.attr = {
.name = "mu_write",
.mode = S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 1032,
.write = arcmsr_sysfs_iop_message_write,
@@ -209,7 +207,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
.attr = {
.name = "mu_clear",
.mode = S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 1,
.write = arcmsr_sysfs_iop_message_clear,
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index a43c3ed4df2..3d50cabca7e 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -401,6 +401,9 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
}
}
+ if (h->lun_state == RDAC_LUN_UNOWNED)
+ h->state = RDAC_STATE_PASSIVE;
+
return err;
}
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 740bad43599..2370fd82ebf 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -343,6 +343,11 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
}
#ifdef CONFIG_IDE_PROC_FS
+static ide_proc_entry_t idescsi_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
+ { NULL, 0, NULL, NULL }
+};
+
#define ide_scsi_devset_get(name, field) \
static int get_##name(ide_drive_t *drive) \
{ \
@@ -378,6 +383,16 @@ static const struct ide_proc_devset idescsi_settings[] = {
IDE_PROC_DEVSET(transform, 0, 3),
{ 0 },
};
+
+static ide_proc_entry_t *ide_scsi_proc_entries(ide_drive_t *drive)
+{
+ return idescsi_proc;
+}
+
+static const struct ide_proc_devset *ide_scsi_proc_devsets(ide_drive_t *drive)
+{
+ return idescsi_settings;
+}
#endif
/*
@@ -419,13 +434,6 @@ static void ide_scsi_remove(ide_drive_t *drive)
static int ide_scsi_probe(ide_drive_t *);
-#ifdef CONFIG_IDE_PROC_FS
-static ide_proc_entry_t idescsi_proc[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
- { NULL, 0, NULL, NULL }
-};
-#endif
-
static ide_driver_t idescsi_driver = {
.gen_driver = {
.owner = THIS_MODULE,
@@ -439,45 +447,39 @@ static ide_driver_t idescsi_driver = {
.end_request = idescsi_end_request,
.error = idescsi_atapi_error,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idescsi_proc,
- .settings = idescsi_settings,
+ .proc_entries = ide_scsi_proc_entries,
+ .proc_devsets = ide_scsi_proc_devsets,
#endif
};
-static int idescsi_ide_open(struct inode *inode, struct file *filp)
+static int idescsi_ide_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_scsi_obj *scsi;
+ struct ide_scsi_obj *scsi = ide_scsi_get(bdev->bd_disk);
- if (!(scsi = ide_scsi_get(disk)))
+ if (!scsi)
return -ENXIO;
return 0;
}
-static int idescsi_ide_release(struct inode *inode, struct file *filp)
+static int idescsi_ide_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_scsi_obj *scsi = ide_scsi_g(disk);
-
- ide_scsi_put(scsi);
-
+ ide_scsi_put(ide_scsi_g(disk));
return 0;
}
-static int idescsi_ide_ioctl(struct inode *inode, struct file *file,
+static int idescsi_ide_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk);
- return generic_ide_ioctl(scsi->drive, file, bdev, cmd, arg);
+ return generic_ide_ioctl(scsi->drive, bdev, cmd, arg);
}
static struct block_device_operations idescsi_ops = {
.owner = THIS_MODULE,
.open = idescsi_ide_open,
.release = idescsi_ide_release,
- .ioctl = idescsi_ide_ioctl,
+ .locked_ioctl = idescsi_ide_ioctl,
};
static int idescsi_slave_configure(struct scsi_device * sdp)
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index d30eb7ba018..ded854a6dd3 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2456,20 +2456,14 @@ static ssize_t ipr_read_trace(struct kobject *kobj,
struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
- int size = IPR_TRACE_SIZE;
- char *src = (char *)ioa_cfg->trace;
-
- if (off > size)
- return 0;
- if (off + count > size) {
- size -= off;
- count = size;
- }
+ ssize_t ret;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- memcpy(buf, &src[off], count);
+ ret = memory_read_from_buffer(buf, count, &off, ioa_cfg->trace,
+ IPR_TRACE_SIZE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- return count;
+
+ return ret;
}
static struct bin_attribute ipr_trace_attr = {
@@ -7859,7 +7853,6 @@ static struct pci_driver ipr_driver = {
.remove = ipr_remove,
.shutdown = ipr_shutdown,
.err_handler = &ipr_err_handler,
- .dynids.use_driver_data = 1
};
/**
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 83c81921677..f25f41a499e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2108,7 +2108,7 @@ struct scsi_qla_host;
struct qla_msix_entry {
int have_irq;
- uint16_t msix_vector;
+ uint32_t msix_vector;
uint16_t msix_entry;
};
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2aed4721c0d..21dd182ad51 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1566,9 +1566,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_out;
}
- if (pci_find_aer_capability(pdev))
- if (pci_enable_pcie_error_reporting(pdev))
- goto probe_out;
+ /* This may fail but that's ok */
+ pci_enable_pcie_error_reporting(pdev);
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) {
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 28b19ef2630..dc1cfb2fd76 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -237,7 +237,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
case SCSI_IOCTL_SEND_COMMAND:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg);
+ return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg);
case SCSI_IOCTL_DOORLOCK:
return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
case SCSI_IOCTL_DOORUNLOCK:
@@ -277,14 +277,14 @@ EXPORT_SYMBOL(scsi_ioctl);
* @filp: either NULL or a &struct file which must have the O_NONBLOCK flag.
*/
int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
- void __user *arg, struct file *filp)
+ void __user *arg, int ndelay)
{
int val, result;
/* The first set of iocts may be executed even if we're doing
* error processing, as long as the device was opened
* non-blocking */
- if (filp && (filp->f_flags & O_NONBLOCK)) {
+ if (ndelay) {
if (scsi_host_in_recovery(sdev->host))
return -ENODEV;
} else if (!scsi_block_when_processing_errors(sdev))
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e5a9526d203..f5d3b96890d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -529,6 +529,14 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
spin_unlock_irqrestore(shost->host_lock, flags);
}
+static inline int scsi_device_is_busy(struct scsi_device *sdev)
+{
+ if (sdev->device_busy >= sdev->queue_depth || sdev->device_blocked)
+ return 1;
+
+ return 0;
+}
+
static inline int scsi_target_is_busy(struct scsi_target *starget)
{
return ((starget->can_queue > 0 &&
@@ -536,6 +544,15 @@ static inline int scsi_target_is_busy(struct scsi_target *starget)
starget->target_blocked);
}
+static inline int scsi_host_is_busy(struct Scsi_Host *shost)
+{
+ if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) ||
+ shost->host_blocked || shost->host_self_blocked)
+ return 1;
+
+ return 0;
+}
+
/*
* Function: scsi_run_queue()
*
@@ -558,11 +575,7 @@ static void scsi_run_queue(struct request_queue *q)
scsi_single_lun_run(sdev);
spin_lock_irqsave(shost->host_lock, flags);
- while (!list_empty(&shost->starved_list) &&
- !shost->host_blocked && !shost->host_self_blocked &&
- !((shost->can_queue > 0) &&
- (shost->host_busy >= shost->can_queue))) {
-
+ while (!list_empty(&shost->starved_list) && !scsi_host_is_busy(shost)) {
int flagset;
/*
@@ -1348,8 +1361,6 @@ int scsi_prep_fn(struct request_queue *q, struct request *req)
static inline int scsi_dev_queue_ready(struct request_queue *q,
struct scsi_device *sdev)
{
- if (sdev->device_busy >= sdev->queue_depth)
- return 0;
if (sdev->device_busy == 0 && sdev->device_blocked) {
/*
* unblock after device_blocked iterates to zero
@@ -1363,7 +1374,7 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
return 0;
}
}
- if (sdev->device_blocked)
+ if (scsi_device_is_busy(sdev))
return 0;
return 1;
@@ -1440,8 +1451,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
return 0;
}
}
- if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) ||
- shost->host_blocked || shost->host_self_blocked) {
+ if (scsi_host_is_busy(shost)) {
if (list_empty(&sdev->starved_entry))
list_add_tail(&sdev->starved_entry, &shost->starved_list);
return 0;
@@ -1455,6 +1465,37 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
}
/*
+ * Busy state exporting function for request stacking drivers.
+ *
+ * For efficiency, no lock is taken to check the busy state of
+ * shost/starget/sdev, since the returned value is not guaranteed and
+ * may be changed after request stacking drivers call the function,
+ * regardless of taking lock or not.
+ *
+ * When scsi can't dispatch I/Os anymore and needs to kill I/Os
+ * (e.g. !sdev), scsi needs to return 'not busy'.
+ * Otherwise, request stacking drivers may hold requests forever.
+ */
+static int scsi_lld_busy(struct request_queue *q)
+{
+ struct scsi_device *sdev = q->queuedata;
+ struct Scsi_Host *shost;
+ struct scsi_target *starget;
+
+ if (!sdev)
+ return 0;
+
+ shost = sdev->host;
+ starget = scsi_target(sdev);
+
+ if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) ||
+ scsi_target_is_busy(starget) || scsi_device_is_busy(sdev))
+ return 1;
+
+ return 0;
+}
+
+/*
* Kill a request for a dead device
*/
static void scsi_kill_request(struct request *req, struct request_queue *q)
@@ -1757,6 +1798,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
blk_queue_prep_rq(q, scsi_prep_fn);
blk_queue_softirq_done(q, scsi_softirq_done);
blk_queue_rq_timed_out(q, scsi_times_out);
+ blk_queue_lld_busy(q, scsi_lld_busy);
return q;
}
@@ -2105,22 +2147,21 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries,
do {
result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sshdr,
timeout, retries);
- } while ((driver_byte(result) & DRIVER_SENSE) &&
- sshdr && sshdr->sense_key == UNIT_ATTENTION &&
- --retries);
+ if (sdev->removable && scsi_sense_valid(sshdr) &&
+ sshdr->sense_key == UNIT_ATTENTION)
+ sdev->changed = 1;
+ } while (scsi_sense_valid(sshdr) &&
+ sshdr->sense_key == UNIT_ATTENTION && --retries);
if (!sshdr)
/* could not allocate sense buffer, so can't process it */
return result;
- if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) {
-
- if ((scsi_sense_valid(sshdr)) &&
- ((sshdr->sense_key == UNIT_ATTENTION) ||
- (sshdr->sense_key == NOT_READY))) {
- sdev->changed = 1;
- result = 0;
- }
+ if (sdev->removable && scsi_sense_valid(sshdr) &&
+ (sshdr->sense_key == UNIT_ATTENTION ||
+ sshdr->sense_key == NOT_READY)) {
+ sdev->changed = 1;
+ result = 0;
}
if (!sshdr_external)
kfree(sshdr);
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index b37e133de80..723fdecd91b 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -205,16 +205,13 @@ static struct notifier_block scsi_netlink_notifier = {
};
-/**
+/*
* GENERIC SCSI transport receive and event handlers
- **/
+ */
/**
- * scsi_generic_msg_handler - receive message handler for GENERIC transport
- * messages
- *
+ * scsi_generic_msg_handler - receive message handler for GENERIC transport messages
* @skb: socket receive buffer
- *
**/
static int
scsi_generic_msg_handler(struct sk_buff *skb)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 7c4d2e68df1..c9e1242eaf2 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -609,17 +609,15 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
* In the latter case @inode and @filp carry an abridged amount
* of information as noted above.
**/
-static int sd_open(struct inode *inode, struct file *filp)
+static int sd_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct scsi_disk *sdkp;
+ struct scsi_disk *sdkp = scsi_disk_get(bdev->bd_disk);
struct scsi_device *sdev;
int retval;
- if (!(sdkp = scsi_disk_get(disk)))
+ if (!sdkp)
return -ENXIO;
-
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n"));
sdev = sdkp->device;
@@ -633,14 +631,13 @@ static int sd_open(struct inode *inode, struct file *filp)
goto error_out;
if (sdev->removable || sdkp->write_prot)
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
/*
* If the drive is empty, just let the open fail.
*/
retval = -ENOMEDIUM;
- if (sdev->removable && !sdkp->media_present &&
- !(filp->f_flags & O_NDELAY))
+ if (sdev->removable && !sdkp->media_present && !(mode & FMODE_NDELAY))
goto error_out;
/*
@@ -648,7 +645,7 @@ static int sd_open(struct inode *inode, struct file *filp)
* if the user expects to be able to write to the thing.
*/
retval = -EROFS;
- if (sdkp->write_prot && (filp->f_mode & FMODE_WRITE))
+ if (sdkp->write_prot && (mode & FMODE_WRITE))
goto error_out;
/*
@@ -684,9 +681,8 @@ error_out:
* Note: may block (uninterruptible) if error recovery is underway
* on this disk.
**/
-static int sd_release(struct inode *inode, struct file *filp)
+static int sd_release(struct gendisk *disk, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdev = sdkp->device;
@@ -743,10 +739,9 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* Note: most ioctls are forward onto the block subsystem or further
* down in the scsi subsystem.
**/
-static int sd_ioctl(struct inode * inode, struct file * filp,
+static int sd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
struct scsi_device *sdp = scsi_disk(disk)->device;
void __user *p = (void __user *)arg;
@@ -761,7 +756,8 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
* may try and take the device offline, in which case all further
* access to the device is prohibited.
*/
- error = scsi_nonblockable_ioctl(sdp, cmd, p, filp);
+ error = scsi_nonblockable_ioctl(sdp, cmd, p,
+ (mode & FMODE_NDELAY_NOW) != 0);
if (!scsi_block_when_processing_errors(sdp) || !error)
return error;
@@ -775,7 +771,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
case SCSI_IOCTL_GET_BUS_NUMBER:
return scsi_ioctl(sdp, cmd, p);
default:
- error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
+ error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
if (error != -ENOTTY)
return error;
}
@@ -928,11 +924,10 @@ static void sd_rescan(struct device *dev)
* This gets directly called from VFS. When the ioctl
* is not recognized we go back to the other translation paths.
*/
-static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
- struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
- struct gendisk *disk = bdev->bd_disk;
- struct scsi_device *sdev = scsi_disk(disk)->device;
+ struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
/*
* If we are in the middle of error recovery, don't let anyone
@@ -962,7 +957,7 @@ static struct block_device_operations sd_fops = {
.owner = THIS_MODULE,
.open = sd_open,
.release = sd_release,
- .ioctl = sd_ioctl,
+ .locked_ioctl = sd_ioctl,
.getgeo = sd_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = sd_compat_ioctl,
@@ -1054,7 +1049,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
good_bytes = sd_completed_bytes(SCpnt);
break;
case RECOVERED_ERROR:
- case NO_SENSE:
/* Inform the user, but make sure that it's not treated
* as a hard error.
*/
@@ -1063,6 +1057,15 @@ static int sd_done(struct scsi_cmnd *SCpnt)
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
good_bytes = scsi_bufflen(SCpnt);
break;
+ case NO_SENSE:
+ /* This indicates a false check condition, so ignore it. An
+ * unknown amount of data was transferred so treat it as an
+ * error.
+ */
+ scsi_print_sense("sd", SCpnt);
+ SCpnt->result = 0;
+ memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ break;
case ABORTED_COMMAND:
if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */
scsi_print_result(SCpnt);
@@ -1076,15 +1079,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
scsi_print_sense("sd", SCpnt);
good_bytes = sd_completed_bytes(SCpnt);
}
- if (!scsi_device_protection(SCpnt->device) &&
- SCpnt->device->use_10_for_rw &&
- (SCpnt->cmnd[0] == READ_10 ||
- SCpnt->cmnd[0] == WRITE_10))
- SCpnt->device->use_10_for_rw = 0;
- if (SCpnt->device->use_10_for_ms &&
- (SCpnt->cmnd[0] == MODE_SENSE_10 ||
- SCpnt->cmnd[0] == MODE_SELECT_10))
- SCpnt->device->use_10_for_ms = 0;
break;
default:
break;
@@ -1437,7 +1431,7 @@ got_data:
{
char cap_str_2[10], cap_str_10[10];
- u64 sz = sdkp->capacity << ffz(~sector_size);
+ u64 sz = (u64)sdkp->capacity << ilog2(sector_size);
string_get_size(sz, STRING_UNITS_2, cap_str_2,
sizeof(cap_str_2));
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 93bd59a1ed7..9adf35bd8b5 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1059,7 +1059,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (sg_allow_access(filp, &opcode))
return -EPERM;
}
- return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
+ return sg_scsi_ioctl(sdp->device->request_queue, NULL, filp->f_mode, p);
case SG_SET_DEBUG:
result = get_user(val, ip);
if (result)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 0f17009c99d..62b6633e3a9 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -471,38 +471,31 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
return scsi_prep_return(q, rq, ret);
}
-static int sr_block_open(struct inode *inode, struct file *file)
+static int sr_block_open(struct block_device *bdev, fmode_t mode)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct scsi_cd *cd;
- int ret = 0;
-
- if(!(cd = scsi_cd_get(disk)))
- return -ENXIO;
-
- if((ret = cdrom_open(&cd->cdi, inode, file)) != 0)
- scsi_cd_put(cd);
+ struct scsi_cd *cd = scsi_cd_get(bdev->bd_disk);
+ int ret = -ENXIO;
+ if (cd) {
+ ret = cdrom_open(&cd->cdi, bdev, mode);
+ if (ret)
+ scsi_cd_put(cd);
+ }
return ret;
}
-static int sr_block_release(struct inode *inode, struct file *file)
+static int sr_block_release(struct gendisk *disk, fmode_t mode)
{
- int ret;
- struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
- ret = cdrom_release(&cd->cdi, file);
- if(ret)
- return ret;
-
+ struct scsi_cd *cd = scsi_cd(disk);
+ cdrom_release(&cd->cdi, mode);
scsi_cd_put(cd);
-
return 0;
}
-static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
unsigned long arg)
{
- struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
+ struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
struct scsi_device *sdev = cd->device;
void __user *argp = (void __user *)arg;
int ret;
@@ -517,7 +510,7 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
return scsi_ioctl(sdev, cmd, argp);
}
- ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg);
+ ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
if (ret != -ENOSYS)
return ret;
@@ -527,7 +520,8 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
* case fall through to scsi_ioctl, which will return ENDOEV again
* if it doesn't recognise the ioctl
*/
- ret = scsi_nonblockable_ioctl(sdev, cmd, argp, NULL);
+ ret = scsi_nonblockable_ioctl(sdev, cmd, argp,
+ (mode & FMODE_NDELAY_NOW) != 0);
if (ret != -ENODEV)
return ret;
return scsi_ioctl(sdev, cmd, argp);
@@ -544,7 +538,7 @@ static struct block_device_operations sr_bdops =
.owner = THIS_MODULE,
.open = sr_block_open,
.release = sr_block_release,
- .ioctl = sr_block_ioctl,
+ .locked_ioctl = sr_block_ioctl,
.media_changed = sr_block_media_changed,
/*
* No compat_ioctl for now because sr_block_ioctl never
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 4eb3da996b3..4ad3e017213 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -223,9 +223,9 @@ int sr_cd_check(struct cdrom_device_info *cdi)
no_multi = 1;
break;
}
- min = BCD2BIN(buffer[15]);
- sec = BCD2BIN(buffer[16]);
- frame = BCD2BIN(buffer[17]);
+ min = bcd2bin(buffer[15]);
+ sec = bcd2bin(buffer[16]);
+ frame = bcd2bin(buffer[17]);
sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
break;
}
@@ -252,9 +252,9 @@ int sr_cd_check(struct cdrom_device_info *cdi)
}
if (rc != 0)
break;
- min = BCD2BIN(buffer[1]);
- sec = BCD2BIN(buffer[2]);
- frame = BCD2BIN(buffer[3]);
+ min = bcd2bin(buffer[1]);
+ sec = bcd2bin(buffer[2]);
+ frame = bcd2bin(buffer[3]);
sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
if (sector)
sector -= CD_MSF_OFFSET;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 5c28d08f18f..c959bdc55f4 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3263,7 +3263,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
* may try and take the device offline, in which case all further
* access to the device is prohibited.
*/
- retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, file);
+ retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p,
+ file->f_flags & O_NDELAY);
if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV)
goto out;
retval = 0;
@@ -3567,8 +3568,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
!capable(CAP_SYS_RAWIO))
i = -EPERM;
else
- i = scsi_cmd_ioctl(file, STp->disk->queue,
- STp->disk, cmd_in, p);
+ i = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
+ file->f_mode, cmd_in, p);
if (i != -ENOTTY)
return i;
break;
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 7514b3a0390..34a99620e5b 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -213,7 +213,7 @@ static int __devinit esp_sun3x_probe(struct platform_device *dev)
esp->ops = &sun3x_esp_ops;
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!res && !res->start)
+ if (!res || !res->start)
goto fail_unlink;
esp->regs = ioremap_nocache(res->start, 0x20);
@@ -221,7 +221,7 @@ static int __devinit esp_sun3x_probe(struct platform_device *dev)
goto fail_unmap_regs;
res = platform_get_resource(dev, IORESOURCE_MEM, 1);
- if (!res && !res->start)
+ if (!res || !res->start)
goto fail_unmap_regs;
esp->dma_regs = ioremap_nocache(res->start, 0x10);
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 381b12ac20e..d935b2d04f9 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -66,7 +66,6 @@
#endif
static struct m68k_serial m68k_soft[NR_PORTS];
-struct m68k_serial *IRQ_ports[NR_IRQS];
static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;
@@ -375,15 +374,11 @@ clear_and_return:
*/
irqreturn_t rs_interrupt(int irq, void *dev_id)
{
- struct m68k_serial * info;
+ struct m68k_serial *info = dev_id;
m68328_uart *uart;
unsigned short rx;
unsigned short tx;
- info = IRQ_ports[irq];
- if(!info)
- return IRQ_NONE;
-
uart = &uart_addr[info->line];
rx = uart->urx.w;
@@ -1383,8 +1378,6 @@ rs68328_init(void)
info->port, info->irq);
printk(" is a builtin MC68328 UART\n");
- IRQ_ports[info->irq] = info; /* waste of space */
-
#ifdef CONFIG_M68VZ328
if (i > 0 )
PJSEL &= 0xCF; /* PSW enable second port output */
@@ -1393,7 +1386,7 @@ rs68328_init(void)
if (request_irq(uart_irqs[i],
rs_interrupt,
IRQF_DISABLED,
- "M68328_UART", NULL))
+ "M68328_UART", info))
panic("Unable to attach 68328 serial interrupt\n");
}
local_irq_restore(flags);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 1528de23a65..303272af386 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -156,11 +156,15 @@ struct uart_8250_port {
};
struct irq_info {
- spinlock_t lock;
+ struct hlist_node node;
+ int irq;
+ spinlock_t lock; /* Protects list not the hash */
struct list_head *head;
};
-static struct irq_info irq_lists[NR_IRQS];
+#define NR_IRQ_HASH 32 /* Can be adjusted later */
+static struct hlist_head irq_lists[NR_IRQ_HASH];
+static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
/*
* Here we define the default xmit fifo size used for each type of UART.
@@ -1545,15 +1549,43 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
BUG_ON(i->head != &up->list);
i->head = NULL;
}
-
spin_unlock_irq(&i->lock);
+ /* List empty so throw away the hash node */
+ if (i->head == NULL) {
+ hlist_del(&i->node);
+ kfree(i);
+ }
}
static int serial_link_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct hlist_head *h;
+ struct hlist_node *n;
+ struct irq_info *i;
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+ mutex_lock(&hash_mutex);
+
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ if (n == NULL) {
+ i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+ if (i == NULL) {
+ mutex_unlock(&hash_mutex);
+ return -ENOMEM;
+ }
+ spin_lock_init(&i->lock);
+ i->irq = up->port.irq;
+ hlist_add_head(&i->node, h);
+ }
+ mutex_unlock(&hash_mutex);
+
spin_lock_irq(&i->lock);
if (i->head) {
@@ -1577,14 +1609,28 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
static void serial_unlink_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct irq_info *i;
+ struct hlist_node *n;
+ struct hlist_head *h;
+ mutex_lock(&hash_mutex);
+
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ BUG_ON(n == NULL);
BUG_ON(i->head == NULL);
if (list_empty(i->head))
free_irq(up->port.irq, i);
serial_do_unlink(i, up);
+ mutex_unlock(&hash_mutex);
}
/* Base timer interval for polling */
@@ -2447,7 +2493,7 @@ static void serial8250_config_port(struct uart_port *port, int flags)
static int
serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+ if (ser->irq >= nr_irqs || ser->irq < 0 ||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
ser->type == PORT_STARTECH)
@@ -2967,7 +3013,7 @@ EXPORT_SYMBOL(serial8250_unregister_port);
static int __init serial8250_init(void)
{
- int ret, i;
+ int ret;
if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
@@ -2976,9 +3022,6 @@ static int __init serial8250_init(void)
"%d ports, IRQ sharing %sabled\n", nr_uarts,
share_irqs ? "en" : "dis");
- for (i = 0; i < NR_IRQS; i++)
- spin_lock_init(&irq_lists[i].lock);
-
#ifdef CONFIG_SPARC
ret = sunserial_register_minors(&serial8250_reg, UART_NR);
#else
@@ -3006,15 +3049,15 @@ static int __init serial8250_init(void)
goto out;
platform_device_del(serial8250_isa_devs);
- put_dev:
+put_dev:
platform_device_put(serial8250_isa_devs);
- unreg_uart_drv:
+unreg_uart_drv:
#ifdef CONFIG_SPARC
sunserial_unregister_minors(&serial8250_reg, UART_NR);
#else
uart_unregister_driver(&serial8250_reg);
#endif
- out:
+out:
return ret;
}
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 0416ad3bc12..418b4fe9a0a 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -111,7 +111,7 @@ static struct parisc_driver serial_driver = {
.probe = serial_init_chip,
};
-int __init probe_serial_gsc(void)
+static int __init probe_serial_gsc(void)
{
register_parisc_driver(&lasi_driver);
register_parisc_driver(&serial_driver);
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index c014ffb110e..5450a0e5ecd 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1100,6 +1100,8 @@ enum pci_board_num_t {
pbn_b0_4_1843200_200,
pbn_b0_8_1843200_200,
+ pbn_b0_1_4000000,
+
pbn_b0_bt_1_115200,
pbn_b0_bt_2_115200,
pbn_b0_bt_8_115200,
@@ -1167,6 +1169,10 @@ enum pci_board_num_t {
pbn_exsys_4055,
pbn_plx_romulus,
pbn_oxsemi,
+ pbn_oxsemi_1_4000000,
+ pbn_oxsemi_2_4000000,
+ pbn_oxsemi_4_4000000,
+ pbn_oxsemi_8_4000000,
pbn_intel_i960,
pbn_sgi_ioc3,
pbn_computone_4,
@@ -1290,6 +1296,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 1843200,
.uart_offset = 0x200,
},
+ [pbn_b0_1_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 4000000,
+ .uart_offset = 8,
+ },
[pbn_b0_bt_1_115200] = {
.flags = FL_BASE0|FL_BASE_BARS,
@@ -1625,6 +1637,35 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 8,
},
+ [pbn_oxsemi_1_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_oxsemi_2_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_oxsemi_4_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_oxsemi_8_4000000] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 4000000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+
/*
* EKF addition for i960 Boards form EKF with serial port.
@@ -1813,6 +1854,39 @@ serial_pci_matches(struct pciserial_board *board,
board->first_offset == guessed->first_offset;
}
+/*
+ * Oxford Semiconductor Inc.
+ * Check that device is part of the Tornado range of devices, then determine
+ * the number of ports available on the device.
+ */
+static int pci_oxsemi_tornado_init(struct pci_dev *dev, struct pciserial_board *board)
+{
+ u8 __iomem *p;
+ unsigned long deviceID;
+ unsigned int number_uarts;
+
+ /* OxSemi Tornado devices are all 0xCxxx */
+ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+ (dev->device & 0xF000) != 0xC000)
+ return 0;
+
+ p = pci_iomap(dev, 0, 5);
+ if (p == NULL)
+ return -ENOMEM;
+
+ deviceID = ioread32(p);
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+ board->num_ports = number_uarts;
+ printk(KERN_DEBUG
+ "%d ports detected on Oxford PCI Express device\n",
+ number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return 0;
+}
+
struct serial_private *
pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
{
@@ -1821,6 +1895,13 @@ pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
+ /*
+ * Find number of ports on board
+ */
+ if (dev->vendor == PCI_VENDOR_ID_OXSEMI ||
+ dev->vendor == PCI_VENDOR_ID_MAINPINE)
+ pci_oxsemi_tornado_init(dev, board);
+
nr_ports = board->num_ports;
/*
@@ -2301,6 +2382,156 @@ static struct pci_device_id serial_pci_tbl[] = {
pbn_b0_bt_2_921600 },
/*
+ * Oxford Semiconductor Inc. Tornado PCI express device range.
+ */
+ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ /*
+ * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ /*
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
* from skokodyn@yahoo.com
*/
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index db783b77a88..c94d3c4b752 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -457,7 +457,7 @@ config SERIAL_SAMSUNG
config SERIAL_SAMSUNG_DEBUG
bool "Samsung SoC serial debug"
- depends on SERIAL_SAMSUNG
+ depends on SERIAL_SAMSUNG && DEBUG_LL
help
Add support for debugging the serial driver. Since this is
generally being used as a console, we use our own output
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 90b56c2c31e..71562689116 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -512,7 +512,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ if (ser->irq < 0 || ser->irq >= nr_irqs)
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 9d08f27208a..b7180046f8d 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -572,7 +572,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ if (ser->irq < 0 || ser->irq >= nr_irqs)
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index a6c4d744495..bde4b4b0b80 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -623,7 +623,7 @@ static int cpm_uart_verify_port(struct uart_port *port,
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ if (ser->irq < 0 || ser->irq >= nr_irqs)
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 23d03051101..611c97a1565 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -922,7 +922,7 @@ static void m32r_sio_config_port(struct uart_port *port, int flags)
static int
m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+ if (ser->irq >= nr_irqs || ser->irq < 0 ||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
ser->type >= ARRAY_SIZE(uart_config))
return -EINVAL;
@@ -1162,7 +1162,7 @@ static int __init m32r_sio_init(void)
printk(KERN_INFO "Serial: M32R SIO driver\n");
- for (i = 0; i < NR_IRQS; i++)
+ for (i = 0; i < nr_irqs; i++)
spin_lock_init(&irq_lists[i].lock);
ret = uart_register_driver(&m32r_sio_reg);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 6bdf3362e3b..874786a11fe 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -741,7 +741,7 @@ static int uart_set_info(struct uart_state *state,
if (port->ops->verify_port)
retval = port->ops->verify_port(port, &new_serial);
- if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+ if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
(new_serial.baud_base < 9600))
retval = -EINVAL;
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index cb49a5ac022..61dc8b3daa2 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -460,7 +460,7 @@ static int lh7a40xuart_verify_port (struct uart_port* port,
if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ if (ser->irq < 0 || ser->irq >= nr_irqs)
ret = -EINVAL;
if (ser->baud_base < 9600) /* *** FIXME: is this true? */
ret = -EINVAL;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 8fcb4c5b9a2..7313c2edcb8 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -1039,7 +1039,7 @@ static int __devinit serial_txx9_probe(struct platform_device *dev)
ret = serial_txx9_register_port(&port);
if (ret < 0) {
dev_err(&dev->dev, "unable to register port at index %d "
- "(IO%x MEM%llx IRQ%d): %d\n", i,
+ "(IO%lx MEM%llx IRQ%d): %d\n", i,
p->iobase, (unsigned long long)p->mapbase,
p->irq, ret);
}
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 3df2aaec829..f0658d2c45b 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -3,7 +3,7 @@
*
* SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
*
- * Copyright (C) 2002 - 2006 Paul Mundt
+ * Copyright (C) 2002 - 2008 Paul Mundt
* Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
*
* based off of the old drivers/char/sh-sci.c by:
@@ -46,6 +46,7 @@
#include <linux/cpufreq.h>
#include <linux/clk.h>
#include <linux/ctype.h>
+#include <linux/err.h>
#ifdef CONFIG_SUPERH
#include <asm/clock.h>
@@ -78,7 +79,7 @@ struct sci_port {
struct timer_list break_timer;
int break_flag;
-#ifdef CONFIG_SUPERH
+#ifdef CONFIG_HAVE_CLK
/* Port clock */
struct clk *clk;
#endif
@@ -831,7 +832,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
return IRQ_HANDLED;
}
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK)
/*
* Here we define a transistion notifier so that we can update all of our
* ports' baud rate when the peripheral clock changes.
@@ -860,7 +861,7 @@ static int sci_notifier(struct notifier_block *self,
* Clean this up later..
*/
clk = clk_get(NULL, "module_clk");
- port->uartclk = clk_get_rate(clk) * 16;
+ port->uartclk = clk_get_rate(clk);
clk_put(clk);
}
@@ -873,7 +874,7 @@ static int sci_notifier(struct notifier_block *self,
}
static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 };
-#endif /* CONFIG_CPU_FREQ */
+#endif /* CONFIG_CPU_FREQ && CONFIG_HAVE_CLK */
static int sci_request_irq(struct sci_port *port)
{
@@ -1008,7 +1009,7 @@ static int sci_startup(struct uart_port *port)
if (s->enable)
s->enable(port);
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#ifdef CONFIG_HAVE_CLK
s->clk = clk_get(NULL, "module_clk");
#endif
@@ -1030,7 +1031,7 @@ static void sci_shutdown(struct uart_port *port)
if (s->disable)
s->disable(port);
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#ifdef CONFIG_HAVE_CLK
clk_put(s->clk);
s->clk = NULL;
#endif
@@ -1041,24 +1042,11 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct sci_port *s = &sci_ports[port->line];
unsigned int status, baud, smr_val;
- int t;
+ int t = -1;
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-
- switch (baud) {
- case 0:
- t = -1;
- break;
- default:
- {
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
- t = SCBRR_VALUE(baud, clk_get_rate(s->clk));
-#else
- t = SCBRR_VALUE(baud);
-#endif
- break;
- }
- }
+ if (likely(baud))
+ t = SCBRR_VALUE(baud, port->uartclk);
do {
status = sci_in(port, SCxSR);
@@ -1113,7 +1101,7 @@ static const char *sci_type(struct uart_port *port)
case PORT_IRDA: return "irda";
}
- return 0;
+ return NULL;
}
static void sci_release_port(struct uart_port *port)
@@ -1145,19 +1133,23 @@ static void sci_config_port(struct uart_port *port, int flags)
break;
}
-#if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
- if (port->mapbase == 0)
+ if (port->flags & UPF_IOREMAP && !port->membase) {
+#if defined(CONFIG_SUPERH64)
port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF");
-
- port->membase = (void __iomem *)port->mapbase;
+ port->membase = (void __iomem *)port->mapbase;
+#else
+ port->membase = ioremap_nocache(port->mapbase, 0x40);
#endif
+
+ printk(KERN_ERR "sci: can't remap port#%d\n", port->line);
+ }
}
static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{
struct sci_port *s = &sci_ports[port->line];
- if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > NR_IRQS)
+ if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
return -EINVAL;
if (ser->baud_base < 2400)
/* No paper tape reader for Mitch.. */
@@ -1207,17 +1199,17 @@ static void __init sci_init_ports(void)
sci_ports[i].disable = h8300_sci_disable;
#endif
sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK;
-#elif defined(CONFIG_SUPERH64)
- sci_ports[i].port.uartclk = current_cpu_data.module_clock * 16;
-#else
+#elif defined(CONFIG_HAVE_CLK)
/*
* XXX: We should use a proper SCI/SCIF clock
*/
{
struct clk *clk = clk_get(NULL, "module_clk");
- sci_ports[i].port.uartclk = clk_get_rate(clk) * 16;
+ sci_ports[i].port.uartclk = clk_get_rate(clk);
clk_put(clk);
}
+#else
+#error "Need a valid uartclk"
#endif
sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i];
@@ -1285,7 +1277,7 @@ static int __init serial_console_setup(struct console *co, char *options)
port->type = serial_console_port->type;
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#ifdef CONFIG_HAVE_CLK
if (!serial_console_port->clk)
serial_console_port->clk = clk_get(NULL, "module_clk");
#endif
@@ -1436,7 +1428,7 @@ static struct uart_driver sci_uart_driver = {
static int __devinit sci_probe(struct platform_device *dev)
{
struct plat_sci_port *p = dev->dev.platform_data;
- int i;
+ int i, ret = -EINVAL;
for (i = 0; p && p->flags != 0; p++, i++) {
struct sci_port *sciport = &sci_ports[i];
@@ -1453,12 +1445,22 @@ static int __devinit sci_probe(struct platform_device *dev)
sciport->port.mapbase = p->mapbase;
- /*
- * For the simple (and majority of) cases where we don't need
- * to do any remapping, just cast the cookie directly.
- */
- if (p->mapbase && !p->membase && !(p->flags & UPF_IOREMAP))
- p->membase = (void __iomem *)p->mapbase;
+ if (p->mapbase && !p->membase) {
+ if (p->flags & UPF_IOREMAP) {
+ p->membase = ioremap_nocache(p->mapbase, 0x40);
+ if (IS_ERR(p->membase)) {
+ ret = PTR_ERR(p->membase);
+ goto err_unreg;
+ }
+ } else {
+ /*
+ * For the simple (and majority of) cases
+ * where we don't need to do any remapping,
+ * just cast the cookie directly.
+ */
+ p->membase = (void __iomem *)p->mapbase;
+ }
+ }
sciport->port.membase = p->membase;
@@ -1479,7 +1481,7 @@ static int __devinit sci_probe(struct platform_device *dev)
kgdb_putchar = kgdb_sci_putchar;
#endif
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK)
cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
dev_info(&dev->dev, "CPU frequency notifier registered\n");
#endif
@@ -1489,6 +1491,12 @@ static int __devinit sci_probe(struct platform_device *dev)
#endif
return 0;
+
+err_unreg:
+ for (i = i - 1; i >= 0; i--)
+ uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port);
+
+ return ret;
}
static int __devexit sci_remove(struct platform_device *dev)
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 8a0749e34ca..7cd28b22680 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -320,18 +320,16 @@
#define SCI_EVENT_WRITE_WAKEUP 0
#define SCI_IN(size, offset) \
- unsigned int addr = port->mapbase + (offset); \
if ((size) == 8) { \
- return ctrl_inb(addr); \
+ return ioread8(port->membase + (offset)); \
} else { \
- return ctrl_inw(addr); \
+ return ioread16(port->membase + (offset)); \
}
#define SCI_OUT(size, offset, value) \
- unsigned int addr = port->mapbase + (offset); \
if ((size) == 8) { \
- ctrl_outb(value, addr); \
+ iowrite8(value, port->membase + (offset)); \
} else if ((size) == 16) { \
- ctrl_outw(value, addr); \
+ iowrite16(value, port->membase + (offset)); \
}
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
@@ -791,11 +789,16 @@ static inline int sci_rxd_in(struct uart_port *port)
defined(CONFIG_CPU_SUBTYPE_SH7721)
#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(16*bps)-1)
+static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
+{
+ if (port->type == PORT_SCIF)
+ return (clk+16*bps)/(32*bps)-1;
+ else
+ return ((clk*2)+16*bps)/(16*bps)-1;
+}
+#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
#elif defined(__H8300H__) || defined(__H8300S__)
-#define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
-#elif defined(CONFIG_SUPERH64)
-#define SCBRR_VALUE(bps) ((current_cpu_data.module_clock+16*bps)/(32*bps)-1)
+#define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
#else /* Generic SH */
#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
#endif
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index b73e3c0056c..d5276c012f7 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -61,7 +61,7 @@
#define SN_SAL_BUFFER_SIZE (64 * (1 << 10))
#define SN_SAL_UART_FIFO_DEPTH 16
-#define SN_SAL_UART_FIFO_SPEED_CPS 9600/10
+#define SN_SAL_UART_FIFO_SPEED_CPS (9600/10)
/* sn_transmit_chars() calling args */
#define TRANSMIT_BUFFERED 0
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index 539c933b335..315a9333ca3 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -1066,7 +1066,7 @@ static int qe_uart_verify_port(struct uart_port *port,
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
return -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ if (ser->irq < 0 || ser->irq >= nr_irqs)
return -EINVAL;
if (ser->baud_base < 9600)
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
index a96f4a8cfeb..6a025cefe6d 100644
--- a/drivers/sh/Makefile
+++ b/drivers/sh/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for the SuperH specific drivers.
#
-
obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_MAPLE) += maple/
+obj-y += intc.o
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
new file mode 100644
index 00000000000..58d24c5a76c
--- /dev/null
+++ b/drivers/sh/intc.c
@@ -0,0 +1,713 @@
+/*
+ * Shared interrupt handling code for IPR and INTC2 types of IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ *
+ * Based on intc2.c and ipr.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <linux/sh_intc.h>
+
+#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
+ ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
+ ((addr_e) << 16) | ((addr_d << 24)))
+
+#define _INTC_SHIFT(h) (h & 0x1f)
+#define _INTC_WIDTH(h) ((h >> 5) & 0xf)
+#define _INTC_FN(h) ((h >> 9) & 0xf)
+#define _INTC_MODE(h) ((h >> 13) & 0x7)
+#define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
+#define _INTC_ADDR_D(h) ((h >> 24) & 0xff)
+
+struct intc_handle_int {
+ unsigned int irq;
+ unsigned long handle;
+};
+
+struct intc_desc_int {
+ unsigned long *reg;
+#ifdef CONFIG_SMP
+ unsigned long *smp;
+#endif
+ unsigned int nr_reg;
+ struct intc_handle_int *prio;
+ unsigned int nr_prio;
+ struct intc_handle_int *sense;
+ unsigned int nr_sense;
+ struct irq_chip chip;
+};
+
+#ifdef CONFIG_SMP
+#define IS_SMP(x) x.smp
+#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
+#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
+#else
+#define IS_SMP(x) 0
+#define INTC_REG(d, x, c) (d->reg[(x)])
+#define SMP_NR(d, x) 1
+#endif
+
+static unsigned int intc_prio_level[NR_IRQS]; /* for now */
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+static unsigned long ack_handle[NR_IRQS];
+#endif
+
+static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
+{
+ struct irq_chip *chip = get_irq_chip(irq);
+ return (void *)((char *)chip - offsetof(struct intc_desc_int, chip));
+}
+
+static inline unsigned int set_field(unsigned int value,
+ unsigned int field_value,
+ unsigned int handle)
+{
+ unsigned int width = _INTC_WIDTH(handle);
+ unsigned int shift = _INTC_SHIFT(handle);
+
+ value &= ~(((1 << width) - 1) << shift);
+ value |= field_value << shift;
+ return value;
+}
+
+static void write_8(unsigned long addr, unsigned long h, unsigned long data)
+{
+ __raw_writeb(set_field(0, data, h), addr);
+}
+
+static void write_16(unsigned long addr, unsigned long h, unsigned long data)
+{
+ __raw_writew(set_field(0, data, h), addr);
+}
+
+static void write_32(unsigned long addr, unsigned long h, unsigned long data)
+{
+ __raw_writel(set_field(0, data, h), addr);
+}
+
+static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
+ local_irq_restore(flags);
+}
+
+static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ __raw_writew(set_field(__raw_readw(addr), data, h), addr);
+ local_irq_restore(flags);
+}
+
+static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ __raw_writel(set_field(__raw_readl(addr), data, h), addr);
+ local_irq_restore(flags);
+}
+
+enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 };
+
+static void (*intc_reg_fns[])(unsigned long addr,
+ unsigned long h,
+ unsigned long data) = {
+ [REG_FN_WRITE_BASE + 0] = write_8,
+ [REG_FN_WRITE_BASE + 1] = write_16,
+ [REG_FN_WRITE_BASE + 3] = write_32,
+ [REG_FN_MODIFY_BASE + 0] = modify_8,
+ [REG_FN_MODIFY_BASE + 1] = modify_16,
+ [REG_FN_MODIFY_BASE + 3] = modify_32,
+};
+
+enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
+ MODE_MASK_REG, /* Bit(s) set -> interrupt disabled */
+ MODE_DUAL_REG, /* Two registers, set bit to enable / disable */
+ MODE_PRIO_REG, /* Priority value written to enable interrupt */
+ MODE_PCLR_REG, /* Above plus all bits set to disable interrupt */
+};
+
+static void intc_mode_field(unsigned long addr,
+ unsigned long handle,
+ void (*fn)(unsigned long,
+ unsigned long,
+ unsigned long),
+ unsigned int irq)
+{
+ fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
+}
+
+static void intc_mode_zero(unsigned long addr,
+ unsigned long handle,
+ void (*fn)(unsigned long,
+ unsigned long,
+ unsigned long),
+ unsigned int irq)
+{
+ fn(addr, handle, 0);
+}
+
+static void intc_mode_prio(unsigned long addr,
+ unsigned long handle,
+ void (*fn)(unsigned long,
+ unsigned long,
+ unsigned long),
+ unsigned int irq)
+{
+ fn(addr, handle, intc_prio_level[irq]);
+}
+
+static void (*intc_enable_fns[])(unsigned long addr,
+ unsigned long handle,
+ void (*fn)(unsigned long,
+ unsigned long,
+ unsigned long),
+ unsigned int irq) = {
+ [MODE_ENABLE_REG] = intc_mode_field,
+ [MODE_MASK_REG] = intc_mode_zero,
+ [MODE_DUAL_REG] = intc_mode_field,
+ [MODE_PRIO_REG] = intc_mode_prio,
+ [MODE_PCLR_REG] = intc_mode_prio,
+};
+
+static void (*intc_disable_fns[])(unsigned long addr,
+ unsigned long handle,
+ void (*fn)(unsigned long,
+ unsigned long,
+ unsigned long),
+ unsigned int irq) = {
+ [MODE_ENABLE_REG] = intc_mode_zero,
+ [MODE_MASK_REG] = intc_mode_field,
+ [MODE_DUAL_REG] = intc_mode_field,
+ [MODE_PRIO_REG] = intc_mode_zero,
+ [MODE_PCLR_REG] = intc_mode_field,
+};
+
+static inline void _intc_enable(unsigned int irq, unsigned long handle)
+{
+ struct intc_desc_int *d = get_intc_desc(irq);
+ unsigned long addr;
+ unsigned int cpu;
+
+ for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
+ addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
+ intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
+ [_INTC_FN(handle)], irq);
+ }
+}
+
+static void intc_enable(unsigned int irq)
+{
+ _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
+}
+
+static void intc_disable(unsigned int irq)
+{
+ struct intc_desc_int *d = get_intc_desc(irq);
+ unsigned long handle = (unsigned long) get_irq_chip_data(irq);
+ unsigned long addr;
+ unsigned int cpu;
+
+ for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
+ addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
+ intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
+ [_INTC_FN(handle)], irq);
+ }
+}
+
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+static void intc_mask_ack(unsigned int irq)
+{
+ struct intc_desc_int *d = get_intc_desc(irq);
+ unsigned long handle = ack_handle[irq];
+ unsigned long addr;
+
+ intc_disable(irq);
+
+ /* read register and write zero only to the assocaited bit */
+
+ if (handle) {
+ addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+ switch (_INTC_FN(handle)) {
+ case REG_FN_MODIFY_BASE + 0: /* 8bit */
+ __raw_readb(addr);
+ __raw_writeb(0xff ^ set_field(0, 1, handle), addr);
+ break;
+ case REG_FN_MODIFY_BASE + 1: /* 16bit */
+ __raw_readw(addr);
+ __raw_writew(0xffff ^ set_field(0, 1, handle), addr);
+ break;
+ case REG_FN_MODIFY_BASE + 3: /* 32bit */
+ __raw_readl(addr);
+ __raw_writel(0xffffffff ^ set_field(0, 1, handle), addr);
+ break;
+ default:
+ BUG();
+ break;
+ }
+ }
+}
+#endif
+
+static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
+ unsigned int nr_hp,
+ unsigned int irq)
+{
+ int i;
+
+ /* this doesn't scale well, but...
+ *
+ * this function should only be used for cerain uncommon
+ * operations such as intc_set_priority() and intc_set_sense()
+ * and in those rare cases performance doesn't matter that much.
+ * keeping the memory footprint low is more important.
+ *
+ * one rather simple way to speed this up and still keep the
+ * memory footprint down is to make sure the array is sorted
+ * and then perform a bisect to lookup the irq.
+ */
+
+ for (i = 0; i < nr_hp; i++) {
+ if ((hp + i)->irq != irq)
+ continue;
+
+ return hp + i;
+ }
+
+ return NULL;
+}
+
+int intc_set_priority(unsigned int irq, unsigned int prio)
+{
+ struct intc_desc_int *d = get_intc_desc(irq);
+ struct intc_handle_int *ihp;
+
+ if (!intc_prio_level[irq] || prio <= 1)
+ return -EINVAL;
+
+ ihp = intc_find_irq(d->prio, d->nr_prio, irq);
+ if (ihp) {
+ if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
+ return -EINVAL;
+
+ intc_prio_level[irq] = prio;
+
+ /*
+ * only set secondary masking method directly
+ * primary masking method is using intc_prio_level[irq]
+ * priority level will be set during next enable()
+ */
+
+ if (_INTC_FN(ihp->handle) != REG_FN_ERR)
+ _intc_enable(irq, ihp->handle);
+ }
+ return 0;
+}
+
+#define VALID(x) (x | 0x80)
+
+static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
+ [IRQ_TYPE_EDGE_FALLING] = VALID(0),
+ [IRQ_TYPE_EDGE_RISING] = VALID(1),
+ [IRQ_TYPE_LEVEL_LOW] = VALID(2),
+ /* SH7706, SH7707 and SH7709 do not support high level triggered */
+#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
+ !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
+ !defined(CONFIG_CPU_SUBTYPE_SH7709)
+ [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
+#endif
+};
+
+static int intc_set_sense(unsigned int irq, unsigned int type)
+{
+ struct intc_desc_int *d = get_intc_desc(irq);
+ unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
+ struct intc_handle_int *ihp;
+ unsigned long addr;
+
+ if (!value)
+ return -EINVAL;
+
+ ihp = intc_find_irq(d->sense, d->nr_sense, irq);
+ if (ihp) {
+ addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
+ intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
+ }
+ return 0;
+}
+
+static unsigned int __init intc_get_reg(struct intc_desc_int *d,
+ unsigned long address)
+{
+ unsigned int k;
+
+ for (k = 0; k < d->nr_reg; k++) {
+ if (d->reg[k] == address)
+ return k;
+ }
+
+ BUG();
+ return 0;
+}
+
+static intc_enum __init intc_grp_id(struct intc_desc *desc,
+ intc_enum enum_id)
+{
+ struct intc_group *g = desc->groups;
+ unsigned int i, j;
+
+ for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
+ g = desc->groups + i;
+
+ for (j = 0; g->enum_ids[j]; j++) {
+ if (g->enum_ids[j] != enum_id)
+ continue;
+
+ return g->enum_id;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int __init intc_mask_data(struct intc_desc *desc,
+ struct intc_desc_int *d,
+ intc_enum enum_id, int do_grps)
+{
+ struct intc_mask_reg *mr = desc->mask_regs;
+ unsigned int i, j, fn, mode;
+ unsigned long reg_e, reg_d;
+
+ for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
+ mr = desc->mask_regs + i;
+
+ for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+ if (mr->enum_ids[j] != enum_id)
+ continue;
+
+ if (mr->set_reg && mr->clr_reg) {
+ fn = REG_FN_WRITE_BASE;
+ mode = MODE_DUAL_REG;
+ reg_e = mr->clr_reg;
+ reg_d = mr->set_reg;
+ } else {
+ fn = REG_FN_MODIFY_BASE;
+ if (mr->set_reg) {
+ mode = MODE_ENABLE_REG;
+ reg_e = mr->set_reg;
+ reg_d = mr->set_reg;
+ } else {
+ mode = MODE_MASK_REG;
+ reg_e = mr->clr_reg;
+ reg_d = mr->clr_reg;
+ }
+ }
+
+ fn += (mr->reg_width >> 3) - 1;
+ return _INTC_MK(fn, mode,
+ intc_get_reg(d, reg_e),
+ intc_get_reg(d, reg_d),
+ 1,
+ (mr->reg_width - 1) - j);
+ }
+ }
+
+ if (do_grps)
+ return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
+
+ return 0;
+}
+
+static unsigned int __init intc_prio_data(struct intc_desc *desc,
+ struct intc_desc_int *d,
+ intc_enum enum_id, int do_grps)
+{
+ struct intc_prio_reg *pr = desc->prio_regs;
+ unsigned int i, j, fn, mode, bit;
+ unsigned long reg_e, reg_d;
+
+ for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
+ pr = desc->prio_regs + i;
+
+ for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
+ if (pr->enum_ids[j] != enum_id)
+ continue;
+
+ if (pr->set_reg && pr->clr_reg) {
+ fn = REG_FN_WRITE_BASE;
+ mode = MODE_PCLR_REG;
+ reg_e = pr->set_reg;
+ reg_d = pr->clr_reg;
+ } else {
+ fn = REG_FN_MODIFY_BASE;
+ mode = MODE_PRIO_REG;
+ if (!pr->set_reg)
+ BUG();
+ reg_e = pr->set_reg;
+ reg_d = pr->set_reg;
+ }
+
+ fn += (pr->reg_width >> 3) - 1;
+
+ BUG_ON((j + 1) * pr->field_width > pr->reg_width);
+
+ bit = pr->reg_width - ((j + 1) * pr->field_width);
+
+ return _INTC_MK(fn, mode,
+ intc_get_reg(d, reg_e),
+ intc_get_reg(d, reg_d),
+ pr->field_width, bit);
+ }
+ }
+
+ if (do_grps)
+ return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);
+
+ return 0;
+}
+
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+static unsigned int __init intc_ack_data(struct intc_desc *desc,
+ struct intc_desc_int *d,
+ intc_enum enum_id)
+{
+ struct intc_mask_reg *mr = desc->ack_regs;
+ unsigned int i, j, fn, mode;
+ unsigned long reg_e, reg_d;
+
+ for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) {
+ mr = desc->ack_regs + i;
+
+ for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+ if (mr->enum_ids[j] != enum_id)
+ continue;
+
+ fn = REG_FN_MODIFY_BASE;
+ mode = MODE_ENABLE_REG;
+ reg_e = mr->set_reg;
+ reg_d = mr->set_reg;
+
+ fn += (mr->reg_width >> 3) - 1;
+ return _INTC_MK(fn, mode,
+ intc_get_reg(d, reg_e),
+ intc_get_reg(d, reg_d),
+ 1,
+ (mr->reg_width - 1) - j);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static unsigned int __init intc_sense_data(struct intc_desc *desc,
+ struct intc_desc_int *d,
+ intc_enum enum_id)
+{
+ struct intc_sense_reg *sr = desc->sense_regs;
+ unsigned int i, j, fn, bit;
+
+ for (i = 0; sr && enum_id && i < desc->nr_sense_regs; i++) {
+ sr = desc->sense_regs + i;
+
+ for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
+ if (sr->enum_ids[j] != enum_id)
+ continue;
+
+ fn = REG_FN_MODIFY_BASE;
+ fn += (sr->reg_width >> 3) - 1;
+
+ BUG_ON((j + 1) * sr->field_width > sr->reg_width);
+
+ bit = sr->reg_width - ((j + 1) * sr->field_width);
+
+ return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
+ 0, sr->field_width, bit);
+ }
+ }
+
+ return 0;
+}
+
+static void __init intc_register_irq(struct intc_desc *desc,
+ struct intc_desc_int *d,
+ intc_enum enum_id,
+ unsigned int irq)
+{
+ struct intc_handle_int *hp;
+ unsigned int data[2], primary;
+
+ /* Prefer single interrupt source bitmap over other combinations:
+ * 1. bitmap, single interrupt source
+ * 2. priority, single interrupt source
+ * 3. bitmap, multiple interrupt sources (groups)
+ * 4. priority, multiple interrupt sources (groups)
+ */
+
+ data[0] = intc_mask_data(desc, d, enum_id, 0);
+ data[1] = intc_prio_data(desc, d, enum_id, 0);
+
+ primary = 0;
+ if (!data[0] && data[1])
+ primary = 1;
+
+ data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
+ data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
+
+ if (!data[primary])
+ primary ^= 1;
+
+ BUG_ON(!data[primary]); /* must have primary masking method */
+
+ disable_irq_nosync(irq);
+ set_irq_chip_and_handler_name(irq, &d->chip,
+ handle_level_irq, "level");
+ set_irq_chip_data(irq, (void *)data[primary]);
+
+ /* set priority level
+ * - this needs to be at least 2 for 5-bit priorities on 7780
+ */
+ intc_prio_level[irq] = 2;
+
+ /* enable secondary masking method if present */
+ if (data[!primary])
+ _intc_enable(irq, data[!primary]);
+
+ /* add irq to d->prio list if priority is available */
+ if (data[1]) {
+ hp = d->prio + d->nr_prio;
+ hp->irq = irq;
+ hp->handle = data[1];
+
+ if (primary) {
+ /*
+ * only secondary priority should access registers, so
+ * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
+ */
+
+ hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
+ hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
+ }
+ d->nr_prio++;
+ }
+
+ /* add irq to d->sense list if sense is available */
+ data[0] = intc_sense_data(desc, d, enum_id);
+ if (data[0]) {
+ (d->sense + d->nr_sense)->irq = irq;
+ (d->sense + d->nr_sense)->handle = data[0];
+ d->nr_sense++;
+ }
+
+ /* irq should be disabled by default */
+ d->chip.mask(irq);
+
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+ if (desc->ack_regs)
+ ack_handle[irq] = intc_ack_data(desc, d, enum_id);
+#endif
+}
+
+static unsigned int __init save_reg(struct intc_desc_int *d,
+ unsigned int cnt,
+ unsigned long value,
+ unsigned int smp)
+{
+ if (value) {
+ d->reg[cnt] = value;
+#ifdef CONFIG_SMP
+ d->smp[cnt] = smp;
+#endif
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void __init register_intc_controller(struct intc_desc *desc)
+{
+ unsigned int i, k, smp;
+ struct intc_desc_int *d;
+
+ d = alloc_bootmem(sizeof(*d));
+
+ d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
+ d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
+ d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
+
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+ d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
+#endif
+ d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
+#ifdef CONFIG_SMP
+ d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
+#endif
+ k = 0;
+
+ if (desc->mask_regs) {
+ for (i = 0; i < desc->nr_mask_regs; i++) {
+ smp = IS_SMP(desc->mask_regs[i]);
+ k += save_reg(d, k, desc->mask_regs[i].set_reg, smp);
+ k += save_reg(d, k, desc->mask_regs[i].clr_reg, smp);
+ }
+ }
+
+ if (desc->prio_regs) {
+ d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));
+
+ for (i = 0; i < desc->nr_prio_regs; i++) {
+ smp = IS_SMP(desc->prio_regs[i]);
+ k += save_reg(d, k, desc->prio_regs[i].set_reg, smp);
+ k += save_reg(d, k, desc->prio_regs[i].clr_reg, smp);
+ }
+ }
+
+ if (desc->sense_regs) {
+ d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));
+
+ for (i = 0; i < desc->nr_sense_regs; i++) {
+ k += save_reg(d, k, desc->sense_regs[i].reg, 0);
+ }
+ }
+
+ d->chip.name = desc->name;
+ d->chip.mask = intc_disable;
+ d->chip.unmask = intc_enable;
+ d->chip.mask_ack = intc_disable;
+ d->chip.set_type = intc_set_sense;
+
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+ if (desc->ack_regs) {
+ for (i = 0; i < desc->nr_ack_regs; i++)
+ k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
+
+ d->chip.mask_ack = intc_mask_ack;
+ }
+#endif
+
+ BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
+
+ for (i = 0; i < desc->nr_vectors; i++) {
+ struct intc_vect *vect = desc->vectors + i;
+
+ intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
+ }
+}
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 2a79decd7df..e1654f59eb7 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -43,4 +43,6 @@ source "drivers/staging/echo/Kconfig"
source "drivers/staging/at76_usb/Kconfig"
+source "drivers/staging/poch/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 325bca4f71c..71c4d53760b 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_USB_ATMEL) += at76_usb/
+obj-$(CONFIG_POCH) += poch/
diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c
index 52df0c66518..174e2bec922 100644
--- a/drivers/staging/at76_usb/at76_usb.c
+++ b/drivers/staging/at76_usb/at76_usb.c
@@ -2319,9 +2319,11 @@ static int at76_iw_handler_get_scan(struct net_device *netdev,
if (!iwe)
return -ENOMEM;
- if (priv->scan_state != SCAN_COMPLETED)
+ if (priv->scan_state != SCAN_COMPLETED) {
/* scan not yet finished */
+ kfree(iwe);
return -EAGAIN;
+ }
spin_lock_irqsave(&priv->bss_list_spinlock, flags);
diff --git a/drivers/staging/echo/bit_operations.h b/drivers/staging/echo/bit_operations.h
index b32f4bf9939..cecdcf3fd75 100644
--- a/drivers/staging/echo/bit_operations.h
+++ b/drivers/staging/echo/bit_operations.h
@@ -30,114 +30,98 @@
#if !defined(_BIT_OPERATIONS_H_)
#define _BIT_OPERATIONS_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#if defined(__i386__) || defined(__x86_64__)
/*! \brief Find the bit position of the highest set bit in a word
\param bits The word to be searched
\return The bit number of the highest set bit, or -1 if the word is zero. */
static __inline__ int top_bit(unsigned int bits)
{
- int res;
-
- __asm__ (" xorl %[res],%[res];\n"
- " decl %[res];\n"
- " bsrl %[bits],%[res]\n"
- : [res] "=&r" (res)
- : [bits] "rm" (bits));
- return res;
+ int res;
+
+ __asm__(" xorl %[res],%[res];\n"
+ " decl %[res];\n"
+ " bsrl %[bits],%[res]\n"
+ :[res] "=&r" (res)
+ :[bits] "rm"(bits)
+ );
+ return res;
}
-/*- End of function --------------------------------------------------------*/
/*! \brief Find the bit position of the lowest set bit in a word
\param bits The word to be searched
\return The bit number of the lowest set bit, or -1 if the word is zero. */
static __inline__ int bottom_bit(unsigned int bits)
{
- int res;
-
- __asm__ (" xorl %[res],%[res];\n"
- " decl %[res];\n"
- " bsfl %[bits],%[res]\n"
- : [res] "=&r" (res)
- : [bits] "rm" (bits));
- return res;
+ int res;
+
+ __asm__(" xorl %[res],%[res];\n"
+ " decl %[res];\n"
+ " bsfl %[bits],%[res]\n"
+ :[res] "=&r" (res)
+ :[bits] "rm"(bits)
+ );
+ return res;
}
-/*- End of function --------------------------------------------------------*/
#else
static __inline__ int top_bit(unsigned int bits)
{
- int i;
-
- if (bits == 0)
- return -1;
- i = 0;
- if (bits & 0xFFFF0000)
- {
- bits &= 0xFFFF0000;
- i += 16;
- }
- if (bits & 0xFF00FF00)
- {
- bits &= 0xFF00FF00;
- i += 8;
- }
- if (bits & 0xF0F0F0F0)
- {
- bits &= 0xF0F0F0F0;
- i += 4;
- }
- if (bits & 0xCCCCCCCC)
- {
- bits &= 0xCCCCCCCC;
- i += 2;
- }
- if (bits & 0xAAAAAAAA)
- {
- bits &= 0xAAAAAAAA;
- i += 1;
- }
- return i;
+ int i;
+
+ if (bits == 0)
+ return -1;
+ i = 0;
+ if (bits & 0xFFFF0000) {
+ bits &= 0xFFFF0000;
+ i += 16;
+ }
+ if (bits & 0xFF00FF00) {
+ bits &= 0xFF00FF00;
+ i += 8;
+ }
+ if (bits & 0xF0F0F0F0) {
+ bits &= 0xF0F0F0F0;
+ i += 4;
+ }
+ if (bits & 0xCCCCCCCC) {
+ bits &= 0xCCCCCCCC;
+ i += 2;
+ }
+ if (bits & 0xAAAAAAAA) {
+ bits &= 0xAAAAAAAA;
+ i += 1;
+ }
+ return i;
}
-/*- End of function --------------------------------------------------------*/
static __inline__ int bottom_bit(unsigned int bits)
{
- int i;
-
- if (bits == 0)
- return -1;
- i = 32;
- if (bits & 0x0000FFFF)
- {
- bits &= 0x0000FFFF;
- i -= 16;
- }
- if (bits & 0x00FF00FF)
- {
- bits &= 0x00FF00FF;
- i -= 8;
- }
- if (bits & 0x0F0F0F0F)
- {
- bits &= 0x0F0F0F0F;
- i -= 4;
- }
- if (bits & 0x33333333)
- {
- bits &= 0x33333333;
- i -= 2;
- }
- if (bits & 0x55555555)
- {
- bits &= 0x55555555;
- i -= 1;
- }
- return i;
+ int i;
+
+ if (bits == 0)
+ return -1;
+ i = 32;
+ if (bits & 0x0000FFFF) {
+ bits &= 0x0000FFFF;
+ i -= 16;
+ }
+ if (bits & 0x00FF00FF) {
+ bits &= 0x00FF00FF;
+ i -= 8;
+ }
+ if (bits & 0x0F0F0F0F) {
+ bits &= 0x0F0F0F0F;
+ i -= 4;
+ }
+ if (bits & 0x33333333) {
+ bits &= 0x33333333;
+ i -= 2;
+ }
+ if (bits & 0x55555555) {
+ bits &= 0x55555555;
+ i -= 1;
+ }
+ return i;
}
-/*- End of function --------------------------------------------------------*/
#endif
/*! \brief Bit reverse a byte.
@@ -146,16 +130,16 @@ static __inline__ int bottom_bit(unsigned int bits)
static __inline__ uint8_t bit_reverse8(uint8_t x)
{
#if defined(__i386__) || defined(__x86_64__)
- /* If multiply is fast */
- return ((x*0x0802U & 0x22110U) | (x*0x8020U & 0x88440U))*0x10101U >> 16;
+ /* If multiply is fast */
+ return ((x * 0x0802U & 0x22110U) | (x * 0x8020U & 0x88440U)) *
+ 0x10101U >> 16;
#else
- /* If multiply is slow, but we have a barrel shifter */
- x = (x >> 4) | (x << 4);
- x = ((x & 0xCC) >> 2) | ((x & 0x33) << 2);
- return ((x & 0xAA) >> 1) | ((x & 0x55) << 1);
+ /* If multiply is slow, but we have a barrel shifter */
+ x = (x >> 4) | (x << 4);
+ x = ((x & 0xCC) >> 2) | ((x & 0x33) << 2);
+ return ((x & 0xAA) >> 1) | ((x & 0x55) << 1);
#endif
}
-/*- End of function --------------------------------------------------------*/
/*! \brief Bit reverse a 16 bit word.
\param data The word to be reversed.
@@ -193,9 +177,8 @@ uint16_t make_mask16(uint16_t x);
\return The word with the single set bit. */
static __inline__ uint32_t least_significant_one32(uint32_t x)
{
- return (x & (-(int32_t) x));
+ return (x & (-(int32_t) x));
}
-/*- End of function --------------------------------------------------------*/
/*! \brief Find the most significant one in a word, and return a word
with just that bit set.
@@ -204,50 +187,42 @@ static __inline__ uint32_t least_significant_one32(uint32_t x)
static __inline__ uint32_t most_significant_one32(uint32_t x)
{
#if defined(__i386__) || defined(__x86_64__)
- return 1 << top_bit(x);
+ return 1 << top_bit(x);
#else
- x = make_mask32(x);
- return (x ^ (x >> 1));
+ x = make_mask32(x);
+ return (x ^ (x >> 1));
#endif
}
-/*- End of function --------------------------------------------------------*/
/*! \brief Find the parity of a byte.
\param x The byte to be checked.
\return 1 for odd, or 0 for even. */
static __inline__ int parity8(uint8_t x)
{
- x = (x ^ (x >> 4)) & 0x0F;
- return (0x6996 >> x) & 1;
+ x = (x ^ (x >> 4)) & 0x0F;
+ return (0x6996 >> x) & 1;
}
-/*- End of function --------------------------------------------------------*/
/*! \brief Find the parity of a 16 bit word.
\param x The word to be checked.
\return 1 for odd, or 0 for even. */
static __inline__ int parity16(uint16_t x)
{
- x ^= (x >> 8);
- x = (x ^ (x >> 4)) & 0x0F;
- return (0x6996 >> x) & 1;
+ x ^= (x >> 8);
+ x = (x ^ (x >> 4)) & 0x0F;
+ return (0x6996 >> x) & 1;
}
-/*- End of function --------------------------------------------------------*/
/*! \brief Find the parity of a 32 bit word.
\param x The word to be checked.
\return 1 for odd, or 0 for even. */
static __inline__ int parity32(uint32_t x)
{
- x ^= (x >> 16);
- x ^= (x >> 8);
- x = (x ^ (x >> 4)) & 0x0F;
- return (0x6996 >> x) & 1;
+ x ^= (x >> 16);
+ x ^= (x >> 8);
+ x = (x ^ (x >> 4)) & 0x0F;
+ return (0x6996 >> x) & 1;
}
-/*- End of function --------------------------------------------------------*/
-
-#ifdef __cplusplus
-}
-#endif
#endif
/*- End of file ------------------------------------------------------------*/
diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c
index 4a281b14fc5..b8f2c5e9dee 100644
--- a/drivers/staging/echo/echo.c
+++ b/drivers/staging/echo/echo.c
@@ -74,7 +74,6 @@
Steve also has some nice notes on echo cancellers in echo.h
-
References:
[1] Ochiai, Areseki, and Ogihara, "Echo Canceller with Two Echo
@@ -105,20 +104,18 @@
Mark, Pawel, and Pavel.
*/
-#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#define malloc(a) kmalloc((a), GFP_KERNEL)
-#define free(a) kfree(a)
#include "bit_operations.h"
#include "echo.h"
#define MIN_TX_POWER_FOR_ADAPTION 64
#define MIN_RX_POWER_FOR_ADAPTION 64
-#define DTD_HANGOVER 600 /* 600 samples, or 75ms */
-#define DC_LOG2BETA 3 /* log2() of DC filter Beta */
+#define DTD_HANGOVER 600 /* 600 samples, or 75ms */
+#define DC_LOG2BETA 3 /* log2() of DC filter Beta */
/*-----------------------------------------------------------------------*\
FUNCTIONS
@@ -126,59 +123,58 @@
/* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */
-
-#ifdef __BLACKFIN_ASM__
-static void __inline__ lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
+#ifdef __bfin__
+static void __inline__ lms_adapt_bg(struct oslec_state *ec, int clean,
+ int shift)
{
- int i, j;
- int offset1;
- int offset2;
- int factor;
- int exp;
- int16_t *phist;
- int n;
-
- if (shift > 0)
- factor = clean << shift;
- else
- factor = clean >> -shift;
-
- /* Update the FIR taps */
-
- offset2 = ec->curr_pos;
- offset1 = ec->taps - offset2;
- phist = &ec->fir_state_bg.history[offset2];
-
- /* st: and en: help us locate the assembler in echo.s */
-
- //asm("st:");
- n = ec->taps;
- for (i = 0, j = offset2; i < n; i++, j++)
- {
- exp = *phist++ * factor;
- ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
- }
- //asm("en:");
-
- /* Note the asm for the inner loop above generated by Blackfin gcc
- 4.1.1 is pretty good (note even parallel instructions used):
-
- R0 = W [P0++] (X);
- R0 *= R2;
- R0 = R0 + R3 (NS) ||
- R1 = W [P1] (X) ||
- nop;
- R0 >>>= 15;
- R0 = R0 + R1;
- W [P1++] = R0;
-
- A block based update algorithm would be much faster but the
- above can't be improved on much. Every instruction saved in
- the loop above is 2 MIPs/ch! The for loop above is where the
- Blackfin spends most of it's time - about 17 MIPs/ch measured
- with speedtest.c with 256 taps (32ms). Write-back and
- Write-through cache gave about the same performance.
- */
+ int i, j;
+ int offset1;
+ int offset2;
+ int factor;
+ int exp;
+ int16_t *phist;
+ int n;
+
+ if (shift > 0)
+ factor = clean << shift;
+ else
+ factor = clean >> -shift;
+
+ /* Update the FIR taps */
+
+ offset2 = ec->curr_pos;
+ offset1 = ec->taps - offset2;
+ phist = &ec->fir_state_bg.history[offset2];
+
+ /* st: and en: help us locate the assembler in echo.s */
+
+ //asm("st:");
+ n = ec->taps;
+ for (i = 0, j = offset2; i < n; i++, j++) {
+ exp = *phist++ * factor;
+ ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
+ }
+ //asm("en:");
+
+ /* Note the asm for the inner loop above generated by Blackfin gcc
+ 4.1.1 is pretty good (note even parallel instructions used):
+
+ R0 = W [P0++] (X);
+ R0 *= R2;
+ R0 = R0 + R3 (NS) ||
+ R1 = W [P1] (X) ||
+ nop;
+ R0 >>>= 15;
+ R0 = R0 + R1;
+ W [P1++] = R0;
+
+ A block based update algorithm would be much faster but the
+ above can't be improved on much. Every instruction saved in
+ the loop above is 2 MIPs/ch! The for loop above is where the
+ Blackfin spends most of it's time - about 17 MIPs/ch measured
+ with speedtest.c with 256 taps (32ms). Write-back and
+ Write-through cache gave about the same performance.
+ */
}
/*
@@ -200,392 +196,393 @@ static void __inline__ lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
*/
#else
-static __inline__ void lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
+static __inline__ void lms_adapt_bg(struct oslec_state *ec, int clean,
+ int shift)
{
- int i;
-
- int offset1;
- int offset2;
- int factor;
- int exp;
-
- if (shift > 0)
- factor = clean << shift;
- else
- factor = clean >> -shift;
-
- /* Update the FIR taps */
-
- offset2 = ec->curr_pos;
- offset1 = ec->taps - offset2;
-
- for (i = ec->taps - 1; i >= offset1; i--)
- {
- exp = (ec->fir_state_bg.history[i - offset1]*factor);
- ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
- }
- for ( ; i >= 0; i--)
- {
- exp = (ec->fir_state_bg.history[i + offset2]*factor);
- ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
- }
+ int i;
+
+ int offset1;
+ int offset2;
+ int factor;
+ int exp;
+
+ if (shift > 0)
+ factor = clean << shift;
+ else
+ factor = clean >> -shift;
+
+ /* Update the FIR taps */
+
+ offset2 = ec->curr_pos;
+ offset1 = ec->taps - offset2;
+
+ for (i = ec->taps - 1; i >= offset1; i--) {
+ exp = (ec->fir_state_bg.history[i - offset1] * factor);
+ ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
+ }
+ for (; i >= 0; i--) {
+ exp = (ec->fir_state_bg.history[i + offset2] * factor);
+ ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
+ }
}
#endif
-/*- End of function --------------------------------------------------------*/
-
-echo_can_state_t *echo_can_create(int len, int adaption_mode)
+struct oslec_state *oslec_create(int len, int adaption_mode)
{
- echo_can_state_t *ec;
- int i;
- int j;
-
- ec = kmalloc(sizeof(*ec), GFP_KERNEL);
- if (ec == NULL)
- return NULL;
- memset(ec, 0, sizeof(*ec));
-
- ec->taps = len;
- ec->log2taps = top_bit(len);
- ec->curr_pos = ec->taps - 1;
-
- for (i = 0; i < 2; i++)
- {
- if ((ec->fir_taps16[i] = (int16_t *) malloc((ec->taps)*sizeof(int16_t))) == NULL)
- {
- for (j = 0; j < i; j++)
- kfree(ec->fir_taps16[j]);
- kfree(ec);
- return NULL;
- }
- memset(ec->fir_taps16[i], 0, (ec->taps)*sizeof(int16_t));
- }
-
- fir16_create(&ec->fir_state,
- ec->fir_taps16[0],
- ec->taps);
- fir16_create(&ec->fir_state_bg,
- ec->fir_taps16[1],
- ec->taps);
-
- for(i=0; i<5; i++) {
- ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
- }
-
- ec->cng_level = 1000;
- echo_can_adaption_mode(ec, adaption_mode);
-
- ec->snapshot = (int16_t*)malloc(ec->taps*sizeof(int16_t));
- memset(ec->snapshot, 0, sizeof(int16_t)*ec->taps);
-
- ec->cond_met = 0;
- ec->Pstates = 0;
- ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
- ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
- ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
- ec->Lbgn = ec->Lbgn_acc = 0;
- ec->Lbgn_upper = 200;
- ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
-
- return ec;
+ struct oslec_state *ec;
+ int i;
+
+ ec = kzalloc(sizeof(*ec), GFP_KERNEL);
+ if (!ec)
+ return NULL;
+
+ ec->taps = len;
+ ec->log2taps = top_bit(len);
+ ec->curr_pos = ec->taps - 1;
+
+ for (i = 0; i < 2; i++) {
+ ec->fir_taps16[i] =
+ kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
+ if (!ec->fir_taps16[i])
+ goto error_oom;
+ }
+
+ fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
+ fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
+
+ for (i = 0; i < 5; i++) {
+ ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
+ }
+
+ ec->cng_level = 1000;
+ oslec_adaption_mode(ec, adaption_mode);
+
+ ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
+ if (!ec->snapshot)
+ goto error_oom;
+
+ ec->cond_met = 0;
+ ec->Pstates = 0;
+ ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
+ ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
+ ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
+ ec->Lbgn = ec->Lbgn_acc = 0;
+ ec->Lbgn_upper = 200;
+ ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
+
+ return ec;
+
+ error_oom:
+ for (i = 0; i < 2; i++)
+ kfree(ec->fir_taps16[i]);
+
+ kfree(ec);
+ return NULL;
}
-/*- End of function --------------------------------------------------------*/
-void echo_can_free(echo_can_state_t *ec)
+EXPORT_SYMBOL_GPL(oslec_create);
+
+void oslec_free(struct oslec_state *ec)
{
int i;
fir16_free(&ec->fir_state);
fir16_free(&ec->fir_state_bg);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 2; i++)
kfree(ec->fir_taps16[i]);
kfree(ec->snapshot);
kfree(ec);
}
-/*- End of function --------------------------------------------------------*/
-void echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode)
+EXPORT_SYMBOL_GPL(oslec_free);
+
+void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
{
- ec->adaption_mode = adaption_mode;
+ ec->adaption_mode = adaption_mode;
}
-/*- End of function --------------------------------------------------------*/
-void echo_can_flush(echo_can_state_t *ec)
+EXPORT_SYMBOL_GPL(oslec_adaption_mode);
+
+void oslec_flush(struct oslec_state *ec)
{
- int i;
+ int i;
- ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
- ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
- ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
+ ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
+ ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
+ ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
- ec->Lbgn = ec->Lbgn_acc = 0;
- ec->Lbgn_upper = 200;
- ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
+ ec->Lbgn = ec->Lbgn_acc = 0;
+ ec->Lbgn_upper = 200;
+ ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
- ec->nonupdate_dwell = 0;
+ ec->nonupdate_dwell = 0;
- fir16_flush(&ec->fir_state);
- fir16_flush(&ec->fir_state_bg);
- ec->fir_state.curr_pos = ec->taps - 1;
- ec->fir_state_bg.curr_pos = ec->taps - 1;
- for (i = 0; i < 2; i++)
- memset(ec->fir_taps16[i], 0, ec->taps*sizeof(int16_t));
+ fir16_flush(&ec->fir_state);
+ fir16_flush(&ec->fir_state_bg);
+ ec->fir_state.curr_pos = ec->taps - 1;
+ ec->fir_state_bg.curr_pos = ec->taps - 1;
+ for (i = 0; i < 2; i++)
+ memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
- ec->curr_pos = ec->taps - 1;
- ec->Pstates = 0;
+ ec->curr_pos = ec->taps - 1;
+ ec->Pstates = 0;
}
-/*- End of function --------------------------------------------------------*/
-void echo_can_snapshot(echo_can_state_t *ec) {
- memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps*sizeof(int16_t));
+EXPORT_SYMBOL_GPL(oslec_flush);
+
+void oslec_snapshot(struct oslec_state *ec)
+{
+ memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
}
-/*- End of function --------------------------------------------------------*/
+
+EXPORT_SYMBOL_GPL(oslec_snapshot);
/* Dual Path Echo Canceller ------------------------------------------------*/
-int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
+int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
{
- int32_t echo_value;
- int clean_bg;
- int tmp, tmp1;
-
- /* Input scaling was found be required to prevent problems when tx
- starts clipping. Another possible way to handle this would be the
- filter coefficent scaling. */
-
- ec->tx = tx; ec->rx = rx;
- tx >>=1;
- rx >>=1;
-
- /*
- Filter DC, 3dB point is 160Hz (I think), note 32 bit precision required
- otherwise values do not track down to 0. Zero at DC, Pole at (1-Beta)
- only real axis. Some chip sets (like Si labs) don't need
- this, but something like a $10 X100P card does. Any DC really slows
- down convergence.
-
- Note: removes some low frequency from the signal, this reduces
- the speech quality when listening to samples through headphones
- but may not be obvious through a telephone handset.
-
- Note that the 3dB frequency in radians is approx Beta, e.g. for
- Beta = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
- */
-
- if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
- tmp = rx << 15;
+ int32_t echo_value;
+ int clean_bg;
+ int tmp, tmp1;
+
+ /* Input scaling was found be required to prevent problems when tx
+ starts clipping. Another possible way to handle this would be the
+ filter coefficent scaling. */
+
+ ec->tx = tx;
+ ec->rx = rx;
+ tx >>= 1;
+ rx >>= 1;
+
+ /*
+ Filter DC, 3dB point is 160Hz (I think), note 32 bit precision required
+ otherwise values do not track down to 0. Zero at DC, Pole at (1-Beta)
+ only real axis. Some chip sets (like Si labs) don't need
+ this, but something like a $10 X100P card does. Any DC really slows
+ down convergence.
+
+ Note: removes some low frequency from the signal, this reduces
+ the speech quality when listening to samples through headphones
+ but may not be obvious through a telephone handset.
+
+ Note that the 3dB frequency in radians is approx Beta, e.g. for
+ Beta = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
+ */
+
+ if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
+ tmp = rx << 15;
#if 1
- /* Make sure the gain of the HPF is 1.0. This can still saturate a little under
- impulse conditions, and it might roll to 32768 and need clipping on sustained peak
- level signals. However, the scale of such clipping is small, and the error due to
- any saturation should not markedly affect the downstream processing. */
- tmp -= (tmp >> 4);
+ /* Make sure the gain of the HPF is 1.0. This can still saturate a little under
+ impulse conditions, and it might roll to 32768 and need clipping on sustained peak
+ level signals. However, the scale of such clipping is small, and the error due to
+ any saturation should not markedly affect the downstream processing. */
+ tmp -= (tmp >> 4);
#endif
- ec->rx_1 += -(ec->rx_1>>DC_LOG2BETA) + tmp - ec->rx_2;
+ ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
+
+ /* hard limit filter to prevent clipping. Note that at this stage
+ rx should be limited to +/- 16383 due to right shift above */
+ tmp1 = ec->rx_1 >> 15;
+ if (tmp1 > 16383)
+ tmp1 = 16383;
+ if (tmp1 < -16383)
+ tmp1 = -16383;
+ rx = tmp1;
+ ec->rx_2 = tmp;
+ }
- /* hard limit filter to prevent clipping. Note that at this stage
- rx should be limited to +/- 16383 due to right shift above */
- tmp1 = ec->rx_1 >> 15;
- if (tmp1 > 16383) tmp1 = 16383;
- if (tmp1 < -16383) tmp1 = -16383;
- rx = tmp1;
- ec->rx_2 = tmp;
- }
+ /* Block average of power in the filter states. Used for
+ adaption power calculation. */
- /* Block average of power in the filter states. Used for
- adaption power calculation. */
+ {
+ int new, old;
+
+ /* efficient "out with the old and in with the new" algorithm so
+ we don't have to recalculate over the whole block of
+ samples. */
+ new = (int)tx *(int)tx;
+ old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
+ (int)ec->fir_state.history[ec->fir_state.curr_pos];
+ ec->Pstates +=
+ ((new - old) + (1 << ec->log2taps)) >> ec->log2taps;
+ if (ec->Pstates < 0)
+ ec->Pstates = 0;
+ }
- {
- int new, old;
+ /* Calculate short term average levels using simple single pole IIRs */
- /* efficient "out with the old and in with the new" algorithm so
- we don't have to recalculate over the whole block of
- samples. */
- new = (int)tx * (int)tx;
- old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
- (int)ec->fir_state.history[ec->fir_state.curr_pos];
- ec->Pstates += ((new - old) + (1<<ec->log2taps)) >> ec->log2taps;
- if (ec->Pstates < 0) ec->Pstates = 0;
- }
-
- /* Calculate short term average levels using simple single pole IIRs */
-
- ec->Ltxacc += abs(tx) - ec->Ltx;
- ec->Ltx = (ec->Ltxacc + (1<<4)) >> 5;
- ec->Lrxacc += abs(rx) - ec->Lrx;
- ec->Lrx = (ec->Lrxacc + (1<<4)) >> 5;
-
- /* Foreground filter ---------------------------------------------------*/
-
- ec->fir_state.coeffs = ec->fir_taps16[0];
- echo_value = fir16(&ec->fir_state, tx);
- ec->clean = rx - echo_value;
- ec->Lcleanacc += abs(ec->clean) - ec->Lclean;
- ec->Lclean = (ec->Lcleanacc + (1<<4)) >> 5;
-
- /* Background filter ---------------------------------------------------*/
-
- echo_value = fir16(&ec->fir_state_bg, tx);
- clean_bg = rx - echo_value;
- ec->Lclean_bgacc += abs(clean_bg) - ec->Lclean_bg;
- ec->Lclean_bg = (ec->Lclean_bgacc + (1<<4)) >> 5;
-
- /* Background Filter adaption -----------------------------------------*/
-
- /* Almost always adap bg filter, just simple DT and energy
- detection to minimise adaption in cases of strong double talk.
- However this is not critical for the dual path algorithm.
- */
- ec->factor = 0;
- ec->shift = 0;
- if ((ec->nonupdate_dwell == 0)) {
- int P, logP, shift;
-
- /* Determine:
-
- f = Beta * clean_bg_rx/P ------ (1)
-
- where P is the total power in the filter states.
-
- The Boffins have shown that if we obey (1) we converge
- quickly and avoid instability.
-
- The correct factor f must be in Q30, as this is the fixed
- point format required by the lms_adapt_bg() function,
- therefore the scaled version of (1) is:
-
- (2^30) * f = (2^30) * Beta * clean_bg_rx/P
- factor = (2^30) * Beta * clean_bg_rx/P ----- (2)
-
- We have chosen Beta = 0.25 by experiment, so:
-
- factor = (2^30) * (2^-2) * clean_bg_rx/P
-
- (30 - 2 - log2(P))
- factor = clean_bg_rx 2 ----- (3)
-
- To avoid a divide we approximate log2(P) as top_bit(P),
- which returns the position of the highest non-zero bit in
- P. This approximation introduces an error as large as a
- factor of 2, but the algorithm seems to handle it OK.
-
- Come to think of it a divide may not be a big deal on a
- modern DSP, so its probably worth checking out the cycles
- for a divide versus a top_bit() implementation.
- */
-
- P = MIN_TX_POWER_FOR_ADAPTION + ec->Pstates;
- logP = top_bit(P) + ec->log2taps;
- shift = 30 - 2 - logP;
- ec->shift = shift;
-
- lms_adapt_bg(ec, clean_bg, shift);
- }
-
- /* very simple DTD to make sure we dont try and adapt with strong
- near end speech */
-
- ec->adapt = 0;
- if ((ec->Lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->Lrx > ec->Ltx))
- ec->nonupdate_dwell = DTD_HANGOVER;
- if (ec->nonupdate_dwell)
- ec->nonupdate_dwell--;
+ ec->Ltxacc += abs(tx) - ec->Ltx;
+ ec->Ltx = (ec->Ltxacc + (1 << 4)) >> 5;
+ ec->Lrxacc += abs(rx) - ec->Lrx;
+ ec->Lrx = (ec->Lrxacc + (1 << 4)) >> 5;
- /* Transfer logic ------------------------------------------------------*/
+ /* Foreground filter --------------------------------------------------- */
- /* These conditions are from the dual path paper [1], I messed with
- them a bit to improve performance. */
+ ec->fir_state.coeffs = ec->fir_taps16[0];
+ echo_value = fir16(&ec->fir_state, tx);
+ ec->clean = rx - echo_value;
+ ec->Lcleanacc += abs(ec->clean) - ec->Lclean;
+ ec->Lclean = (ec->Lcleanacc + (1 << 4)) >> 5;
- if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
- (ec->nonupdate_dwell == 0) &&
- (8*ec->Lclean_bg < 7*ec->Lclean) /* (ec->Lclean_bg < 0.875*ec->Lclean) */ &&
- (8*ec->Lclean_bg < ec->Ltx) /* (ec->Lclean_bg < 0.125*ec->Ltx) */ )
- {
- if (ec->cond_met == 6) {
- /* BG filter has had better results for 6 consecutive samples */
- ec->adapt = 1;
- memcpy(ec->fir_taps16[0], ec->fir_taps16[1], ec->taps*sizeof(int16_t));
- }
- else
- ec->cond_met++;
- }
- else
- ec->cond_met = 0;
+ /* Background filter --------------------------------------------------- */
- /* Non-Linear Processing ---------------------------------------------------*/
+ echo_value = fir16(&ec->fir_state_bg, tx);
+ clean_bg = rx - echo_value;
+ ec->Lclean_bgacc += abs(clean_bg) - ec->Lclean_bg;
+ ec->Lclean_bg = (ec->Lclean_bgacc + (1 << 4)) >> 5;
- ec->clean_nlp = ec->clean;
- if (ec->adaption_mode & ECHO_CAN_USE_NLP)
- {
- /* Non-linear processor - a fancy way to say "zap small signals, to avoid
- residual echo due to (uLaw/ALaw) non-linearity in the channel.". */
+ /* Background Filter adaption ----------------------------------------- */
- if ((16*ec->Lclean < ec->Ltx))
- {
- /* Our e/c has improved echo by at least 24 dB (each factor of 2 is 6dB,
- so 2*2*2*2=16 is the same as 6+6+6+6=24dB) */
- if (ec->adaption_mode & ECHO_CAN_USE_CNG)
- {
- ec->cng_level = ec->Lbgn;
-
- /* Very elementary comfort noise generation. Just random
- numbers rolled off very vaguely Hoth-like. DR: This
- noise doesn't sound quite right to me - I suspect there
- are some overlfow issues in the filtering as it's too
- "crackly". TODO: debug this, maybe just play noise at
- high level or look at spectrum.
- */
-
- ec->cng_rndnum = 1664525U*ec->cng_rndnum + 1013904223U;
- ec->cng_filter = ((ec->cng_rndnum & 0xFFFF) - 32768 + 5*ec->cng_filter) >> 3;
- ec->clean_nlp = (ec->cng_filter*ec->cng_level*8) >> 14;
-
- }
- else if (ec->adaption_mode & ECHO_CAN_USE_CLIP)
- {
- /* This sounds much better than CNG */
- if (ec->clean_nlp > ec->Lbgn)
- ec->clean_nlp = ec->Lbgn;
- if (ec->clean_nlp < -ec->Lbgn)
- ec->clean_nlp = -ec->Lbgn;
+ /* Almost always adap bg filter, just simple DT and energy
+ detection to minimise adaption in cases of strong double talk.
+ However this is not critical for the dual path algorithm.
+ */
+ ec->factor = 0;
+ ec->shift = 0;
+ if ((ec->nonupdate_dwell == 0)) {
+ int P, logP, shift;
+
+ /* Determine:
+
+ f = Beta * clean_bg_rx/P ------ (1)
+
+ where P is the total power in the filter states.
+
+ The Boffins have shown that if we obey (1) we converge
+ quickly and avoid instability.
+
+ The correct factor f must be in Q30, as this is the fixed
+ point format required by the lms_adapt_bg() function,
+ therefore the scaled version of (1) is:
+
+ (2^30) * f = (2^30) * Beta * clean_bg_rx/P
+ factor = (2^30) * Beta * clean_bg_rx/P ----- (2)
+
+ We have chosen Beta = 0.25 by experiment, so:
+
+ factor = (2^30) * (2^-2) * clean_bg_rx/P
+
+ (30 - 2 - log2(P))
+ factor = clean_bg_rx 2 ----- (3)
+
+ To avoid a divide we approximate log2(P) as top_bit(P),
+ which returns the position of the highest non-zero bit in
+ P. This approximation introduces an error as large as a
+ factor of 2, but the algorithm seems to handle it OK.
+
+ Come to think of it a divide may not be a big deal on a
+ modern DSP, so its probably worth checking out the cycles
+ for a divide versus a top_bit() implementation.
+ */
+
+ P = MIN_TX_POWER_FOR_ADAPTION + ec->Pstates;
+ logP = top_bit(P) + ec->log2taps;
+ shift = 30 - 2 - logP;
+ ec->shift = shift;
+
+ lms_adapt_bg(ec, clean_bg, shift);
}
- else
- {
- /* just mute the residual, doesn't sound very good, used mainly
- in G168 tests */
- ec->clean_nlp = 0;
- }
- }
- else {
- /* Background noise estimator. I tried a few algorithms
- here without much luck. This very simple one seems to
- work best, we just average the level using a slow (1 sec
- time const) filter if the current level is less than a
- (experimentally derived) constant. This means we dont
- include high level signals like near end speech. When
- combined with CNG or especially CLIP seems to work OK.
- */
- if (ec->Lclean < 40) {
- ec->Lbgn_acc += abs(ec->clean) - ec->Lbgn;
- ec->Lbgn = (ec->Lbgn_acc + (1<<11)) >> 12;
- }
- }
- }
-
- /* Roll around the taps buffer */
- if (ec->curr_pos <= 0)
- ec->curr_pos = ec->taps;
- ec->curr_pos--;
-
- if (ec->adaption_mode & ECHO_CAN_DISABLE)
- ec->clean_nlp = rx;
-
- /* Output scaled back up again to match input scaling */
-
- return (int16_t) ec->clean_nlp << 1;
+
+ /* very simple DTD to make sure we dont try and adapt with strong
+ near end speech */
+
+ ec->adapt = 0;
+ if ((ec->Lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->Lrx > ec->Ltx))
+ ec->nonupdate_dwell = DTD_HANGOVER;
+ if (ec->nonupdate_dwell)
+ ec->nonupdate_dwell--;
+
+ /* Transfer logic ------------------------------------------------------ */
+
+ /* These conditions are from the dual path paper [1], I messed with
+ them a bit to improve performance. */
+
+ if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
+ (ec->nonupdate_dwell == 0) &&
+ (8 * ec->Lclean_bg <
+ 7 * ec->Lclean) /* (ec->Lclean_bg < 0.875*ec->Lclean) */ &&
+ (8 * ec->Lclean_bg <
+ ec->Ltx) /* (ec->Lclean_bg < 0.125*ec->Ltx) */ ) {
+ if (ec->cond_met == 6) {
+ /* BG filter has had better results for 6 consecutive samples */
+ ec->adapt = 1;
+ memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
+ ec->taps * sizeof(int16_t));
+ } else
+ ec->cond_met++;
+ } else
+ ec->cond_met = 0;
+
+ /* Non-Linear Processing --------------------------------------------------- */
+
+ ec->clean_nlp = ec->clean;
+ if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
+ /* Non-linear processor - a fancy way to say "zap small signals, to avoid
+ residual echo due to (uLaw/ALaw) non-linearity in the channel.". */
+
+ if ((16 * ec->Lclean < ec->Ltx)) {
+ /* Our e/c has improved echo by at least 24 dB (each factor of 2 is 6dB,
+ so 2*2*2*2=16 is the same as 6+6+6+6=24dB) */
+ if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
+ ec->cng_level = ec->Lbgn;
+
+ /* Very elementary comfort noise generation. Just random
+ numbers rolled off very vaguely Hoth-like. DR: This
+ noise doesn't sound quite right to me - I suspect there
+ are some overlfow issues in the filtering as it's too
+ "crackly". TODO: debug this, maybe just play noise at
+ high level or look at spectrum.
+ */
+
+ ec->cng_rndnum =
+ 1664525U * ec->cng_rndnum + 1013904223U;
+ ec->cng_filter =
+ ((ec->cng_rndnum & 0xFFFF) - 32768 +
+ 5 * ec->cng_filter) >> 3;
+ ec->clean_nlp =
+ (ec->cng_filter * ec->cng_level * 8) >> 14;
+
+ } else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
+ /* This sounds much better than CNG */
+ if (ec->clean_nlp > ec->Lbgn)
+ ec->clean_nlp = ec->Lbgn;
+ if (ec->clean_nlp < -ec->Lbgn)
+ ec->clean_nlp = -ec->Lbgn;
+ } else {
+ /* just mute the residual, doesn't sound very good, used mainly
+ in G168 tests */
+ ec->clean_nlp = 0;
+ }
+ } else {
+ /* Background noise estimator. I tried a few algorithms
+ here without much luck. This very simple one seems to
+ work best, we just average the level using a slow (1 sec
+ time const) filter if the current level is less than a
+ (experimentally derived) constant. This means we dont
+ include high level signals like near end speech. When
+ combined with CNG or especially CLIP seems to work OK.
+ */
+ if (ec->Lclean < 40) {
+ ec->Lbgn_acc += abs(ec->clean) - ec->Lbgn;
+ ec->Lbgn = (ec->Lbgn_acc + (1 << 11)) >> 12;
+ }
+ }
+ }
+
+ /* Roll around the taps buffer */
+ if (ec->curr_pos <= 0)
+ ec->curr_pos = ec->taps;
+ ec->curr_pos--;
+
+ if (ec->adaption_mode & ECHO_CAN_DISABLE)
+ ec->clean_nlp = rx;
+
+ /* Output scaled back up again to match input scaling */
+
+ return (int16_t) ec->clean_nlp << 1;
}
-/*- End of function --------------------------------------------------------*/
+EXPORT_SYMBOL_GPL(oslec_update);
/* This function is seperated from the echo canceller is it is usually called
as part of the tx process. See rx HP (DC blocking) filter above, it's
@@ -608,25 +605,35 @@ int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
precision, which noise shapes things, giving very clean DC removal.
*/
-int16_t echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx) {
- int tmp, tmp1;
+int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx)
+{
+ int tmp, tmp1;
- if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
- tmp = tx << 15;
+ if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
+ tmp = tx << 15;
#if 1
- /* Make sure the gain of the HPF is 1.0. The first can still saturate a little under
- impulse conditions, and it might roll to 32768 and need clipping on sustained peak
- level signals. However, the scale of such clipping is small, and the error due to
- any saturation should not markedly affect the downstream processing. */
- tmp -= (tmp >> 4);
+ /* Make sure the gain of the HPF is 1.0. The first can still saturate a little under
+ impulse conditions, and it might roll to 32768 and need clipping on sustained peak
+ level signals. However, the scale of such clipping is small, and the error due to
+ any saturation should not markedly affect the downstream processing. */
+ tmp -= (tmp >> 4);
#endif
- ec->tx_1 += -(ec->tx_1>>DC_LOG2BETA) + tmp - ec->tx_2;
- tmp1 = ec->tx_1 >> 15;
- if (tmp1 > 32767) tmp1 = 32767;
- if (tmp1 < -32767) tmp1 = -32767;
- tx = tmp1;
- ec->tx_2 = tmp;
- }
-
- return tx;
+ ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
+ tmp1 = ec->tx_1 >> 15;
+ if (tmp1 > 32767)
+ tmp1 = 32767;
+ if (tmp1 < -32767)
+ tmp1 = -32767;
+ tx = tmp1;
+ ec->tx_2 = tmp;
+ }
+
+ return tx;
}
+
+EXPORT_SYMBOL_GPL(oslec_hpf_tx);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Rowe");
+MODULE_DESCRIPTION("Open Source Line Echo Canceller");
+MODULE_VERSION("0.3.0");
diff --git a/drivers/staging/echo/echo.h b/drivers/staging/echo/echo.h
index 7a91b4390f3..9fb9543c4f1 100644
--- a/drivers/staging/echo/echo.h
+++ b/drivers/staging/echo/echo.h
@@ -118,23 +118,14 @@ a minor burden.
*/
#include "fir.h"
-
-/* Mask bits for the adaption mode */
-#define ECHO_CAN_USE_ADAPTION 0x01
-#define ECHO_CAN_USE_NLP 0x02
-#define ECHO_CAN_USE_CNG 0x04
-#define ECHO_CAN_USE_CLIP 0x08
-#define ECHO_CAN_USE_TX_HPF 0x10
-#define ECHO_CAN_USE_RX_HPF 0x20
-#define ECHO_CAN_DISABLE 0x40
+#include "oslec.h"
/*!
G.168 echo canceller descriptor. This defines the working state for a line
echo canceller.
*/
-typedef struct
-{
- int16_t tx,rx;
+struct oslec_state {
+ int16_t tx, rx;
int16_t clean;
int16_t clean_nlp;
@@ -176,45 +167,6 @@ typedef struct
/* snapshot sample of coeffs used for development */
int16_t *snapshot;
-} echo_can_state_t;
-
-/*! Create a voice echo canceller context.
- \param len The length of the canceller, in samples.
- \return The new canceller context, or NULL if the canceller could not be created.
-*/
-echo_can_state_t *echo_can_create(int len, int adaption_mode);
-
-/*! Free a voice echo canceller context.
- \param ec The echo canceller context.
-*/
-void echo_can_free(echo_can_state_t *ec);
-
-/*! Flush (reinitialise) a voice echo canceller context.
- \param ec The echo canceller context.
-*/
-void echo_can_flush(echo_can_state_t *ec);
-
-/*! Set the adaption mode of a voice echo canceller context.
- \param ec The echo canceller context.
- \param adapt The mode.
-*/
-void echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode);
-
-void echo_can_snapshot(echo_can_state_t *ec);
-
-/*! Process a sample through a voice echo canceller.
- \param ec The echo canceller context.
- \param tx The transmitted audio sample.
- \param rx The received audio sample.
- \return The clean (echo cancelled) received sample.
-*/
-int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx);
-
-/*! Process to high pass filter the tx signal.
- \param ec The echo canceller context.
- \param tx The transmitted auio sample.
- \return The HP filtered transmit sample, send this to your D/A.
-*/
-int16_t echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx);
+};
-#endif /* __ECHO_H */
+#endif /* __ECHO_H */
diff --git a/drivers/staging/echo/fir.h b/drivers/staging/echo/fir.h
index e1bfc499488..5645cb1b2f9 100644
--- a/drivers/staging/echo/fir.h
+++ b/drivers/staging/echo/fir.h
@@ -72,8 +72,7 @@
16 bit integer FIR descriptor. This defines the working state for a single
instance of an FIR filter using 16 bit integer coefficients.
*/
-typedef struct
-{
+typedef struct {
int taps;
int curr_pos;
const int16_t *coeffs;
@@ -85,8 +84,7 @@ typedef struct
instance of an FIR filter using 32 bit integer coefficients, and filtering
16 bit integer data.
*/
-typedef struct
-{
+typedef struct {
int taps;
int curr_pos;
const int32_t *coeffs;
@@ -97,273 +95,201 @@ typedef struct
Floating point FIR descriptor. This defines the working state for a single
instance of an FIR filter using floating point coefficients and data.
*/
-typedef struct
-{
+typedef struct {
int taps;
int curr_pos;
const float *coeffs;
float *history;
} fir_float_state_t;
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static __inline__ const int16_t *fir16_create(fir16_state_t *fir,
- const int16_t *coeffs,
- int taps)
+static __inline__ const int16_t *fir16_create(fir16_state_t * fir,
+ const int16_t * coeffs, int taps)
{
fir->taps = taps;
fir->curr_pos = taps - 1;
fir->coeffs = coeffs;
-#if defined(USE_MMX) || defined(USE_SSE2) || defined(__BLACKFIN_ASM__)
- if ((fir->history = malloc(2*taps*sizeof(int16_t))))
- memset(fir->history, 0, 2*taps*sizeof(int16_t));
+#if defined(USE_MMX) || defined(USE_SSE2) || defined(__bfin__)
+ fir->history = kcalloc(2 * taps, sizeof(int16_t), GFP_KERNEL);
#else
- if ((fir->history = (int16_t *) malloc(taps*sizeof(int16_t))))
- memset(fir->history, 0, taps*sizeof(int16_t));
+ fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
#endif
return fir->history;
}
-/*- End of function --------------------------------------------------------*/
-static __inline__ void fir16_flush(fir16_state_t *fir)
+static __inline__ void fir16_flush(fir16_state_t * fir)
{
-#if defined(USE_MMX) || defined(USE_SSE2) || defined(__BLACKFIN_ASM__)
- memset(fir->history, 0, 2*fir->taps*sizeof(int16_t));
+#if defined(USE_MMX) || defined(USE_SSE2) || defined(__bfin__)
+ memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t));
#else
- memset(fir->history, 0, fir->taps*sizeof(int16_t));
+ memset(fir->history, 0, fir->taps * sizeof(int16_t));
#endif
}
-/*- End of function --------------------------------------------------------*/
-static __inline__ void fir16_free(fir16_state_t *fir)
+static __inline__ void fir16_free(fir16_state_t * fir)
{
- free(fir->history);
+ kfree(fir->history);
}
-/*- End of function --------------------------------------------------------*/
-#ifdef __BLACKFIN_ASM__
+#ifdef __bfin__
static inline int32_t dot_asm(short *x, short *y, int len)
{
- int dot;
-
- len--;
-
- __asm__
- (
- "I0 = %1;\n\t"
- "I1 = %2;\n\t"
- "A0 = 0;\n\t"
- "R0.L = W[I0++] || R1.L = W[I1++];\n\t"
- "LOOP dot%= LC0 = %3;\n\t"
- "LOOP_BEGIN dot%=;\n\t"
- "A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t"
- "LOOP_END dot%=;\n\t"
- "A0 += R0.L*R1.L (IS);\n\t"
- "R0 = A0;\n\t"
- "%0 = R0;\n\t"
- : "=&d" (dot)
- : "a" (x), "a" (y), "a" (len)
- : "I0", "I1", "A1", "A0", "R0", "R1"
- );
-
- return dot;
+ int dot;
+
+ len--;
+
+ __asm__("I0 = %1;\n\t"
+ "I1 = %2;\n\t"
+ "A0 = 0;\n\t"
+ "R0.L = W[I0++] || R1.L = W[I1++];\n\t"
+ "LOOP dot%= LC0 = %3;\n\t"
+ "LOOP_BEGIN dot%=;\n\t"
+ "A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t"
+ "LOOP_END dot%=;\n\t"
+ "A0 += R0.L*R1.L (IS);\n\t"
+ "R0 = A0;\n\t"
+ "%0 = R0;\n\t"
+ :"=&d"(dot)
+ :"a"(x), "a"(y), "a"(len)
+ :"I0", "I1", "A1", "A0", "R0", "R1"
+ );
+
+ return dot;
}
#endif
-/*- End of function --------------------------------------------------------*/
-static __inline__ int16_t fir16(fir16_state_t *fir, int16_t sample)
+static __inline__ int16_t fir16(fir16_state_t * fir, int16_t sample)
{
- int32_t y;
+ int32_t y;
#if defined(USE_MMX)
- int i;
- mmx_t *mmx_coeffs;
- mmx_t *mmx_hist;
-
- fir->history[fir->curr_pos] = sample;
- fir->history[fir->curr_pos + fir->taps] = sample;
-
- mmx_coeffs = (mmx_t *) fir->coeffs;
- mmx_hist = (mmx_t *) &fir->history[fir->curr_pos];
- i = fir->taps;
- pxor_r2r(mm4, mm4);
- /* 8 samples per iteration, so the filter must be a multiple of 8 long. */
- while (i > 0)
- {
- movq_m2r(mmx_coeffs[0], mm0);
- movq_m2r(mmx_coeffs[1], mm2);
- movq_m2r(mmx_hist[0], mm1);
- movq_m2r(mmx_hist[1], mm3);
- mmx_coeffs += 2;
- mmx_hist += 2;
- pmaddwd_r2r(mm1, mm0);
- pmaddwd_r2r(mm3, mm2);
- paddd_r2r(mm0, mm4);
- paddd_r2r(mm2, mm4);
- i -= 8;
- }
- movq_r2r(mm4, mm0);
- psrlq_i2r(32, mm0);
- paddd_r2r(mm0, mm4);
- movd_r2m(mm4, y);
- emms();
+ int i;
+ mmx_t *mmx_coeffs;
+ mmx_t *mmx_hist;
+
+ fir->history[fir->curr_pos] = sample;
+ fir->history[fir->curr_pos + fir->taps] = sample;
+
+ mmx_coeffs = (mmx_t *) fir->coeffs;
+ mmx_hist = (mmx_t *) & fir->history[fir->curr_pos];
+ i = fir->taps;
+ pxor_r2r(mm4, mm4);
+ /* 8 samples per iteration, so the filter must be a multiple of 8 long. */
+ while (i > 0) {
+ movq_m2r(mmx_coeffs[0], mm0);
+ movq_m2r(mmx_coeffs[1], mm2);
+ movq_m2r(mmx_hist[0], mm1);
+ movq_m2r(mmx_hist[1], mm3);
+ mmx_coeffs += 2;
+ mmx_hist += 2;
+ pmaddwd_r2r(mm1, mm0);
+ pmaddwd_r2r(mm3, mm2);
+ paddd_r2r(mm0, mm4);
+ paddd_r2r(mm2, mm4);
+ i -= 8;
+ }
+ movq_r2r(mm4, mm0);
+ psrlq_i2r(32, mm0);
+ paddd_r2r(mm0, mm4);
+ movd_r2m(mm4, y);
+ emms();
#elif defined(USE_SSE2)
- int i;
- xmm_t *xmm_coeffs;
- xmm_t *xmm_hist;
-
- fir->history[fir->curr_pos] = sample;
- fir->history[fir->curr_pos + fir->taps] = sample;
-
- xmm_coeffs = (xmm_t *) fir->coeffs;
- xmm_hist = (xmm_t *) &fir->history[fir->curr_pos];
- i = fir->taps;
- pxor_r2r(xmm4, xmm4);
- /* 16 samples per iteration, so the filter must be a multiple of 16 long. */
- while (i > 0)
- {
- movdqu_m2r(xmm_coeffs[0], xmm0);
- movdqu_m2r(xmm_coeffs[1], xmm2);
- movdqu_m2r(xmm_hist[0], xmm1);
- movdqu_m2r(xmm_hist[1], xmm3);
- xmm_coeffs += 2;
- xmm_hist += 2;
- pmaddwd_r2r(xmm1, xmm0);
- pmaddwd_r2r(xmm3, xmm2);
- paddd_r2r(xmm0, xmm4);
- paddd_r2r(xmm2, xmm4);
- i -= 16;
- }
- movdqa_r2r(xmm4, xmm0);
- psrldq_i2r(8, xmm0);
- paddd_r2r(xmm0, xmm4);
- movdqa_r2r(xmm4, xmm0);
- psrldq_i2r(4, xmm0);
- paddd_r2r(xmm0, xmm4);
- movd_r2m(xmm4, y);
-#elif defined(__BLACKFIN_ASM__)
- fir->history[fir->curr_pos] = sample;
- fir->history[fir->curr_pos + fir->taps] = sample;
- y = dot_asm((int16_t*)fir->coeffs, &fir->history[fir->curr_pos], fir->taps);
+ int i;
+ xmm_t *xmm_coeffs;
+ xmm_t *xmm_hist;
+
+ fir->history[fir->curr_pos] = sample;
+ fir->history[fir->curr_pos + fir->taps] = sample;
+
+ xmm_coeffs = (xmm_t *) fir->coeffs;
+ xmm_hist = (xmm_t *) & fir->history[fir->curr_pos];
+ i = fir->taps;
+ pxor_r2r(xmm4, xmm4);
+ /* 16 samples per iteration, so the filter must be a multiple of 16 long. */
+ while (i > 0) {
+ movdqu_m2r(xmm_coeffs[0], xmm0);
+ movdqu_m2r(xmm_coeffs[1], xmm2);
+ movdqu_m2r(xmm_hist[0], xmm1);
+ movdqu_m2r(xmm_hist[1], xmm3);
+ xmm_coeffs += 2;
+ xmm_hist += 2;
+ pmaddwd_r2r(xmm1, xmm0);
+ pmaddwd_r2r(xmm3, xmm2);
+ paddd_r2r(xmm0, xmm4);
+ paddd_r2r(xmm2, xmm4);
+ i -= 16;
+ }
+ movdqa_r2r(xmm4, xmm0);
+ psrldq_i2r(8, xmm0);
+ paddd_r2r(xmm0, xmm4);
+ movdqa_r2r(xmm4, xmm0);
+ psrldq_i2r(4, xmm0);
+ paddd_r2r(xmm0, xmm4);
+ movd_r2m(xmm4, y);
+#elif defined(__bfin__)
+ fir->history[fir->curr_pos] = sample;
+ fir->history[fir->curr_pos + fir->taps] = sample;
+ y = dot_asm((int16_t *) fir->coeffs, &fir->history[fir->curr_pos],
+ fir->taps);
#else
- int i;
- int offset1;
- int offset2;
-
- fir->history[fir->curr_pos] = sample;
-
- offset2 = fir->curr_pos;
- offset1 = fir->taps - offset2;
- y = 0;
- for (i = fir->taps - 1; i >= offset1; i--)
- y += fir->coeffs[i]*fir->history[i - offset1];
- for ( ; i >= 0; i--)
- y += fir->coeffs[i]*fir->history[i + offset2];
+ int i;
+ int offset1;
+ int offset2;
+
+ fir->history[fir->curr_pos] = sample;
+
+ offset2 = fir->curr_pos;
+ offset1 = fir->taps - offset2;
+ y = 0;
+ for (i = fir->taps - 1; i >= offset1; i--)
+ y += fir->coeffs[i] * fir->history[i - offset1];
+ for (; i >= 0; i--)
+ y += fir->coeffs[i] * fir->history[i + offset2];
#endif
- if (fir->curr_pos <= 0)
- fir->curr_pos = fir->taps;
- fir->curr_pos--;
- return (int16_t) (y >> 15);
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ const int16_t *fir32_create(fir32_state_t *fir,
- const int32_t *coeffs,
- int taps)
-{
- fir->taps = taps;
- fir->curr_pos = taps - 1;
- fir->coeffs = coeffs;
- fir->history = (int16_t *) malloc(taps*sizeof(int16_t));
- if (fir->history)
- memset(fir->history, '\0', taps*sizeof(int16_t));
- return fir->history;
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ void fir32_flush(fir32_state_t *fir)
-{
- memset(fir->history, 0, fir->taps*sizeof(int16_t));
+ if (fir->curr_pos <= 0)
+ fir->curr_pos = fir->taps;
+ fir->curr_pos--;
+ return (int16_t) (y >> 15);
}
-/*- End of function --------------------------------------------------------*/
-static __inline__ void fir32_free(fir32_state_t *fir)
+static __inline__ const int16_t *fir32_create(fir32_state_t * fir,
+ const int32_t * coeffs, int taps)
{
- free(fir->history);
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ int16_t fir32(fir32_state_t *fir, int16_t sample)
-{
- int i;
- int32_t y;
- int offset1;
- int offset2;
-
- fir->history[fir->curr_pos] = sample;
- offset2 = fir->curr_pos;
- offset1 = fir->taps - offset2;
- y = 0;
- for (i = fir->taps - 1; i >= offset1; i--)
- y += fir->coeffs[i]*fir->history[i - offset1];
- for ( ; i >= 0; i--)
- y += fir->coeffs[i]*fir->history[i + offset2];
- if (fir->curr_pos <= 0)
- fir->curr_pos = fir->taps;
- fir->curr_pos--;
- return (int16_t) (y >> 15);
+ fir->taps = taps;
+ fir->curr_pos = taps - 1;
+ fir->coeffs = coeffs;
+ fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
+ return fir->history;
}
-/*- End of function --------------------------------------------------------*/
-#ifndef __KERNEL__
-static __inline__ const float *fir_float_create(fir_float_state_t *fir,
- const float *coeffs,
- int taps)
+static __inline__ void fir32_flush(fir32_state_t * fir)
{
- fir->taps = taps;
- fir->curr_pos = taps - 1;
- fir->coeffs = coeffs;
- fir->history = (float *) malloc(taps*sizeof(float));
- if (fir->history)
- memset(fir->history, '\0', taps*sizeof(float));
- return fir->history;
+ memset(fir->history, 0, fir->taps * sizeof(int16_t));
}
-/*- End of function --------------------------------------------------------*/
-static __inline__ void fir_float_free(fir_float_state_t *fir)
+static __inline__ void fir32_free(fir32_state_t * fir)
{
- free(fir->history);
+ kfree(fir->history);
}
-/*- End of function --------------------------------------------------------*/
-static __inline__ int16_t fir_float(fir_float_state_t *fir, int16_t sample)
+static __inline__ int16_t fir32(fir32_state_t * fir, int16_t sample)
{
- int i;
- float y;
- int offset1;
- int offset2;
-
- fir->history[fir->curr_pos] = sample;
-
- offset2 = fir->curr_pos;
- offset1 = fir->taps - offset2;
- y = 0;
- for (i = fir->taps - 1; i >= offset1; i--)
- y += fir->coeffs[i]*fir->history[i - offset1];
- for ( ; i >= 0; i--)
- y += fir->coeffs[i]*fir->history[i + offset2];
- if (fir->curr_pos <= 0)
- fir->curr_pos = fir->taps;
- fir->curr_pos--;
- return (int16_t) y;
+ int i;
+ int32_t y;
+ int offset1;
+ int offset2;
+
+ fir->history[fir->curr_pos] = sample;
+ offset2 = fir->curr_pos;
+ offset1 = fir->taps - offset2;
+ y = 0;
+ for (i = fir->taps - 1; i >= offset1; i--)
+ y += fir->coeffs[i] * fir->history[i - offset1];
+ for (; i >= 0; i--)
+ y += fir->coeffs[i] * fir->history[i + offset2];
+ if (fir->curr_pos <= 0)
+ fir->curr_pos = fir->taps;
+ fir->curr_pos--;
+ return (int16_t) (y >> 15);
}
-/*- End of function --------------------------------------------------------*/
-#endif
-
-#ifdef __cplusplus
-}
-#endif
#endif
/*- End of file ------------------------------------------------------------*/
diff --git a/drivers/staging/echo/mmx.h b/drivers/staging/echo/mmx.h
index b5a3964865b..35412efe61c 100644
--- a/drivers/staging/echo/mmx.h
+++ b/drivers/staging/echo/mmx.h
@@ -27,24 +27,23 @@
* values by ULL, lest they be truncated by the compiler)
*/
-typedef union {
- long long q; /* Quadword (64-bit) value */
- unsigned long long uq; /* Unsigned Quadword */
- int d[2]; /* 2 Doubleword (32-bit) values */
- unsigned int ud[2]; /* 2 Unsigned Doubleword */
- short w[4]; /* 4 Word (16-bit) values */
- unsigned short uw[4]; /* 4 Unsigned Word */
- char b[8]; /* 8 Byte (8-bit) values */
- unsigned char ub[8]; /* 8 Unsigned Byte */
- float s[2]; /* Single-precision (32-bit) value */
-} mmx_t; /* On an 8-byte (64-bit) boundary */
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} mmx_t; /* On an 8-byte (64-bit) boundary */
/* SSE registers */
typedef union {
char b[16];
} xmm_t;
-
#define mmx_i2r(op,imm,reg) \
__asm__ __volatile__ (#op " %0, %%" #reg \
: /* nothing */ \
@@ -63,7 +62,6 @@ typedef union {
#define mmx_r2r(op,regs,regd) \
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
-
#define emms() __asm__ __volatile__ ("emms")
#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
@@ -192,16 +190,13 @@ typedef union {
#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
-
/* 3DNOW extensions */
#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
-
/* AMD MMX extensions - also available in intel SSE */
-
#define mmx_m2ri(op,mem,reg,imm) \
__asm__ __volatile__ (#op " %1, %0, %%" #reg \
: /* nothing */ \
@@ -216,7 +211,6 @@ typedef union {
: /* nothing */ \
: "m" (mem))
-
#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
@@ -284,5 +278,4 @@ typedef union {
#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd)
#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd)
-
#endif /* AVCODEC_I386MMX_H */
diff --git a/drivers/staging/echo/oslec.h b/drivers/staging/echo/oslec.h
new file mode 100644
index 00000000000..bad852328a2
--- /dev/null
+++ b/drivers/staging/echo/oslec.h
@@ -0,0 +1,86 @@
+/*
+ * OSLEC - A line echo canceller. This code is being developed
+ * against and partially complies with G168. Using code from SpanDSP
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ * and David Rowe <david_at_rowetel_dot_com>
+ *
+ * Copyright (C) 2001 Steve Underwood and 2007-2008 David Rowe
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __OSLEC_H
+#define __OSLEC_H
+
+/* TODO: document interface */
+
+/* Mask bits for the adaption mode */
+#define ECHO_CAN_USE_ADAPTION 0x01
+#define ECHO_CAN_USE_NLP 0x02
+#define ECHO_CAN_USE_CNG 0x04
+#define ECHO_CAN_USE_CLIP 0x08
+#define ECHO_CAN_USE_TX_HPF 0x10
+#define ECHO_CAN_USE_RX_HPF 0x20
+#define ECHO_CAN_DISABLE 0x40
+
+/*!
+ G.168 echo canceller descriptor. This defines the working state for a line
+ echo canceller.
+*/
+struct oslec_state;
+
+/*! Create a voice echo canceller context.
+ \param len The length of the canceller, in samples.
+ \return The new canceller context, or NULL if the canceller could not be created.
+*/
+struct oslec_state *oslec_create(int len, int adaption_mode);
+
+/*! Free a voice echo canceller context.
+ \param ec The echo canceller context.
+*/
+void oslec_free(struct oslec_state *ec);
+
+/*! Flush (reinitialise) a voice echo canceller context.
+ \param ec The echo canceller context.
+*/
+void oslec_flush(struct oslec_state *ec);
+
+/*! Set the adaption mode of a voice echo canceller context.
+ \param ec The echo canceller context.
+ \param adapt The mode.
+*/
+void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode);
+
+void oslec_snapshot(struct oslec_state *ec);
+
+/*! Process a sample through a voice echo canceller.
+ \param ec The echo canceller context.
+ \param tx The transmitted audio sample.
+ \param rx The received audio sample.
+ \return The clean (echo cancelled) received sample.
+*/
+int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx);
+
+/*! Process to high pass filter the tx signal.
+ \param ec The echo canceller context.
+ \param tx The transmitted auio sample.
+ \return The HP filtered transmit sample, send this to your D/A.
+*/
+int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx);
+
+#endif /* __OSLEC_H */
diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c
index 6c4fa54419e..9dd6dfd9a03 100644
--- a/drivers/staging/et131x/et1310_phy.c
+++ b/drivers/staging/et131x/et1310_phy.c
@@ -84,7 +84,6 @@
#include <linux/if_arp.h>
#include <linux/ioport.h>
#include <linux/random.h>
-#include <linux/delay.h>
#include "et1310_phy.h"
#include "et1310_pm.h"
@@ -95,7 +94,6 @@
#include "et131x_initpci.h"
#include "et1310_address_map.h"
-#include "et1310_jagcore.h"
#include "et1310_tx.h"
#include "et1310_rx.h"
#include "et1310_mac.h"
diff --git a/drivers/staging/et131x/et131x_debug.c b/drivers/staging/et131x/et131x_debug.c
index 9ee5bce92c2..d1dd46e0a9c 100644
--- a/drivers/staging/et131x/et131x_debug.c
+++ b/drivers/staging/et131x/et131x_debug.c
@@ -97,7 +97,6 @@
#include "et131x_isr.h"
#include "et1310_address_map.h"
-#include "et1310_jagcore.h"
#include "et1310_tx.h"
#include "et1310_rx.h"
#include "et1310_mac.h"
diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c
index 4c6f171f5b7..a18c499d0ae 100644
--- a/drivers/staging/et131x/et131x_initpci.c
+++ b/drivers/staging/et131x/et131x_initpci.c
@@ -97,7 +97,6 @@
#include "et131x_isr.h"
#include "et1310_address_map.h"
-#include "et1310_jagcore.h"
#include "et1310_tx.h"
#include "et1310_rx.h"
#include "et1310_mac.h"
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index 57a121c338c..593fdb767aa 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -1,10 +1,12 @@
config VIDEO_GO7007
tristate "Go 7007 support"
depends on VIDEO_DEV && PCI && I2C && INPUT
+ depends on SND
select VIDEOBUF_DMA_SG
select VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
+ select SND_PCM
select CRC32
default N
---help---
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index 81ae4b0fa89..e4ead96679c 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -16,7 +16,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
diff --git a/drivers/staging/go7007/go7007-fw.c b/drivers/staging/go7007/go7007-fw.c
index c2aea1020b0..a0e17b0e0ce 100644
--- a/drivers/staging/go7007/go7007-fw.c
+++ b/drivers/staging/go7007/go7007-fw.c
@@ -26,7 +26,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/device.h>
diff --git a/drivers/staging/go7007/go7007-i2c.c b/drivers/staging/go7007/go7007-i2c.c
index 10baae3dade..cd55b76eabc 100644
--- a/drivers/staging/go7007/go7007-i2c.c
+++ b/drivers/staging/go7007/go7007-i2c.c
@@ -15,7 +15,6 @@
* Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index d4ed6d2b715..3f5ee3424e7 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -16,7 +16,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/wait.h>
diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c
index 382740c405f..a7de401f61a 100644
--- a/drivers/staging/go7007/snd-go7007.c
+++ b/drivers/staging/go7007/snd-go7007.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/spinlock.h>
diff --git a/drivers/staging/go7007/wis-ov7640.c b/drivers/staging/go7007/wis-ov7640.c
index f5f11e927af..2f9efca0460 100644
--- a/drivers/staging/go7007/wis-ov7640.c
+++ b/drivers/staging/go7007/wis-ov7640.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
index c1aff1b923a..11689723945 100644
--- a/drivers/staging/go7007/wis-saa7113.c
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/ioctl.h>
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
index 5c94c883b31..59417a7174d 100644
--- a/drivers/staging/go7007/wis-saa7115.c
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/ioctl.h>
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index 5997fb47945..5a91ee409a7 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/tuner.h>
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
index 27fe4d0d4ed..57b8f2b1caa 100644
--- a/drivers/staging/go7007/wis-tw2804.c
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/ioctl.h>
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index d8e41968022..40627b282cb 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/ioctl.h>
diff --git a/drivers/staging/go7007/wis-uda1342.c b/drivers/staging/go7007/wis-uda1342.c
index a0894e3cb8c..555645c0cc1 100644
--- a/drivers/staging/go7007/wis-uda1342.c
+++ b/drivers/staging/go7007/wis-uda1342.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/tvaudio.h>
diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c
index 862dd7ffb5c..0b33773bb4f 100644
--- a/drivers/staging/me4000/me4000.c
+++ b/drivers/staging/me4000/me4000.c
@@ -25,24 +25,21 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/delay.h>
-#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/unistd.h>
#include <linux/list.h>
#include <linux/proc_fs.h>
-
+#include <linux/types.h>
#include <linux/poll.h>
#include <linux/vmalloc.h>
+#include <linux/slab.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
-#include <linux/types.h>
-
-#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
/* Include-File for the Meilhaus ME-4000 I/O board */
#include "me4000.h"
@@ -57,14 +54,14 @@ MODULE_SUPPORTED_DEVICE("Meilhaus ME-4000 Multi I/O boards");
MODULE_LICENSE("GPL");
/* Board specific data are kept in a global list */
-LIST_HEAD(me4000_board_info_list);
+static LIST_HEAD(me4000_board_info_list);
/* Major Device Numbers. 0 means to get it automatically from the System */
-static int me4000_ao_major_driver_no = 0;
-static int me4000_ai_major_driver_no = 0;
-static int me4000_dio_major_driver_no = 0;
-static int me4000_cnt_major_driver_no = 0;
-static int me4000_ext_int_major_driver_no = 0;
+static int me4000_ao_major_driver_no;
+static int me4000_ai_major_driver_no;
+static int me4000_dio_major_driver_no;
+static int me4000_cnt_major_driver_no;
+static int me4000_ext_int_major_driver_no;
/* Let the user specify a custom major driver number */
module_param(me4000_ao_major_driver_no, int, 0);
@@ -88,36 +85,22 @@ MODULE_PARM_DESC(me4000_ext_int_major_driver_no,
"Major driver number for external interrupt (default 0)");
/*-----------------------------------------------------------------------------
- Module stuff
- ---------------------------------------------------------------------------*/
-int init_module(void);
-void cleanup_module(void);
-
-/*-----------------------------------------------------------------------------
Board detection and initialization
---------------------------------------------------------------------------*/
static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id);
-static int me4000_xilinx_download(me4000_info_t *);
-static int me4000_reset_board(me4000_info_t *);
+static int me4000_xilinx_download(struct me4000_info *);
+static int me4000_reset_board(struct me4000_info *);
static void clear_board_info_list(void);
-static int get_registers(struct pci_dev *dev, me4000_info_t * info);
-static int init_board_info(struct pci_dev *dev, me4000_info_t * board_info);
-static int alloc_ao_contexts(me4000_info_t * info);
-static void release_ao_contexts(me4000_info_t * board_info);
-static int alloc_ai_context(me4000_info_t * info);
-static int alloc_dio_context(me4000_info_t * info);
-static int alloc_cnt_context(me4000_info_t * info);
-static int alloc_ext_int_context(me4000_info_t * info);
-
+static void release_ao_contexts(struct me4000_info *board_info);
/*-----------------------------------------------------------------------------
Stuff used by all device parts
---------------------------------------------------------------------------*/
static int me4000_open(struct inode *, struct file *);
static int me4000_release(struct inode *, struct file *);
-static int me4000_get_user_info(me4000_user_info_t *,
- me4000_info_t * board_info);
+static int me4000_get_user_info(struct me4000_user_info *,
+ struct me4000_info *board_info);
static int me4000_read_procmem(char *, char **, off_t, int, int *, void *);
/*-----------------------------------------------------------------------------
@@ -140,40 +123,42 @@ static int me4000_ao_ioctl_cont(struct inode *, struct file *, unsigned int,
static unsigned int me4000_ao_poll_cont(struct file *, poll_table *);
static int me4000_ao_fsync_cont(struct file *, struct dentry *, int);
-static int me4000_ao_start(unsigned long *, me4000_ao_context_t *);
-static int me4000_ao_stop(me4000_ao_context_t *);
-static int me4000_ao_immediate_stop(me4000_ao_context_t *);
-static int me4000_ao_timer_set_divisor(u32 *, me4000_ao_context_t *);
-static int me4000_ao_preload(me4000_ao_context_t *);
-static int me4000_ao_preload_update(me4000_ao_context_t *);
-static int me4000_ao_ex_trig_set_edge(int *, me4000_ao_context_t *);
-static int me4000_ao_ex_trig_enable(me4000_ao_context_t *);
-static int me4000_ao_ex_trig_disable(me4000_ao_context_t *);
-static int me4000_ao_prepare(me4000_ao_context_t * ao_info);
-static int me4000_ao_reset(me4000_ao_context_t * ao_info);
-static int me4000_ao_enable_do(me4000_ao_context_t *);
-static int me4000_ao_disable_do(me4000_ao_context_t *);
-static int me4000_ao_fsm_state(int *, me4000_ao_context_t *);
-
-static int me4000_ao_simultaneous_ex_trig(me4000_ao_context_t * ao_context);
-static int me4000_ao_simultaneous_sw(me4000_ao_context_t * ao_context);
-static int me4000_ao_simultaneous_disable(me4000_ao_context_t * ao_context);
-static int me4000_ao_simultaneous_update(me4000_ao_channel_list_t * channels,
- me4000_ao_context_t * ao_context);
-
-static int me4000_ao_synchronous_ex_trig(me4000_ao_context_t * ao_context);
-static int me4000_ao_synchronous_sw(me4000_ao_context_t * ao_context);
-static int me4000_ao_synchronous_disable(me4000_ao_context_t * ao_context);
+static int me4000_ao_start(unsigned long *, struct me4000_ao_context *);
+static int me4000_ao_stop(struct me4000_ao_context *);
+static int me4000_ao_immediate_stop(struct me4000_ao_context *);
+static int me4000_ao_timer_set_divisor(u32 *, struct me4000_ao_context *);
+static int me4000_ao_preload(struct me4000_ao_context *);
+static int me4000_ao_preload_update(struct me4000_ao_context *);
+static int me4000_ao_ex_trig_set_edge(int *, struct me4000_ao_context *);
+static int me4000_ao_ex_trig_enable(struct me4000_ao_context *);
+static int me4000_ao_ex_trig_disable(struct me4000_ao_context *);
+static int me4000_ao_prepare(struct me4000_ao_context *ao_info);
+static int me4000_ao_reset(struct me4000_ao_context *ao_info);
+static int me4000_ao_enable_do(struct me4000_ao_context *);
+static int me4000_ao_disable_do(struct me4000_ao_context *);
+static int me4000_ao_fsm_state(int *, struct me4000_ao_context *);
+
+static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context);
+static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context);
+static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context);
+static int me4000_ao_simultaneous_update(
+ struct me4000_ao_channel_list *channels,
+ struct me4000_ao_context *ao_context);
+
+static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context);
+static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context);
+static int me4000_ao_synchronous_disable(struct me4000_ao_context *ao_context);
static int me4000_ao_ex_trig_timeout(unsigned long *arg,
- me4000_ao_context_t * ao_context);
+ struct me4000_ao_context *ao_context);
static int me4000_ao_get_free_buffer(unsigned long *arg,
- me4000_ao_context_t * ao_context);
+ struct me4000_ao_context *ao_context);
/*-----------------------------------------------------------------------------
Analog input stuff
---------------------------------------------------------------------------*/
-static int me4000_ai_single(me4000_ai_single_t *, me4000_ai_context_t *);
+static int me4000_ai_single(struct me4000_ai_single *,
+ struct me4000_ai_context *);
static int me4000_ai_ioctl_sing(struct inode *, struct file *, unsigned int,
unsigned long);
@@ -186,68 +171,69 @@ static int me4000_ai_fasync(int fd, struct file *file_p, int mode);
static int me4000_ai_ioctl_ext(struct inode *, struct file *, unsigned int,
unsigned long);
-static int me4000_ai_prepare(me4000_ai_context_t * ai_context);
-static int me4000_ai_reset(me4000_ai_context_t * ai_context);
-static int me4000_ai_config(me4000_ai_config_t *, me4000_ai_context_t *);
-static int me4000_ai_start(me4000_ai_context_t *);
-static int me4000_ai_start_ex(unsigned long *, me4000_ai_context_t *);
-static int me4000_ai_stop(me4000_ai_context_t *);
-static int me4000_ai_immediate_stop(me4000_ai_context_t *);
-static int me4000_ai_ex_trig_enable(me4000_ai_context_t *);
-static int me4000_ai_ex_trig_disable(me4000_ai_context_t *);
-static int me4000_ai_ex_trig_setup(me4000_ai_trigger_t *,
- me4000_ai_context_t *);
-static int me4000_ai_sc_setup(me4000_ai_sc_t * arg,
- me4000_ai_context_t * ai_context);
-static int me4000_ai_offset_enable(me4000_ai_context_t * ai_context);
-static int me4000_ai_offset_disable(me4000_ai_context_t * ai_context);
-static int me4000_ai_fullscale_enable(me4000_ai_context_t * ai_context);
-static int me4000_ai_fullscale_disable(me4000_ai_context_t * ai_context);
-static int me4000_ai_fsm_state(int *arg, me4000_ai_context_t * ai_context);
+static int me4000_ai_prepare(struct me4000_ai_context *ai_context);
+static int me4000_ai_reset(struct me4000_ai_context *ai_context);
+static int me4000_ai_config(struct me4000_ai_config *,
+ struct me4000_ai_context *);
+static int me4000_ai_start(struct me4000_ai_context *);
+static int me4000_ai_start_ex(unsigned long *, struct me4000_ai_context *);
+static int me4000_ai_stop(struct me4000_ai_context *);
+static int me4000_ai_immediate_stop(struct me4000_ai_context *);
+static int me4000_ai_ex_trig_enable(struct me4000_ai_context *);
+static int me4000_ai_ex_trig_disable(struct me4000_ai_context *);
+static int me4000_ai_ex_trig_setup(struct me4000_ai_trigger *,
+ struct me4000_ai_context *);
+static int me4000_ai_sc_setup(struct me4000_ai_sc *arg,
+ struct me4000_ai_context *ai_context);
+static int me4000_ai_offset_enable(struct me4000_ai_context *ai_context);
+static int me4000_ai_offset_disable(struct me4000_ai_context *ai_context);
+static int me4000_ai_fullscale_enable(struct me4000_ai_context *ai_context);
+static int me4000_ai_fullscale_disable(struct me4000_ai_context *ai_context);
+static int me4000_ai_fsm_state(int *arg, struct me4000_ai_context *ai_context);
static int me4000_ai_get_count_buffer(unsigned long *arg,
- me4000_ai_context_t * ai_context);
+ struct me4000_ai_context *ai_context);
/*-----------------------------------------------------------------------------
EEPROM stuff
---------------------------------------------------------------------------*/
-static int me4000_eeprom_read(me4000_eeprom_t * arg,
- me4000_ai_context_t * ai_context);
-static int me4000_eeprom_write(me4000_eeprom_t * arg,
- me4000_ai_context_t * ai_context);
-static unsigned short eeprom_read_cmd(me4000_ai_context_t * ai_context,
- unsigned long cmd, int length);
-static int eeprom_write_cmd(me4000_ai_context_t * ai_context, unsigned long cmd,
- int length);
+static int me4000_eeprom_read(struct me4000_eeprom *arg,
+ struct me4000_ai_context *ai_context);
+static int me4000_eeprom_write(struct me4000_eeprom *arg,
+ struct me4000_ai_context *ai_context);
/*-----------------------------------------------------------------------------
Digital I/O stuff
---------------------------------------------------------------------------*/
static int me4000_dio_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
-static int me4000_dio_config(me4000_dio_config_t *, me4000_dio_context_t *);
-static int me4000_dio_get_byte(me4000_dio_byte_t *, me4000_dio_context_t *);
-static int me4000_dio_set_byte(me4000_dio_byte_t *, me4000_dio_context_t *);
-static int me4000_dio_reset(me4000_dio_context_t *);
+static int me4000_dio_config(struct me4000_dio_config *,
+ struct me4000_dio_context *);
+static int me4000_dio_get_byte(struct me4000_dio_byte *,
+ struct me4000_dio_context *);
+static int me4000_dio_set_byte(struct me4000_dio_byte *,
+ struct me4000_dio_context *);
+static int me4000_dio_reset(struct me4000_dio_context *);
/*-----------------------------------------------------------------------------
Counter stuff
---------------------------------------------------------------------------*/
static int me4000_cnt_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
-static int me4000_cnt_config(me4000_cnt_config_t *, me4000_cnt_context_t *);
-static int me4000_cnt_read(me4000_cnt_t *, me4000_cnt_context_t *);
-static int me4000_cnt_write(me4000_cnt_t *, me4000_cnt_context_t *);
-static int me4000_cnt_reset(me4000_cnt_context_t *);
+static int me4000_cnt_config(struct me4000_cnt_config *,
+ struct me4000_cnt_context *);
+static int me4000_cnt_read(struct me4000_cnt *, struct me4000_cnt_context *);
+static int me4000_cnt_write(struct me4000_cnt *, struct me4000_cnt_context *);
+static int me4000_cnt_reset(struct me4000_cnt_context *);
/*-----------------------------------------------------------------------------
External interrupt routines
---------------------------------------------------------------------------*/
static int me4000_ext_int_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
-static int me4000_ext_int_enable(me4000_ext_int_context_t *);
-static int me4000_ext_int_disable(me4000_ext_int_context_t *);
+static int me4000_ext_int_enable(struct me4000_ext_int_context *);
+static int me4000_ext_int_disable(struct me4000_ext_int_context *);
static int me4000_ext_int_count(unsigned long *arg,
- me4000_ext_int_context_t * ext_int_context);
+ struct me4000_ext_int_context *ext_int_context);
static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode);
/*-----------------------------------------------------------------------------
@@ -260,27 +246,18 @@ static irqreturn_t me4000_ext_int_isr(int, void *);
/*-----------------------------------------------------------------------------
Inline functions
---------------------------------------------------------------------------*/
-static int inline me4000_buf_count(me4000_circ_buf_t, int);
-static int inline me4000_buf_space(me4000_circ_buf_t, int);
-static int inline me4000_space_to_end(me4000_circ_buf_t, int);
-static int inline me4000_values_to_end(me4000_circ_buf_t, int);
-
-static void inline me4000_outb(unsigned char value, unsigned long port);
-static void inline me4000_outl(unsigned long value, unsigned long port);
-static unsigned long inline me4000_inl(unsigned long port);
-static unsigned char inline me4000_inb(unsigned long port);
-static int me4000_buf_count(me4000_circ_buf_t buf, int size)
+static int inline me4000_buf_count(struct me4000_circ_buf buf, int size)
{
return ((buf.head - buf.tail) & (size - 1));
}
-static int me4000_buf_space(me4000_circ_buf_t buf, int size)
+static int inline me4000_buf_space(struct me4000_circ_buf buf, int size)
{
return ((buf.tail - (buf.head + 1)) & (size - 1));
}
-static int me4000_values_to_end(me4000_circ_buf_t buf, int size)
+static int inline me4000_values_to_end(struct me4000_circ_buf buf, int size)
{
int end;
int n;
@@ -289,7 +266,7 @@ static int me4000_values_to_end(me4000_circ_buf_t buf, int size)
return (n < end) ? n : end;
}
-static int me4000_space_to_end(me4000_circ_buf_t buf, int size)
+static int inline me4000_space_to_end(struct me4000_circ_buf buf, int size)
{
int end;
int n;
@@ -299,19 +276,19 @@ static int me4000_space_to_end(me4000_circ_buf_t buf, int size)
return (n <= end) ? n : (end + 1);
}
-static void me4000_outb(unsigned char value, unsigned long port)
+static void inline me4000_outb(unsigned char value, unsigned long port)
{
PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
outb(value, port);
}
-static void me4000_outl(unsigned long value, unsigned long port)
+static void inline me4000_outl(unsigned long value, unsigned long port)
{
PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
outl(value, port);
}
-static unsigned long me4000_inl(unsigned long port)
+static unsigned long inline me4000_inl(unsigned long port)
{
unsigned long value;
value = inl(port);
@@ -319,7 +296,7 @@ static unsigned long me4000_inl(unsigned long port)
return value;
}
-static unsigned char me4000_inb(unsigned long port)
+static unsigned char inline me4000_inb(unsigned long port)
{
unsigned char value;
value = inb(port);
@@ -327,102 +304,102 @@ static unsigned char me4000_inb(unsigned long port)
return value;
}
-struct pci_driver me4000_driver = {
+static struct pci_driver me4000_driver = {
.name = ME4000_NAME,
.id_table = me4000_pci_table,
.probe = me4000_probe
};
static struct file_operations me4000_ao_fops_sing = {
- owner:THIS_MODULE,
- write:me4000_ao_write_sing,
- ioctl:me4000_ao_ioctl_sing,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .write = me4000_ao_write_sing,
+ .ioctl = me4000_ao_ioctl_sing,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_ao_fops_wrap = {
- owner:THIS_MODULE,
- write:me4000_ao_write_wrap,
- ioctl:me4000_ao_ioctl_wrap,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .write = me4000_ao_write_wrap,
+ .ioctl = me4000_ao_ioctl_wrap,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_ao_fops_cont = {
- owner:THIS_MODULE,
- write:me4000_ao_write_cont,
- poll:me4000_ao_poll_cont,
- ioctl:me4000_ao_ioctl_cont,
- open:me4000_open,
- release:me4000_release,
- fsync:me4000_ao_fsync_cont,
+ .owner = THIS_MODULE,
+ .write = me4000_ao_write_cont,
+ .poll = me4000_ao_poll_cont,
+ .ioctl = me4000_ao_ioctl_cont,
+ .open = me4000_open,
+ .release = me4000_release,
+ .fsync = me4000_ao_fsync_cont,
};
static struct file_operations me4000_ai_fops_sing = {
- owner:THIS_MODULE,
- ioctl:me4000_ai_ioctl_sing,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .ioctl = me4000_ai_ioctl_sing,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_ai_fops_cont_sw = {
- owner:THIS_MODULE,
- read:me4000_ai_read,
- poll:me4000_ai_poll,
- ioctl:me4000_ai_ioctl_sw,
- open:me4000_open,
- release:me4000_release,
- fasync:me4000_ai_fasync,
+ .owner = THIS_MODULE,
+ .read = me4000_ai_read,
+ .poll = me4000_ai_poll,
+ .ioctl = me4000_ai_ioctl_sw,
+ .open = me4000_open,
+ .release = me4000_release,
+ .fasync = me4000_ai_fasync,
};
static struct file_operations me4000_ai_fops_cont_et = {
- owner:THIS_MODULE,
- read:me4000_ai_read,
- poll:me4000_ai_poll,
- ioctl:me4000_ai_ioctl_ext,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .read = me4000_ai_read,
+ .poll = me4000_ai_poll,
+ .ioctl = me4000_ai_ioctl_ext,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_ai_fops_cont_et_value = {
- owner:THIS_MODULE,
- read:me4000_ai_read,
- poll:me4000_ai_poll,
- ioctl:me4000_ai_ioctl_ext,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .read = me4000_ai_read,
+ .poll = me4000_ai_poll,
+ .ioctl = me4000_ai_ioctl_ext,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_ai_fops_cont_et_chanlist = {
- owner:THIS_MODULE,
- read:me4000_ai_read,
- poll:me4000_ai_poll,
- ioctl:me4000_ai_ioctl_ext,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .read = me4000_ai_read,
+ .poll = me4000_ai_poll,
+ .ioctl = me4000_ai_ioctl_ext,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_dio_fops = {
- owner:THIS_MODULE,
- ioctl:me4000_dio_ioctl,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .ioctl = me4000_dio_ioctl,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_cnt_fops = {
- owner:THIS_MODULE,
- ioctl:me4000_cnt_ioctl,
- open:me4000_open,
- release:me4000_release,
+ .owner = THIS_MODULE,
+ .ioctl = me4000_cnt_ioctl,
+ .open = me4000_open,
+ .release = me4000_release,
};
static struct file_operations me4000_ext_int_fops = {
- owner:THIS_MODULE,
- ioctl:me4000_ext_int_ioctl,
- open:me4000_open,
- release:me4000_release,
- fasync:me4000_ext_int_fasync,
+ .owner = THIS_MODULE,
+ .ioctl = me4000_ext_int_ioctl,
+ .open = me4000_open,
+ .release = me4000_release,
+ .fasync = me4000_ext_int_fasync,
};
static struct file_operations *me4000_ao_fops_array[] = {
@@ -439,9 +416,9 @@ static struct file_operations *me4000_ai_fops_array[] = {
&me4000_ai_fops_cont_et_chanlist, // work through one channel list by external trigger
};
-int __init me4000_init_module(void)
+static int __init me4000_init_module(void)
{
- int result = 0;
+ int result;
CALL_PDEBUG("init_module() is executed\n");
@@ -533,26 +510,26 @@ int __init me4000_init_module(void)
return 0;
- INIT_ERROR_7:
+INIT_ERROR_7:
unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME);
- INIT_ERROR_6:
+INIT_ERROR_6:
unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME);
- INIT_ERROR_5:
+INIT_ERROR_5:
unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME);
- INIT_ERROR_4:
+INIT_ERROR_4:
unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME);
- INIT_ERROR_3:
+INIT_ERROR_3:
unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME);
- INIT_ERROR_2:
+INIT_ERROR_2:
pci_unregister_driver(&me4000_driver);
clear_board_info_list();
- INIT_ERROR_1:
+INIT_ERROR_1:
return result;
}
@@ -562,18 +539,18 @@ static void clear_board_info_list(void)
{
struct list_head *board_p;
struct list_head *dac_p;
- me4000_info_t *board_info;
- me4000_ao_context_t *ao_context;
+ struct me4000_info *board_info;
+ struct me4000_ao_context *ao_context;
/* Clear context lists */
for (board_p = me4000_board_info_list.next;
board_p != &me4000_board_info_list; board_p = board_p->next) {
- board_info = list_entry(board_p, me4000_info_t, list);
+ board_info = list_entry(board_p, struct me4000_info, list);
/* Clear analog output context list */
while (!list_empty(&board_info->ao_context_list)) {
dac_p = board_info->ao_context_list.next;
ao_context =
- list_entry(dac_p, me4000_ao_context_t, list);
+ list_entry(dac_p, struct me4000_ao_context, list);
me4000_ao_reset(ao_context);
free_irq(ao_context->irq, ao_context);
if (ao_context->circ_buf.buf)
@@ -600,14 +577,14 @@ static void clear_board_info_list(void)
/* Clear the board info list */
while (!list_empty(&me4000_board_info_list)) {
board_p = me4000_board_info_list.next;
- board_info = list_entry(board_p, me4000_info_t, list);
+ board_info = list_entry(board_p, struct me4000_info, list);
pci_release_regions(board_info->pci_dev_p);
list_del(board_p);
kfree(board_info);
}
}
-static int get_registers(struct pci_dev *dev, me4000_info_t * board_info)
+static int get_registers(struct pci_dev *dev, struct me4000_info *board_info)
{
/*--------------------------- plx regbase ---------------------------------*/
@@ -667,20 +644,20 @@ static int get_registers(struct pci_dev *dev, me4000_info_t * board_info)
}
static int init_board_info(struct pci_dev *pci_dev_p,
- me4000_info_t * board_info)
+ struct me4000_info *board_info)
{
int i;
int result;
struct list_head *board_p;
board_info->pci_dev_p = pci_dev_p;
- for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
+ for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
if (me4000_boards[i].device_id == pci_dev_p->device) {
board_info->board_p = &me4000_boards[i];
break;
}
}
- if (i == ME4000_BOARD_VERSIONS) {
+ if (i == ARRAY_SIZE(me4000_boards)) {
printk(KERN_ERR
"ME4000:init_board_info():Device ID not valid\n");
return -ENODEV;
@@ -755,21 +732,21 @@ static int init_board_info(struct pci_dev *pci_dev_p,
return 0;
}
-static int alloc_ao_contexts(me4000_info_t * info)
+static int alloc_ao_contexts(struct me4000_info *info)
{
int i;
int err;
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
for (i = 0; i < info->board_p->ao.count; i++) {
- ao_context = kmalloc(sizeof(me4000_ao_context_t), GFP_KERNEL);
+ ao_context = kzalloc(sizeof(struct me4000_ao_context),
+ GFP_KERNEL);
if (!ao_context) {
printk(KERN_ERR
"alloc_ao_contexts():Can't get memory for ao context\n");
release_ao_contexts(info);
return -ENOMEM;
}
- memset(ao_context, 0, sizeof(me4000_ao_context_t));
spin_lock_init(&ao_context->use_lock);
spin_lock_init(&ao_context->int_lock);
@@ -780,15 +757,13 @@ static int alloc_ao_contexts(me4000_info_t * info)
if (info->board_p->ao.fifo_count) {
/* Allocate circular buffer */
ao_context->circ_buf.buf =
- kmalloc(ME4000_AO_BUFFER_SIZE, GFP_KERNEL);
+ kzalloc(ME4000_AO_BUFFER_SIZE, GFP_KERNEL);
if (!ao_context->circ_buf.buf) {
printk(KERN_ERR
"alloc_ao_contexts():Can't get circular buffer\n");
release_ao_contexts(info);
return -ENOMEM;
}
- memset(ao_context->circ_buf.buf, 0,
- ME4000_AO_BUFFER_SIZE);
/* Clear the circular buffer */
ao_context->circ_buf.head = 0;
@@ -872,9 +847,8 @@ static int alloc_ao_contexts(me4000_info_t * info)
ME4000_NAME, ao_context);
if (err) {
printk(KERN_ERR
- "alloc_ao_contexts():Can't get interrupt line");
- if (ao_context->circ_buf.buf)
- kfree(ao_context->circ_buf.buf);
+ "%s:Can't get interrupt line", __func__);
+ kfree(ao_context->circ_buf.buf);
kfree(ao_context);
release_ao_contexts(info);
return -ENODEV;
@@ -888,35 +862,34 @@ static int alloc_ao_contexts(me4000_info_t * info)
return 0;
}
-static void release_ao_contexts(me4000_info_t * board_info)
+static void release_ao_contexts(struct me4000_info *board_info)
{
struct list_head *dac_p;
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
/* Clear analog output context list */
while (!list_empty(&board_info->ao_context_list)) {
dac_p = board_info->ao_context_list.next;
- ao_context = list_entry(dac_p, me4000_ao_context_t, list);
+ ao_context = list_entry(dac_p, struct me4000_ao_context, list);
free_irq(ao_context->irq, ao_context);
- if (ao_context->circ_buf.buf)
- kfree(ao_context->circ_buf.buf);
+ kfree(ao_context->circ_buf.buf);
list_del(dac_p);
kfree(ao_context);
}
}
-static int alloc_ai_context(me4000_info_t * info)
+static int alloc_ai_context(struct me4000_info *info)
{
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
if (info->board_p->ai.count) {
- ai_context = kmalloc(sizeof(me4000_ai_context_t), GFP_KERNEL);
+ ai_context = kzalloc(sizeof(struct me4000_ai_context),
+ GFP_KERNEL);
if (!ai_context) {
printk(KERN_ERR
"ME4000:alloc_ai_context():Can't get memory for ai context\n");
return -ENOMEM;
}
- memset(ai_context, 0, sizeof(me4000_ai_context_t));
info->ai_context = ai_context;
@@ -958,18 +931,18 @@ static int alloc_ai_context(me4000_info_t * info)
return 0;
}
-static int alloc_dio_context(me4000_info_t * info)
+static int alloc_dio_context(struct me4000_info *info)
{
- me4000_dio_context_t *dio_context;
+ struct me4000_dio_context *dio_context;
if (info->board_p->dio.count) {
- dio_context = kmalloc(sizeof(me4000_dio_context_t), GFP_KERNEL);
+ dio_context = kzalloc(sizeof(struct me4000_dio_context),
+ GFP_KERNEL);
if (!dio_context) {
printk(KERN_ERR
"ME4000:alloc_dio_context():Can't get memory for dio context\n");
return -ENOMEM;
}
- memset(dio_context, 0, sizeof(me4000_dio_context_t));
info->dio_context = dio_context;
@@ -995,18 +968,18 @@ static int alloc_dio_context(me4000_info_t * info)
return 0;
}
-static int alloc_cnt_context(me4000_info_t * info)
+static int alloc_cnt_context(struct me4000_info *info)
{
- me4000_cnt_context_t *cnt_context;
+ struct me4000_cnt_context *cnt_context;
if (info->board_p->cnt.count) {
- cnt_context = kmalloc(sizeof(me4000_cnt_context_t), GFP_KERNEL);
+ cnt_context = kzalloc(sizeof(struct me4000_cnt_context),
+ GFP_KERNEL);
if (!cnt_context) {
printk(KERN_ERR
"ME4000:alloc_cnt_context():Can't get memory for cnt context\n");
return -ENOMEM;
}
- memset(cnt_context, 0, sizeof(me4000_cnt_context_t));
info->cnt_context = cnt_context;
@@ -1026,19 +999,18 @@ static int alloc_cnt_context(me4000_info_t * info)
return 0;
}
-static int alloc_ext_int_context(me4000_info_t * info)
+static int alloc_ext_int_context(struct me4000_info *info)
{
- me4000_ext_int_context_t *ext_int_context;
+ struct me4000_ext_int_context *ext_int_context;
if (info->board_p->cnt.count) {
ext_int_context =
- kmalloc(sizeof(me4000_ext_int_context_t), GFP_KERNEL);
+ kzalloc(sizeof(struct me4000_ext_int_context), GFP_KERNEL);
if (!ext_int_context) {
printk(KERN_ERR
"ME4000:alloc_ext_int_context():Can't get memory for cnt context\n");
return -ENOMEM;
}
- memset(ext_int_context, 0, sizeof(me4000_ext_int_context_t));
info->ext_int_context = ext_int_context;
@@ -1060,19 +1032,18 @@ static int alloc_ext_int_context(me4000_info_t * info)
static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int result = 0;
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
CALL_PDEBUG("me4000_probe() is executed\n");
/* Allocate structure for board context */
- board_info = kmalloc(sizeof(me4000_info_t), GFP_KERNEL);
+ board_info = kzalloc(sizeof(struct me4000_info), GFP_KERNEL);
if (!board_info) {
printk(KERN_ERR
"ME4000:Can't get memory for board info structure\n");
result = -ENOMEM;
goto PROBE_ERROR_1;
}
- memset(board_info, 0, sizeof(me4000_info_t));
/* Add to global linked list */
list_add_tail(&board_info->list, &me4000_board_info_list);
@@ -1080,70 +1051,70 @@ static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* Get the PCI base registers */
result = get_registers(dev, board_info);
if (result) {
- printk(KERN_ERR "me4000_probe():Cannot get registers\n");
+ printk(KERN_ERR "%s:Cannot get registers\n", __func__);
goto PROBE_ERROR_2;
}
/* Enable the device */
result = pci_enable_device(dev);
if (result < 0) {
- printk(KERN_ERR "me4000_probe():Cannot enable PCI device\n");
+ printk(KERN_ERR "%s:Cannot enable PCI device\n", __func__);
goto PROBE_ERROR_2;
}
/* Request the PCI register regions */
result = pci_request_regions(dev, ME4000_NAME);
if (result < 0) {
- printk(KERN_ERR "me4000_probe():Cannot request I/O regions\n");
+ printk(KERN_ERR "%s:Cannot request I/O regions\n", __func__);
goto PROBE_ERROR_2;
}
/* Initialize board info */
result = init_board_info(dev, board_info);
if (result) {
- printk(KERN_ERR "me4000_probe():Cannot init baord info\n");
+ printk(KERN_ERR "%s:Cannot init baord info\n", __func__);
goto PROBE_ERROR_3;
}
/* Download the xilinx firmware */
result = me4000_xilinx_download(board_info);
if (result) {
- printk(KERN_ERR "me4000_probe:Can't download firmware\n");
+ printk(KERN_ERR "%s:Can't download firmware\n", __func__);
goto PROBE_ERROR_3;
}
/* Make a hardware reset */
result = me4000_reset_board(board_info);
if (result) {
- printk(KERN_ERR "me4000_probe:Can't reset board\n");
+ printk(KERN_ERR "%s :Can't reset board\n", __func__);
goto PROBE_ERROR_3;
}
/* Allocate analog output context structures */
result = alloc_ao_contexts(board_info);
if (result) {
- printk(KERN_ERR "me4000_probe():Cannot allocate ao contexts\n");
+ printk(KERN_ERR "%s:Cannot allocate ao contexts\n", __func__);
goto PROBE_ERROR_3;
}
/* Allocate analog input context */
result = alloc_ai_context(board_info);
if (result) {
- printk(KERN_ERR "me4000_probe():Cannot allocate ai context\n");
+ printk(KERN_ERR "%s:Cannot allocate ai context\n", __func__);
goto PROBE_ERROR_4;
}
/* Allocate digital I/O context */
result = alloc_dio_context(board_info);
if (result) {
- printk(KERN_ERR "me4000_probe():Cannot allocate dio context\n");
+ printk(KERN_ERR "%s:Cannot allocate dio context\n", __func__);
goto PROBE_ERROR_5;
}
/* Allocate counter context */
result = alloc_cnt_context(board_info);
if (result) {
- printk(KERN_ERR "me4000_probe():Cannot allocate cnt context\n");
+ printk(KERN_ERR "%s:Cannot allocate cnt context\n", __func__);
goto PROBE_ERROR_6;
}
@@ -1151,36 +1122,36 @@ static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id)
result = alloc_ext_int_context(board_info);
if (result) {
printk(KERN_ERR
- "me4000_probe():Cannot allocate ext_int context\n");
+ "%s:Cannot allocate ext_int context\n", __func__);
goto PROBE_ERROR_7;
}
return 0;
- PROBE_ERROR_7:
+PROBE_ERROR_7:
kfree(board_info->cnt_context);
- PROBE_ERROR_6:
+PROBE_ERROR_6:
kfree(board_info->dio_context);
- PROBE_ERROR_5:
+PROBE_ERROR_5:
kfree(board_info->ai_context);
- PROBE_ERROR_4:
+PROBE_ERROR_4:
release_ao_contexts(board_info);
- PROBE_ERROR_3:
+PROBE_ERROR_3:
pci_release_regions(dev);
- PROBE_ERROR_2:
+PROBE_ERROR_2:
list_del(&board_info->list);
kfree(board_info);
- PROBE_ERROR_1:
+PROBE_ERROR_1:
return result;
}
-static int me4000_xilinx_download(me4000_info_t * info)
+static int me4000_xilinx_download(struct me4000_info *info)
{
int size = 0;
u32 value = 0;
@@ -1211,7 +1182,7 @@ static int me4000_xilinx_download(me4000_info_t * info)
/* Wait until /INIT pin is set */
udelay(20);
if (!inl(info->plx_regbase + PLX_INTCSR) & 0x20) {
- printk(KERN_ERR "me4000_xilinx_download():Can't init Xilinx\n");
+ printk(KERN_ERR "%s:Can't init Xilinx\n", __func__);
return -EIO;
}
@@ -1232,7 +1203,7 @@ static int me4000_xilinx_download(me4000_info_t * info)
/* Check if BUSY flag is low */
if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
printk(KERN_ERR
- "me4000_xilinx_download():Xilinx is still busy (idx = %d)\n",
+ "%s:Xilinx is still busy (idx = %d)\n", __func__,
idx);
return -EIO;
}
@@ -1246,9 +1217,9 @@ static int me4000_xilinx_download(me4000_info_t * info)
PDEBUG("me4000_xilinx_download():Download was successful\n");
} else {
printk(KERN_ERR
- "ME4000:me4000_xilinx_download():DONE flag is not set\n");
+ "ME4000:%s:DONE flag is not set\n", __func__);
printk(KERN_ERR
- "ME4000:me4000_xilinx_download():Download not succesful\n");
+ "ME4000:%s:Download not succesful\n", __func__);
return -EIO;
}
@@ -1260,7 +1231,7 @@ static int me4000_xilinx_download(me4000_info_t * info)
return 0;
}
-static int me4000_reset_board(me4000_info_t * info)
+static int me4000_reset_board(struct me4000_info *info)
{
unsigned long icr;
@@ -1314,12 +1285,12 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
int err = 0;
int i;
struct list_head *ptr;
- me4000_info_t *board_info = NULL;
- me4000_ao_context_t *ao_context = NULL;
- me4000_ai_context_t *ai_context = NULL;
- me4000_dio_context_t *dio_context = NULL;
- me4000_cnt_context_t *cnt_context = NULL;
- me4000_ext_int_context_t *ext_int_context = NULL;
+ struct me4000_info *board_info = NULL;
+ struct me4000_ao_context *ao_context = NULL;
+ struct me4000_ai_context *ai_context = NULL;
+ struct me4000_dio_context *dio_context = NULL;
+ struct me4000_cnt_context *cnt_context = NULL;
+ struct me4000_ext_int_context *ext_int_context = NULL;
CALL_PDEBUG("me4000_open() is executed\n");
@@ -1335,7 +1306,7 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
/* Search for the board context */
for (ptr = me4000_board_info_list.next, i = 0;
ptr != &me4000_board_info_list; ptr = ptr->next, i++) {
- board_info = list_entry(ptr, me4000_info_t, list);
+ board_info = list_entry(ptr, struct me4000_info, list);
if (i == board)
break;
}
@@ -1351,7 +1322,8 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
for (ptr = board_info->ao_context_list.next, i = 0;
ptr != &board_info->ao_context_list;
ptr = ptr->next, i++) {
- ao_context = list_entry(ptr, me4000_ao_context_t, list);
+ ao_context = list_entry(ptr, struct me4000_ao_context,
+ list);
if (i == dev)
break;
}
@@ -1415,7 +1387,7 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
/* Search for the board context */
for (ptr = me4000_board_info_list.next, i = 0;
ptr != &me4000_board_info_list; ptr = ptr->next, i++) {
- board_info = list_entry(ptr, me4000_info_t, list);
+ board_info = list_entry(ptr, struct me4000_info, list);
if (i == board)
break;
}
@@ -1469,7 +1441,7 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
/* Search for the board context */
for (ptr = me4000_board_info_list.next;
ptr != &me4000_board_info_list; ptr = ptr->next) {
- board_info = list_entry(ptr, me4000_info_t, list);
+ board_info = list_entry(ptr, struct me4000_info, list);
if (board_info->board_count == board)
break;
}
@@ -1514,7 +1486,7 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
/* Search for the board context */
for (ptr = me4000_board_info_list.next;
ptr != &me4000_board_info_list; ptr = ptr->next) {
- board_info = list_entry(ptr, me4000_info_t, list);
+ board_info = list_entry(ptr, struct me4000_info, list);
if (board_info->board_count == board)
break;
}
@@ -1557,7 +1529,7 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
/* Search for the board context */
for (ptr = me4000_board_info_list.next;
ptr != &me4000_board_info_list; ptr = ptr->next) {
- board_info = list_entry(ptr, me4000_info_t, list);
+ board_info = list_entry(ptr, struct me4000_info, list);
if (board_info->board_count == board)
break;
}
@@ -1613,11 +1585,11 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
static int me4000_release(struct inode *inode_p, struct file *file_p)
{
- me4000_ao_context_t *ao_context;
- me4000_ai_context_t *ai_context;
- me4000_dio_context_t *dio_context;
- me4000_cnt_context_t *cnt_context;
- me4000_ext_int_context_t *ext_int_context;
+ struct me4000_ao_context *ao_context;
+ struct me4000_ai_context *ai_context;
+ struct me4000_dio_context *dio_context;
+ struct me4000_cnt_context *cnt_context;
+ struct me4000_ext_int_context *ext_int_context;
CALL_PDEBUG("me4000_release() is executed\n");
@@ -1677,7 +1649,7 @@ static int me4000_release(struct inode *inode_p, struct file *file_p)
/*------------------------------- Analog output stuff --------------------------------------*/
-static int me4000_ao_prepare(me4000_ao_context_t * ao_context)
+static int me4000_ao_prepare(struct me4000_ao_context *ao_context)
{
unsigned long flags;
@@ -1756,7 +1728,7 @@ static int me4000_ao_prepare(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_reset(me4000_ao_context_t * ao_context)
+static int me4000_ao_reset(struct me4000_ao_context *ao_context)
{
u32 tmp;
wait_queue_head_t queue;
@@ -1777,9 +1749,10 @@ static int me4000_ao_reset(me4000_ao_context_t * ao_context)
tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
me4000_outl(tmp, ao_context->ctrl_reg);
- while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
- sleep_on_timeout(&queue, 1);
- }
+ wait_event_timeout(queue,
+ (inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM) == 0,
+ 1);
/* Set to transparent mode */
me4000_ao_simultaneous_disable(ao_context);
@@ -1812,9 +1785,10 @@ static int me4000_ao_reset(me4000_ao_context_t * ao_context)
me4000_outl(tmp, ao_context->ctrl_reg);
spin_unlock_irqrestore(&ao_context->int_lock, flags);
- while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
- sleep_on_timeout(&queue, 1);
- }
+ wait_event_timeout(queue,
+ (inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM) == 0,
+ 1);
/* Clear the circular buffer */
ao_context->circ_buf.head = 0;
@@ -1853,9 +1827,9 @@ static int me4000_ao_reset(me4000_ao_context_t * ao_context)
}
static ssize_t me4000_ao_write_sing(struct file *filep, const char *buff,
- size_t cnt, loff_t * offp)
+ size_t cnt, loff_t *offp)
{
- me4000_ao_context_t *ao_context = filep->private_data;
+ struct me4000_ao_context *ao_context = filep->private_data;
u32 value;
const u16 *buffer = (const u16 *)buff;
@@ -1863,13 +1837,13 @@ static ssize_t me4000_ao_write_sing(struct file *filep, const char *buff,
if (cnt != 2) {
printk(KERN_ERR
- "me4000_ao_write_sing():Write count is not 2\n");
+ "%s:Write count is not 2\n", __func__);
return -EINVAL;
}
if (get_user(value, buffer)) {
printk(KERN_ERR
- "me4000_ao_write_sing():Cannot copy data from user\n");
+ "%s:Cannot copy data from user\n", __func__);
return -EFAULT;
}
@@ -1879,9 +1853,9 @@ static ssize_t me4000_ao_write_sing(struct file *filep, const char *buff,
}
static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff,
- size_t cnt, loff_t * offp)
+ size_t cnt, loff_t *offp)
{
- me4000_ao_context_t *ao_context = filep->private_data;
+ struct me4000_ao_context *ao_context = filep->private_data;
size_t i;
u32 value;
u32 tmp;
@@ -1893,13 +1867,13 @@ static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff,
/* Check if a conversion is already running */
if (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
printk(KERN_ERR
- "ME4000:me4000_ao_write_wrap():There is already a conversion running\n");
+ "%s:There is already a conversion running\n", __func__);
return -EBUSY;
}
if (count > ME4000_AO_FIFO_COUNT) {
printk(KERN_ERR
- "me4000_ao_write_wrap():Can't load more than %d values\n",
+ "%s:Can't load more than %d values\n", __func__,
ME4000_AO_FIFO_COUNT);
return -ENOSPC;
}
@@ -1914,7 +1888,7 @@ static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff,
for (i = 0; i < count; i++) {
if (get_user(value, buffer + i)) {
printk(KERN_ERR
- "me4000_ao_write_single():Cannot copy data from user\n");
+ "%s:Cannot copy data from user\n", __func__);
return -EFAULT;
}
if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG)
@@ -1928,9 +1902,9 @@ static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff,
}
static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff,
- size_t cnt, loff_t * offp)
+ size_t cnt, loff_t *offp)
{
- me4000_ao_context_t *ao_context = filep->private_data;
+ struct me4000_ao_context *ao_context = filep->private_data;
const u16 *buffer = (const u16 *)buff;
size_t count = cnt / 2;
unsigned long flags;
@@ -2154,9 +2128,9 @@ static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff,
return 2 * ret;
}
-static unsigned int me4000_ao_poll_cont(struct file *file_p, poll_table * wait)
+static unsigned int me4000_ao_poll_cont(struct file *file_p, poll_table *wait)
{
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
unsigned long mask = 0;
CALL_PDEBUG("me4000_ao_poll_cont() is executed\n");
@@ -2177,7 +2151,7 @@ static unsigned int me4000_ao_poll_cont(struct file *file_p, poll_table * wait)
static int me4000_ao_fsync_cont(struct file *file_p, struct dentry *dentry_p,
int datasync)
{
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
wait_queue_head_t queue;
CALL_PDEBUG("me4000_ao_fsync_cont() is executed\n");
@@ -2187,15 +2161,19 @@ static int me4000_ao_fsync_cont(struct file *file_p, struct dentry *dentry_p,
while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
interruptible_sleep_on_timeout(&queue, 1);
+ wait_event_interruptible_timeout(queue,
+ !(inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM),
+ 1);
if (ao_context->pipe_flag) {
printk(KERN_ERR
- "me4000_ao_fsync_cont():Broken pipe detected\n");
+ "%s:Broken pipe detected\n", __func__);
return -EPIPE;
}
if (signal_pending(current)) {
printk(KERN_ERR
- "me4000_ao_fsync_cont():Wait on state machine interrupted\n");
+ "%s:Wait on state machine interrupted\n",
+ __func__);
return -EINTR;
}
}
@@ -2206,7 +2184,7 @@ static int me4000_ao_fsync_cont(struct file *file_p, struct dentry *dentry_p,
static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
CALL_PDEBUG("me4000_ao_ioctl_sing() is executed\n");
@@ -2229,7 +2207,7 @@ static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p,
case ME4000_AO_PRELOAD_UPDATE:
return me4000_ao_preload_update(ao_context);
case ME4000_GET_USER_INFO:
- return me4000_get_user_info((me4000_user_info_t *) arg,
+ return me4000_get_user_info((struct me4000_user_info *)arg,
ao_context->board_info);
case ME4000_AO_SIMULTANEOUS_EX_TRIG:
return me4000_ao_simultaneous_ex_trig(ao_context);
@@ -2239,8 +2217,9 @@ static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p,
return me4000_ao_simultaneous_disable(ao_context);
case ME4000_AO_SIMULTANEOUS_UPDATE:
return
- me4000_ao_simultaneous_update((me4000_ao_channel_list_t *)
- arg, ao_context);
+ me4000_ao_simultaneous_update(
+ (struct me4000_ao_channel_list *)arg,
+ ao_context);
case ME4000_AO_EX_TRIG_TIMEOUT:
return me4000_ao_ex_trig_timeout((unsigned long *)arg,
ao_context);
@@ -2258,7 +2237,7 @@ static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p,
static int me4000_ao_ioctl_wrap(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
CALL_PDEBUG("me4000_ao_ioctl_wrap() is executed\n");
@@ -2287,7 +2266,7 @@ static int me4000_ao_ioctl_wrap(struct inode *inode_p, struct file *file_p,
case ME4000_AO_EX_TRIG_DISABLE:
return me4000_ao_ex_trig_disable(ao_context);
case ME4000_GET_USER_INFO:
- return me4000_get_user_info((me4000_user_info_t *) arg,
+ return me4000_get_user_info((struct me4000_user_info *)arg,
ao_context->board_info);
case ME4000_AO_FSM_STATE:
return me4000_ao_fsm_state((int *)arg, ao_context);
@@ -2310,7 +2289,7 @@ static int me4000_ao_ioctl_wrap(struct inode *inode_p, struct file *file_p,
static int me4000_ao_ioctl_cont(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
CALL_PDEBUG("me4000_ao_ioctl_cont() is executed\n");
@@ -2345,7 +2324,7 @@ static int me4000_ao_ioctl_cont(struct inode *inode_p, struct file *file_p,
case ME4000_AO_FSM_STATE:
return me4000_ao_fsm_state((int *)arg, ao_context);
case ME4000_GET_USER_INFO:
- return me4000_get_user_info((me4000_user_info_t *) arg,
+ return me4000_get_user_info((struct me4000_user_info *)arg,
ao_context->board_info);
case ME4000_AO_SYNCHRONOUS_EX_TRIG:
return me4000_ao_synchronous_ex_trig(ao_context);
@@ -2362,7 +2341,8 @@ static int me4000_ao_ioctl_cont(struct inode *inode_p, struct file *file_p,
return 0;
}
-static int me4000_ao_start(unsigned long *arg, me4000_ao_context_t * ao_context)
+static int me4000_ao_start(unsigned long *arg,
+ struct me4000_ao_context *ao_context)
{
u32 tmp;
wait_queue_head_t queue;
@@ -2412,7 +2392,7 @@ static int me4000_ao_start(unsigned long *arg, me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_stop(me4000_ao_context_t * ao_context)
+static int me4000_ao_stop(struct me4000_ao_context *ao_context)
{
u32 tmp;
wait_queue_head_t queue;
@@ -2445,7 +2425,7 @@ static int me4000_ao_stop(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_immediate_stop(me4000_ao_context_t * ao_context)
+static int me4000_ao_immediate_stop(struct me4000_ao_context *ao_context)
{
u32 tmp;
wait_queue_head_t queue;
@@ -2477,8 +2457,8 @@ static int me4000_ao_immediate_stop(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_timer_set_divisor(u32 * arg,
- me4000_ao_context_t * ao_context)
+static int me4000_ao_timer_set_divisor(u32 *arg,
+ struct me4000_ao_context *ao_context)
{
u32 divisor;
u32 tmp;
@@ -2518,7 +2498,7 @@ static int me4000_ao_timer_set_divisor(u32 * arg,
}
static int me4000_ao_ex_trig_set_edge(int *arg,
- me4000_ao_context_t * ao_context)
+ struct me4000_ao_context *ao_context)
{
int mode;
u32 tmp;
@@ -2569,7 +2549,7 @@ static int me4000_ao_ex_trig_set_edge(int *arg,
return 0;
}
-static int me4000_ao_ex_trig_enable(me4000_ao_context_t * ao_context)
+static int me4000_ao_ex_trig_enable(struct me4000_ao_context *ao_context)
{
u32 tmp;
unsigned long flags;
@@ -2593,7 +2573,7 @@ static int me4000_ao_ex_trig_enable(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_ex_trig_disable(me4000_ao_context_t * ao_context)
+static int me4000_ao_ex_trig_disable(struct me4000_ao_context *ao_context)
{
u32 tmp;
unsigned long flags;
@@ -2617,7 +2597,7 @@ static int me4000_ao_ex_trig_disable(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_simultaneous_disable(me4000_ao_context_t * ao_context)
+static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context)
{
u32 tmp;
@@ -2643,7 +2623,7 @@ static int me4000_ao_simultaneous_disable(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_simultaneous_ex_trig(me4000_ao_context_t * ao_context)
+static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context)
{
u32 tmp;
@@ -2659,7 +2639,7 @@ static int me4000_ao_simultaneous_ex_trig(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_simultaneous_sw(me4000_ao_context_t * ao_context)
+static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context)
{
u32 tmp;
@@ -2675,13 +2655,13 @@ static int me4000_ao_simultaneous_sw(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_preload(me4000_ao_context_t * ao_context)
+static int me4000_ao_preload(struct me4000_ao_context *ao_context)
{
CALL_PDEBUG("me4000_ao_preload() is executed\n");
return me4000_ao_simultaneous_sw(ao_context);
}
-static int me4000_ao_preload_update(me4000_ao_context_t * ao_context)
+static int me4000_ao_preload_update(struct me4000_ao_context *ao_context)
{
u32 tmp;
u32 ctrl;
@@ -2705,10 +2685,12 @@ static int me4000_ao_preload_update(me4000_ao_context_t * ao_context)
if (!
(tmp &
(0x1 <<
- (((me4000_ao_context_t *) entry)->index + 16)))) {
+ (((struct me4000_ao_context *)entry)->index
+ + 16)))) {
tmp &=
~(0x1 <<
- (((me4000_ao_context_t *) entry)->index));
+ (((struct me4000_ao_context *)entry)->
+ index));
}
}
}
@@ -2718,18 +2700,19 @@ static int me4000_ao_preload_update(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_simultaneous_update(me4000_ao_channel_list_t * arg,
- me4000_ao_context_t * ao_context)
+static int me4000_ao_simultaneous_update(struct me4000_ao_channel_list *arg,
+ struct me4000_ao_context *ao_context)
{
int err;
int i;
u32 tmp;
- me4000_ao_channel_list_t channels;
+ struct me4000_ao_channel_list channels;
CALL_PDEBUG("me4000_ao_simultaneous_update() is executed\n");
/* Copy data from user */
- err = copy_from_user(&channels, arg, sizeof(me4000_ao_channel_list_t));
+ err = copy_from_user(&channels, arg,
+ sizeof(struct me4000_ao_channel_list));
if (err) {
printk(KERN_ERR
"ME4000:me4000_ao_simultaneous_update():Can't copy command\n");
@@ -2737,13 +2720,12 @@ static int me4000_ao_simultaneous_update(me4000_ao_channel_list_t * arg,
}
channels.list =
- kmalloc(sizeof(unsigned long) * channels.count, GFP_KERNEL);
+ kzalloc(sizeof(unsigned long) * channels.count, GFP_KERNEL);
if (!channels.list) {
printk(KERN_ERR
"ME4000:me4000_ao_simultaneous_update():Can't get buffer\n");
return -ENOMEM;
}
- memset(channels.list, 0, sizeof(unsigned long) * channels.count);
/* Copy channel list from user */
err =
@@ -2777,7 +2759,7 @@ static int me4000_ao_simultaneous_update(me4000_ao_channel_list_t * arg,
return 0;
}
-static int me4000_ao_synchronous_ex_trig(me4000_ao_context_t * ao_context)
+static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context)
{
u32 tmp;
unsigned long flags;
@@ -2813,7 +2795,7 @@ static int me4000_ao_synchronous_ex_trig(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_synchronous_sw(me4000_ao_context_t * ao_context)
+static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context)
{
u32 tmp;
unsigned long flags;
@@ -2848,13 +2830,13 @@ static int me4000_ao_synchronous_sw(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_synchronous_disable(me4000_ao_context_t * ao_context)
+static int me4000_ao_synchronous_disable(struct me4000_ao_context *ao_context)
{
return me4000_ao_simultaneous_disable(ao_context);
}
static int me4000_ao_get_free_buffer(unsigned long *arg,
- me4000_ao_context_t * ao_context)
+ struct me4000_ao_context *ao_context)
{
unsigned long c;
int err;
@@ -2864,7 +2846,7 @@ static int me4000_ao_get_free_buffer(unsigned long *arg,
err = copy_to_user(arg, &c, sizeof(unsigned long));
if (err) {
printk(KERN_ERR
- "ME4000:me4000_ao_get_free_buffer():Can't copy to user space\n");
+ "%s:Can't copy to user space\n", __func__);
return -EFAULT;
}
@@ -2872,7 +2854,7 @@ static int me4000_ao_get_free_buffer(unsigned long *arg,
}
static int me4000_ao_ex_trig_timeout(unsigned long *arg,
- me4000_ao_context_t * ao_context)
+ struct me4000_ao_context *ao_context)
{
u32 tmp;
wait_queue_head_t queue;
@@ -2928,7 +2910,7 @@ static int me4000_ao_ex_trig_timeout(unsigned long *arg,
return 0;
}
-static int me4000_ao_enable_do(me4000_ao_context_t * ao_context)
+static int me4000_ao_enable_do(struct me4000_ao_context *ao_context)
{
u32 tmp;
unsigned long flags;
@@ -2959,7 +2941,7 @@ static int me4000_ao_enable_do(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_disable_do(me4000_ao_context_t * ao_context)
+static int me4000_ao_disable_do(struct me4000_ao_context *ao_context)
{
u32 tmp;
unsigned long flags;
@@ -2989,7 +2971,7 @@ static int me4000_ao_disable_do(me4000_ao_context_t * ao_context)
return 0;
}
-static int me4000_ao_fsm_state(int *arg, me4000_ao_context_t * ao_context)
+static int me4000_ao_fsm_state(int *arg, struct me4000_ao_context *ao_context)
{
unsigned long tmp;
@@ -3012,9 +2994,9 @@ static int me4000_ao_fsm_state(int *arg, me4000_ao_context_t * ao_context)
return 0;
}
-/*------------------------------- Analog input stuff --------------------------------------*/
+/*------------------------- Analog input stuff -------------------------------*/
-static int me4000_ai_prepare(me4000_ai_context_t * ai_context)
+static int me4000_ai_prepare(struct me4000_ai_context *ai_context)
{
wait_queue_head_t queue;
int err;
@@ -3057,14 +3039,13 @@ static int me4000_ai_prepare(me4000_ai_context_t * ai_context)
/* Allocate circular buffer */
ai_context->circ_buf.buf =
- kmalloc(ME4000_AI_BUFFER_SIZE, GFP_KERNEL);
+ kzalloc(ME4000_AI_BUFFER_SIZE, GFP_KERNEL);
if (!ai_context->circ_buf.buf) {
printk(KERN_ERR
"ME4000:me4000_ai_prepare():Can't get circular buffer\n");
free_irq(ai_context->irq, ai_context);
return -ENOMEM;
}
- memset(ai_context->circ_buf.buf, 0, ME4000_AI_BUFFER_SIZE);
/* Clear the circular buffer */
ai_context->circ_buf.head = 0;
@@ -3074,7 +3055,7 @@ static int me4000_ai_prepare(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_reset(me4000_ai_context_t * ai_context)
+static int me4000_ai_reset(struct me4000_ai_context *ai_context)
{
wait_queue_head_t queue;
u32 tmp;
@@ -3139,7 +3120,7 @@ static int me4000_ai_reset(me4000_ai_context_t * ai_context)
static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
CALL_PDEBUG("me4000_ai_ioctl_sing() is executed\n");
@@ -3157,16 +3138,17 @@ static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p,
switch (service) {
case ME4000_AI_SINGLE:
- return me4000_ai_single((me4000_ai_single_t *) arg, ai_context);
+ return me4000_ai_single((struct me4000_ai_single *)arg,
+ ai_context);
case ME4000_AI_EX_TRIG_ENABLE:
return me4000_ai_ex_trig_enable(ai_context);
case ME4000_AI_EX_TRIG_DISABLE:
return me4000_ai_ex_trig_disable(ai_context);
case ME4000_AI_EX_TRIG_SETUP:
- return me4000_ai_ex_trig_setup((me4000_ai_trigger_t *) arg,
+ return me4000_ai_ex_trig_setup((struct me4000_ai_trigger *)arg,
ai_context);
case ME4000_GET_USER_INFO:
- return me4000_get_user_info((me4000_user_info_t *) arg,
+ return me4000_get_user_info((struct me4000_user_info *)arg,
ai_context->board_info);
case ME4000_AI_OFFSET_ENABLE:
return me4000_ai_offset_enable(ai_context);
@@ -3177,9 +3159,11 @@ static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p,
case ME4000_AI_FULLSCALE_DISABLE:
return me4000_ai_fullscale_disable(ai_context);
case ME4000_AI_EEPROM_READ:
- return me4000_eeprom_read((me4000_eeprom_t *) arg, ai_context);
+ return me4000_eeprom_read((struct me4000_eeprom *)arg,
+ ai_context);
case ME4000_AI_EEPROM_WRITE:
- return me4000_eeprom_write((me4000_eeprom_t *) arg, ai_context);
+ return me4000_eeprom_write((struct me4000_eeprom *)arg,
+ ai_context);
default:
printk(KERN_ERR
"me4000_ai_ioctl_sing():Invalid service number\n");
@@ -3188,10 +3172,10 @@ static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p,
return 0;
}
-static int me4000_ai_single(me4000_ai_single_t * arg,
- me4000_ai_context_t * ai_context)
+static int me4000_ai_single(struct me4000_ai_single *arg,
+ struct me4000_ai_context *ai_context)
{
- me4000_ai_single_t cmd;
+ struct me4000_ai_single cmd;
int err;
u32 tmp;
wait_queue_head_t queue;
@@ -3202,7 +3186,7 @@ static int me4000_ai_single(me4000_ai_single_t * arg,
init_waitqueue_head(&queue);
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_ai_single_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_single));
if (err) {
printk(KERN_ERR
"ME4000:me4000_ai_single():Can't copy from user space\n");
@@ -3301,7 +3285,7 @@ static int me4000_ai_single(me4000_ai_single_t * arg,
cmd.value = me4000_inl(ai_context->data_reg) & 0xFFFF;
/* Copy result back to user */
- err = copy_to_user(arg, &cmd, sizeof(me4000_ai_single_t));
+ err = copy_to_user(arg, &cmd, sizeof(struct me4000_ai_single));
if (err) {
printk(KERN_ERR
"ME4000:me4000_ai_single():Can't copy to user space\n");
@@ -3314,7 +3298,7 @@ static int me4000_ai_single(me4000_ai_single_t * arg,
static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
CALL_PDEBUG("me4000_ai_ioctl_sw() is executed\n");
@@ -3332,9 +3316,11 @@ static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p,
switch (service) {
case ME4000_AI_SC_SETUP:
- return me4000_ai_sc_setup((me4000_ai_sc_t *) arg, ai_context);
+ return me4000_ai_sc_setup((struct me4000_ai_sc *)arg,
+ ai_context);
case ME4000_AI_CONFIG:
- return me4000_ai_config((me4000_ai_config_t *) arg, ai_context);
+ return me4000_ai_config((struct me4000_ai_config *)arg,
+ ai_context);
case ME4000_AI_START:
return me4000_ai_start(ai_context);
case ME4000_AI_STOP:
@@ -3344,19 +3330,20 @@ static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p,
case ME4000_AI_FSM_STATE:
return me4000_ai_fsm_state((int *)arg, ai_context);
case ME4000_GET_USER_INFO:
- return me4000_get_user_info((me4000_user_info_t *) arg,
+ return me4000_get_user_info((struct me4000_user_info *)arg,
ai_context->board_info);
case ME4000_AI_EEPROM_READ:
- return me4000_eeprom_read((me4000_eeprom_t *) arg, ai_context);
+ return me4000_eeprom_read((struct me4000_eeprom *)arg,
+ ai_context);
case ME4000_AI_EEPROM_WRITE:
- return me4000_eeprom_write((me4000_eeprom_t *) arg, ai_context);
+ return me4000_eeprom_write((struct me4000_eeprom *)arg,
+ ai_context);
case ME4000_AI_GET_COUNT_BUFFER:
return me4000_ai_get_count_buffer((unsigned long *)arg,
ai_context);
default:
printk(KERN_ERR
- "ME4000:me4000_ai_ioctl_sw():Invalid service number %d\n",
- service);
+ "%s:Invalid service number %d\n", __func__, service);
return -ENOTTY;
}
return 0;
@@ -3365,7 +3352,7 @@ static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p,
static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
CALL_PDEBUG("me4000_ai_ioctl_ext() is executed\n");
@@ -3383,9 +3370,11 @@ static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p,
switch (service) {
case ME4000_AI_SC_SETUP:
- return me4000_ai_sc_setup((me4000_ai_sc_t *) arg, ai_context);
+ return me4000_ai_sc_setup((struct me4000_ai_sc *)arg,
+ ai_context);
case ME4000_AI_CONFIG:
- return me4000_ai_config((me4000_ai_config_t *) arg, ai_context);
+ return me4000_ai_config((struct me4000_ai_config *)arg,
+ ai_context);
case ME4000_AI_START:
return me4000_ai_start_ex((unsigned long *)arg, ai_context);
case ME4000_AI_STOP:
@@ -3397,20 +3386,19 @@ static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p,
case ME4000_AI_EX_TRIG_DISABLE:
return me4000_ai_ex_trig_disable(ai_context);
case ME4000_AI_EX_TRIG_SETUP:
- return me4000_ai_ex_trig_setup((me4000_ai_trigger_t *) arg,
+ return me4000_ai_ex_trig_setup((struct me4000_ai_trigger *)arg,
ai_context);
case ME4000_AI_FSM_STATE:
return me4000_ai_fsm_state((int *)arg, ai_context);
case ME4000_GET_USER_INFO:
- return me4000_get_user_info((me4000_user_info_t *) arg,
+ return me4000_get_user_info((struct me4000_user_info *)arg,
ai_context->board_info);
case ME4000_AI_GET_COUNT_BUFFER:
return me4000_ai_get_count_buffer((unsigned long *)arg,
ai_context);
default:
printk(KERN_ERR
- "ME4000:me4000_ai_ioctl_ext():Invalid service number %d\n",
- service);
+ "%s:Invalid service number %d\n", __func__ , service);
return -ENOTTY;
}
return 0;
@@ -3418,7 +3406,7 @@ static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p,
static int me4000_ai_fasync(int fd, struct file *file_p, int mode)
{
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
CALL_PDEBUG("me4000_ao_fasync_cont() is executed\n");
@@ -3426,10 +3414,10 @@ static int me4000_ai_fasync(int fd, struct file *file_p, int mode)
return fasync_helper(fd, file_p, mode, &ai_context->fasync_p);
}
-static int me4000_ai_config(me4000_ai_config_t * arg,
- me4000_ai_context_t * ai_context)
+static int me4000_ai_config(struct me4000_ai_config *arg,
+ struct me4000_ai_context *ai_context)
{
- me4000_ai_config_t cmd;
+ struct me4000_ai_config cmd;
u32 *list = NULL;
u32 mode;
int i;
@@ -3451,7 +3439,7 @@ static int me4000_ai_config(me4000_ai_config_t * arg,
}
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_ai_config_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_config));
if (err) {
printk(KERN_ERR
"ME4000:me4000_ai_config():Can't copy from user space\n");
@@ -3671,7 +3659,7 @@ static int me4000_ai_config(me4000_ai_config_t * arg,
return 0;
- AI_CONFIG_ERR:
+AI_CONFIG_ERR:
/* Reset the timers */
ai_context->chan_timer = 66;
@@ -3699,7 +3687,7 @@ static int me4000_ai_config(me4000_ai_config_t * arg,
}
-static int ai_common_start(me4000_ai_context_t * ai_context)
+static int ai_common_start(struct me4000_ai_context *ai_context)
{
u32 tmp;
CALL_PDEBUG("ai_common_start() is executed\n");
@@ -3762,7 +3750,7 @@ static int ai_common_start(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_start(me4000_ai_context_t * ai_context)
+static int me4000_ai_start(struct me4000_ai_context *ai_context)
{
int err;
CALL_PDEBUG("me4000_ai_start() is executed\n");
@@ -3779,7 +3767,7 @@ static int me4000_ai_start(me4000_ai_context_t * ai_context)
}
static int me4000_ai_start_ex(unsigned long *arg,
- me4000_ai_context_t * ai_context)
+ struct me4000_ai_context *ai_context)
{
int err;
wait_queue_head_t queue;
@@ -3834,7 +3822,7 @@ static int me4000_ai_start_ex(unsigned long *arg,
return 0;
}
-static int me4000_ai_stop(me4000_ai_context_t * ai_context)
+static int me4000_ai_stop(struct me4000_ai_context *ai_context)
{
wait_queue_head_t queue;
u32 tmp;
@@ -3871,7 +3859,7 @@ static int me4000_ai_stop(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_immediate_stop(me4000_ai_context_t * ai_context)
+static int me4000_ai_immediate_stop(struct me4000_ai_context *ai_context)
{
wait_queue_head_t queue;
u32 tmp;
@@ -3908,7 +3896,7 @@ static int me4000_ai_immediate_stop(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_ex_trig_enable(me4000_ai_context_t * ai_context)
+static int me4000_ai_ex_trig_enable(struct me4000_ai_context *ai_context)
{
u32 tmp;
unsigned long flags;
@@ -3924,7 +3912,7 @@ static int me4000_ai_ex_trig_enable(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_ex_trig_disable(me4000_ai_context_t * ai_context)
+static int me4000_ai_ex_trig_disable(struct me4000_ai_context *ai_context)
{
u32 tmp;
unsigned long flags;
@@ -3940,10 +3928,10 @@ static int me4000_ai_ex_trig_disable(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_ex_trig_setup(me4000_ai_trigger_t * arg,
- me4000_ai_context_t * ai_context)
+static int me4000_ai_ex_trig_setup(struct me4000_ai_trigger *arg,
+ struct me4000_ai_context *ai_context)
{
- me4000_ai_trigger_t cmd;
+ struct me4000_ai_trigger cmd;
int err;
u32 tmp;
unsigned long flags;
@@ -3951,7 +3939,7 @@ static int me4000_ai_ex_trig_setup(me4000_ai_trigger_t * arg,
CALL_PDEBUG("me4000_ai_ex_trig_setup() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_ai_trigger_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_trigger));
if (err) {
printk(KERN_ERR
"ME4000:me4000_ai_ex_trig_setup():Can't copy from user space\n");
@@ -4000,16 +3988,16 @@ static int me4000_ai_ex_trig_setup(me4000_ai_trigger_t * arg,
return 0;
}
-static int me4000_ai_sc_setup(me4000_ai_sc_t * arg,
- me4000_ai_context_t * ai_context)
+static int me4000_ai_sc_setup(struct me4000_ai_sc *arg,
+ struct me4000_ai_context *ai_context)
{
- me4000_ai_sc_t cmd;
+ struct me4000_ai_sc cmd;
int err;
CALL_PDEBUG("me4000_ai_sc_setup() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_ai_sc_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_sc));
if (err) {
printk(KERN_ERR
"ME4000:me4000_ai_sc_setup():Can't copy from user space\n");
@@ -4023,9 +4011,9 @@ static int me4000_ai_sc_setup(me4000_ai_sc_t * arg,
}
static ssize_t me4000_ai_read(struct file *filep, char *buff, size_t cnt,
- loff_t * offp)
+ loff_t *offp)
{
- me4000_ai_context_t *ai_context = filep->private_data;
+ struct me4000_ai_context *ai_context = filep->private_data;
s16 *buffer = (s16 *) buff;
size_t count = cnt / 2;
unsigned long flags;
@@ -4150,9 +4138,9 @@ static ssize_t me4000_ai_read(struct file *filep, char *buff, size_t cnt,
return ret * 2;
}
-static unsigned int me4000_ai_poll(struct file *file_p, poll_table * wait)
+static unsigned int me4000_ai_poll(struct file *file_p, poll_table *wait)
{
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
unsigned long mask = 0;
CALL_PDEBUG("me4000_ai_poll() is executed\n");
@@ -4171,7 +4159,7 @@ static unsigned int me4000_ai_poll(struct file *file_p, poll_table * wait)
return mask;
}
-static int me4000_ai_offset_enable(me4000_ai_context_t * ai_context)
+static int me4000_ai_offset_enable(struct me4000_ai_context *ai_context)
{
unsigned long tmp;
@@ -4184,7 +4172,7 @@ static int me4000_ai_offset_enable(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_offset_disable(me4000_ai_context_t * ai_context)
+static int me4000_ai_offset_disable(struct me4000_ai_context *ai_context)
{
unsigned long tmp;
@@ -4197,7 +4185,7 @@ static int me4000_ai_offset_disable(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_fullscale_enable(me4000_ai_context_t * ai_context)
+static int me4000_ai_fullscale_enable(struct me4000_ai_context *ai_context)
{
unsigned long tmp;
@@ -4210,7 +4198,7 @@ static int me4000_ai_fullscale_enable(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_fullscale_disable(me4000_ai_context_t * ai_context)
+static int me4000_ai_fullscale_disable(struct me4000_ai_context *ai_context)
{
unsigned long tmp;
@@ -4223,7 +4211,7 @@ static int me4000_ai_fullscale_disable(me4000_ai_context_t * ai_context)
return 0;
}
-static int me4000_ai_fsm_state(int *arg, me4000_ai_context_t * ai_context)
+static int me4000_ai_fsm_state(int *arg, struct me4000_ai_context *ai_context)
{
unsigned long tmp;
@@ -4242,7 +4230,7 @@ static int me4000_ai_fsm_state(int *arg, me4000_ai_context_t * ai_context)
}
static int me4000_ai_get_count_buffer(unsigned long *arg,
- me4000_ai_context_t * ai_context)
+ struct me4000_ai_context *ai_context)
{
unsigned long c;
int err;
@@ -4252,7 +4240,7 @@ static int me4000_ai_get_count_buffer(unsigned long *arg,
err = copy_to_user(arg, &c, sizeof(unsigned long));
if (err) {
printk(KERN_ERR
- "ME4000:me4000_ai_get_count_buffer():Can't copy to user space\n");
+ "%s:Can't copy to user space\n", __func__);
return -EFAULT;
}
@@ -4261,7 +4249,7 @@ static int me4000_ai_get_count_buffer(unsigned long *arg,
/*---------------------------------- EEPROM stuff ---------------------------*/
-static int eeprom_write_cmd(me4000_ai_context_t * ai_context, unsigned long cmd,
+static int eeprom_write_cmd(struct me4000_ai_context *ai_context, unsigned long cmd,
int length)
{
int i;
@@ -4318,7 +4306,7 @@ static int eeprom_write_cmd(me4000_ai_context_t * ai_context, unsigned long cmd,
return 0;
}
-static unsigned short eeprom_read_cmd(me4000_ai_context_t * ai_context,
+static unsigned short eeprom_read_cmd(struct me4000_ai_context *ai_context,
unsigned long cmd, int length)
{
int i;
@@ -4397,11 +4385,11 @@ static unsigned short eeprom_read_cmd(me4000_ai_context_t * ai_context,
return id;
}
-static int me4000_eeprom_write(me4000_eeprom_t * arg,
- me4000_ai_context_t * ai_context)
+static int me4000_eeprom_write(struct me4000_eeprom *arg,
+ struct me4000_ai_context *ai_context)
{
int err;
- me4000_eeprom_t setup;
+ struct me4000_eeprom setup;
unsigned long cmd;
unsigned long date_high;
unsigned long date_low;
@@ -4594,12 +4582,12 @@ static int me4000_eeprom_write(me4000_eeprom_t * arg,
return 0;
}
-static int me4000_eeprom_read(me4000_eeprom_t * arg,
- me4000_ai_context_t * ai_context)
+static int me4000_eeprom_read(struct me4000_eeprom *arg,
+ struct me4000_ai_context *ai_context)
{
int err;
unsigned long cmd;
- me4000_eeprom_t setup;
+ struct me4000_eeprom setup;
CALL_PDEBUG("me4000_eeprom_read() is executed\n");
@@ -4687,7 +4675,7 @@ static int me4000_eeprom_read(me4000_eeprom_t * arg,
static int me4000_dio_ioctl(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_dio_context_t *dio_context;
+ struct me4000_dio_context *dio_context;
CALL_PDEBUG("me4000_dio_ioctl() is executed\n");
@@ -4704,13 +4692,13 @@ static int me4000_dio_ioctl(struct inode *inode_p, struct file *file_p,
switch (service) {
case ME4000_DIO_CONFIG:
- return me4000_dio_config((me4000_dio_config_t *) arg,
+ return me4000_dio_config((struct me4000_dio_config *)arg,
dio_context);
case ME4000_DIO_SET_BYTE:
- return me4000_dio_set_byte((me4000_dio_byte_t *) arg,
+ return me4000_dio_set_byte((struct me4000_dio_byte *)arg,
dio_context);
case ME4000_DIO_GET_BYTE:
- return me4000_dio_get_byte((me4000_dio_byte_t *) arg,
+ return me4000_dio_get_byte((struct me4000_dio_byte *)arg,
dio_context);
case ME4000_DIO_RESET:
return me4000_dio_reset(dio_context);
@@ -4723,17 +4711,17 @@ static int me4000_dio_ioctl(struct inode *inode_p, struct file *file_p,
return 0;
}
-static int me4000_dio_config(me4000_dio_config_t * arg,
- me4000_dio_context_t * dio_context)
+static int me4000_dio_config(struct me4000_dio_config *arg,
+ struct me4000_dio_context *dio_context)
{
- me4000_dio_config_t cmd;
+ struct me4000_dio_config cmd;
u32 tmp;
int err;
CALL_PDEBUG("me4000_dio_config() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_dio_config_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_config));
if (err) {
printk(KERN_ERR
"ME4000:me4000_dio_config():Can't copy from user space\n");
@@ -4964,16 +4952,16 @@ static int me4000_dio_config(me4000_dio_config_t * arg,
return 0;
}
-static int me4000_dio_set_byte(me4000_dio_byte_t * arg,
- me4000_dio_context_t * dio_context)
+static int me4000_dio_set_byte(struct me4000_dio_byte *arg,
+ struct me4000_dio_context *dio_context)
{
- me4000_dio_byte_t cmd;
+ struct me4000_dio_byte cmd;
int err;
CALL_PDEBUG("me4000_dio_set_byte() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_dio_byte_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_byte));
if (err) {
printk(KERN_ERR
"ME4000:me4000_dio_set_byte():Can't copy from user space\n");
@@ -5030,16 +5018,16 @@ static int me4000_dio_set_byte(me4000_dio_byte_t * arg,
return 0;
}
-static int me4000_dio_get_byte(me4000_dio_byte_t * arg,
- me4000_dio_context_t * dio_context)
+static int me4000_dio_get_byte(struct me4000_dio_byte *arg,
+ struct me4000_dio_context *dio_context)
{
- me4000_dio_byte_t cmd;
+ struct me4000_dio_byte cmd;
int err;
CALL_PDEBUG("me4000_dio_get_byte() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_dio_byte_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_byte));
if (err) {
printk(KERN_ERR
"ME4000:me4000_dio_get_byte():Can't copy from user space\n");
@@ -5070,7 +5058,7 @@ static int me4000_dio_get_byte(me4000_dio_byte_t * arg,
}
/* Copy result back to user */
- err = copy_to_user(arg, &cmd, sizeof(me4000_dio_byte_t));
+ err = copy_to_user(arg, &cmd, sizeof(struct me4000_dio_byte));
if (err) {
printk(KERN_ERR
"ME4000:me4000_dio_get_byte():Can't copy to user space\n");
@@ -5080,7 +5068,7 @@ static int me4000_dio_get_byte(me4000_dio_byte_t * arg,
return 0;
}
-static int me4000_dio_reset(me4000_dio_context_t * dio_context)
+static int me4000_dio_reset(struct me4000_dio_context *dio_context)
{
CALL_PDEBUG("me4000_dio_reset() is executed\n");
@@ -5101,7 +5089,7 @@ static int me4000_dio_reset(me4000_dio_context_t * dio_context)
static int me4000_cnt_ioctl(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_cnt_context_t *cnt_context;
+ struct me4000_cnt_context *cnt_context;
CALL_PDEBUG("me4000_cnt_ioctl() is executed\n");
@@ -5118,11 +5106,11 @@ static int me4000_cnt_ioctl(struct inode *inode_p, struct file *file_p,
switch (service) {
case ME4000_CNT_READ:
- return me4000_cnt_read((me4000_cnt_t *) arg, cnt_context);
+ return me4000_cnt_read((struct me4000_cnt *)arg, cnt_context);
case ME4000_CNT_WRITE:
- return me4000_cnt_write((me4000_cnt_t *) arg, cnt_context);
+ return me4000_cnt_write((struct me4000_cnt *)arg, cnt_context);
case ME4000_CNT_CONFIG:
- return me4000_cnt_config((me4000_cnt_config_t *) arg,
+ return me4000_cnt_config((struct me4000_cnt_config *)arg,
cnt_context);
case ME4000_CNT_RESET:
return me4000_cnt_reset(cnt_context);
@@ -5135,10 +5123,10 @@ static int me4000_cnt_ioctl(struct inode *inode_p, struct file *file_p,
return 0;
}
-static int me4000_cnt_config(me4000_cnt_config_t * arg,
- me4000_cnt_context_t * cnt_context)
+static int me4000_cnt_config(struct me4000_cnt_config *arg,
+ struct me4000_cnt_context *cnt_context)
{
- me4000_cnt_config_t cmd;
+ struct me4000_cnt_config cmd;
u8 counter;
u8 mode;
int err;
@@ -5146,7 +5134,7 @@ static int me4000_cnt_config(me4000_cnt_config_t * arg,
CALL_PDEBUG("me4000_cnt_config() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_cnt_config_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt_config));
if (err) {
printk(KERN_ERR
"ME4000:me4000_cnt_config():Can't copy from user space\n");
@@ -5204,17 +5192,17 @@ static int me4000_cnt_config(me4000_cnt_config_t * arg,
return 0;
}
-static int me4000_cnt_read(me4000_cnt_t * arg,
- me4000_cnt_context_t * cnt_context)
+static int me4000_cnt_read(struct me4000_cnt *arg,
+ struct me4000_cnt_context *cnt_context)
{
- me4000_cnt_t cmd;
+ struct me4000_cnt cmd;
u8 tmp;
int err;
CALL_PDEBUG("me4000_cnt_read() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_cnt_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt));
if (err) {
printk(KERN_ERR
"ME4000:me4000_cnt_read():Can't copy from user space\n");
@@ -5249,7 +5237,7 @@ static int me4000_cnt_read(me4000_cnt_t * arg,
}
/* Copy result back to user */
- err = copy_to_user(arg, &cmd, sizeof(me4000_cnt_t));
+ err = copy_to_user(arg, &cmd, sizeof(struct me4000_cnt));
if (err) {
printk(KERN_ERR
"ME4000:me4000_cnt_read():Can't copy to user space\n");
@@ -5259,17 +5247,17 @@ static int me4000_cnt_read(me4000_cnt_t * arg,
return 0;
}
-static int me4000_cnt_write(me4000_cnt_t * arg,
- me4000_cnt_context_t * cnt_context)
+static int me4000_cnt_write(struct me4000_cnt *arg,
+ struct me4000_cnt_context *cnt_context)
{
- me4000_cnt_t cmd;
+ struct me4000_cnt cmd;
u8 tmp;
int err;
CALL_PDEBUG("me4000_cnt_write() is executed\n");
/* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(me4000_cnt_t));
+ err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt));
if (err) {
printk(KERN_ERR
"ME4000:me4000_cnt_write():Can't copy from user space\n");
@@ -5306,7 +5294,7 @@ static int me4000_cnt_write(me4000_cnt_t * arg,
return 0;
}
-static int me4000_cnt_reset(me4000_cnt_context_t * cnt_context)
+static int me4000_cnt_reset(struct me4000_cnt_context *cnt_context)
{
CALL_PDEBUG("me4000_cnt_reset() is executed\n");
@@ -5333,7 +5321,7 @@ static int me4000_cnt_reset(me4000_cnt_context_t * cnt_context)
static int me4000_ext_int_ioctl(struct inode *inode_p, struct file *file_p,
unsigned int service, unsigned long arg)
{
- me4000_ext_int_context_t *ext_int_context;
+ struct me4000_ext_int_context *ext_int_context;
CALL_PDEBUG("me4000_ext_int_ioctl() is executed\n");
@@ -5366,7 +5354,7 @@ static int me4000_ext_int_ioctl(struct inode *inode_p, struct file *file_p,
return 0;
}
-static int me4000_ext_int_enable(me4000_ext_int_context_t * ext_int_context)
+static int me4000_ext_int_enable(struct me4000_ext_int_context *ext_int_context)
{
unsigned long tmp;
@@ -5379,7 +5367,7 @@ static int me4000_ext_int_enable(me4000_ext_int_context_t * ext_int_context)
return 0;
}
-static int me4000_ext_int_disable(me4000_ext_int_context_t * ext_int_context)
+static int me4000_ext_int_disable(struct me4000_ext_int_context *ext_int_context)
{
unsigned long tmp;
@@ -5393,7 +5381,7 @@ static int me4000_ext_int_disable(me4000_ext_int_context_t * ext_int_context)
}
static int me4000_ext_int_count(unsigned long *arg,
- me4000_ext_int_context_t * ext_int_context)
+ struct me4000_ext_int_context *ext_int_context)
{
CALL_PDEBUG("me4000_ext_int_count() is executed\n");
@@ -5404,10 +5392,10 @@ static int me4000_ext_int_count(unsigned long *arg,
/*------------------------------------ General stuff ------------------------------------*/
-static int me4000_get_user_info(me4000_user_info_t * arg,
- me4000_info_t * board_info)
+static int me4000_get_user_info(struct me4000_user_info *arg,
+ struct me4000_info *board_info)
{
- me4000_user_info_t user_info;
+ struct me4000_user_info user_info;
CALL_PDEBUG("me4000_get_user_info() is executed\n");
@@ -5437,7 +5425,7 @@ static int me4000_get_user_info(me4000_user_info_t * arg,
user_info.cnt_count = board_info->board_p->cnt.count;
- if (copy_to_user(arg, &user_info, sizeof(me4000_user_info_t)))
+ if (copy_to_user(arg, &user_info, sizeof(struct me4000_user_info)))
return -EFAULT;
return 0;
@@ -5448,7 +5436,7 @@ static int me4000_get_user_info(me4000_user_info_t * arg,
static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode)
{
int result = 0;
- me4000_ext_int_context_t *ext_int_context;
+ struct me4000_ext_int_context *ext_int_context;
CALL_PDEBUG("me4000_ext_int_fasync() is executed\n");
@@ -5465,7 +5453,7 @@ static irqreturn_t me4000_ao_isr(int irq, void *dev_id)
{
u32 tmp;
u32 value;
- me4000_ao_context_t *ao_context;
+ struct me4000_ao_context *ao_context;
int i;
int c = 0;
int c1 = 0;
@@ -5589,7 +5577,7 @@ static irqreturn_t me4000_ao_isr(int irq, void *dev_id)
static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
{
u32 tmp;
- me4000_ai_context_t *ai_context;
+ struct me4000_ai_context *ai_context;
int i;
int c = 0;
int c1 = 0;
@@ -5933,7 +5921,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
static irqreturn_t me4000_ext_int_isr(int irq, void *dev_id)
{
- me4000_ext_int_context_t *ext_int_context;
+ struct me4000_ext_int_context *ext_int_context;
unsigned long tmp;
ISR_PDEBUG("me4000_ext_int_isr() is executed\n");
@@ -5969,10 +5957,10 @@ static irqreturn_t me4000_ext_int_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-void __exit me4000_module_exit(void)
+static void __exit me4000_module_exit(void)
{
struct list_head *board_p;
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
CALL_PDEBUG("cleanup_module() is executed\n");
@@ -5993,7 +5981,7 @@ void __exit me4000_module_exit(void)
/* Reset the boards */
for (board_p = me4000_board_info_list.next;
board_p != &me4000_board_info_list; board_p = board_p->next) {
- board_info = list_entry(board_p, me4000_info_t, list);
+ board_info = list_entry(board_p, struct me4000_info, list);
me4000_reset_board(board_info);
}
@@ -6007,7 +5995,7 @@ static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
{
int len = 0;
int limit = count - 1000;
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
struct list_head *ptr;
len += sprintf(buf + len, "\nME4000 DRIVER VERSION %X.%X.%X\n\n",
@@ -6019,7 +6007,7 @@ static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
for (ptr = me4000_board_info_list.next;
(ptr != &me4000_board_info_list) && (len < limit);
ptr = ptr->next) {
- board_info = list_entry(ptr, me4000_info_t, list);
+ board_info = list_entry(ptr, struct me4000_info, list);
len +=
sprintf(buf + len, "Board number %d:\n",
@@ -6029,14 +6017,14 @@ static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
sprintf(buf + len, "PLX base register = 0x%lX\n",
board_info->plx_regbase);
len +=
- sprintf(buf + len, "PLX base register size = 0x%lX\n",
- board_info->plx_regbase_size);
+ sprintf(buf + len, "PLX base register size = 0x%X\n",
+ (unsigned int)board_info->plx_regbase_size);
len +=
- sprintf(buf + len, "ME4000 base register = 0x%lX\n",
- board_info->me4000_regbase);
+ sprintf(buf + len, "ME4000 base register = 0x%X\n",
+ (unsigned int)board_info->me4000_regbase);
len +=
- sprintf(buf + len, "ME4000 base register size = 0x%lX\n",
- board_info->me4000_regbase_size);
+ sprintf(buf + len, "ME4000 base register size = 0x%X\n",
+ (unsigned int)board_info->me4000_regbase_size);
len +=
sprintf(buf + len, "Serial number = 0x%X\n",
board_info->serial_no);
diff --git a/drivers/staging/me4000/me4000.h b/drivers/staging/me4000/me4000.h
index c35e4b9793a..81c6f4d5e25 100644
--- a/drivers/staging/me4000/me4000.h
+++ b/drivers/staging/me4000/me4000.h
@@ -329,46 +329,46 @@
Circular buffer used for analog input/output reads/writes.
===========================================================================*/
-typedef struct me4000_circ_buf {
+struct me4000_circ_buf {
s16 *buf;
int volatile head;
int volatile tail;
-} me4000_circ_buf_t;
+};
/*=============================================================================
Information about the hardware capabilities
===========================================================================*/
-typedef struct me4000_ao_info {
+struct me4000_ao_info {
int count;
int fifo_count;
-} me4000_ao_info_t;
+};
-typedef struct me4000_ai_info {
+struct me4000_ai_info {
int count;
int sh_count;
int diff_count;
int ex_trig_analog;
-} me4000_ai_info_t;
+};
-typedef struct me4000_dio_info {
+struct me4000_dio_info {
int count;
-} me4000_dio_info_t;
+};
-typedef struct me4000_cnt_info {
+struct me4000_cnt_info {
int count;
-} me4000_cnt_info_t;
+};
-typedef struct me4000_board {
+struct me4000_board {
u16 vendor_id;
u16 device_id;
- me4000_ao_info_t ao;
- me4000_ai_info_t ai;
- me4000_dio_info_t dio;
- me4000_cnt_info_t cnt;
-} me4000_board_t;
+ struct me4000_ao_info ao;
+ struct me4000_ai_info ai;
+ struct me4000_dio_info dio;
+ struct me4000_cnt_info cnt;
+};
-static me4000_board_t me4000_boards[] = {
+static struct me4000_board me4000_boards[] = {
{PCI_VENDOR_ID_MEILHAUS, 0x4610, {0, 0}, {16, 0, 0, 0}, {4}, {3}},
{PCI_VENDOR_ID_MEILHAUS, 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
@@ -391,8 +391,6 @@ static me4000_board_t me4000_boards[] = {
{0},
};
-#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(me4000_board_t) - 1)
-
/*=============================================================================
PCI device table.
This is used by modprobe to translate PCI IDs to drivers.
@@ -427,19 +425,19 @@ MODULE_DEVICE_TABLE(pci, me4000_pci_table);
Global board and subdevice information structures
===========================================================================*/
-typedef struct me4000_info {
+struct me4000_info {
struct list_head list; // List of all detected boards
int board_count; // Index of the board after detection
unsigned long plx_regbase; // PLX configuration space base address
- unsigned long me4000_regbase; // Base address of the ME4000
- unsigned long timer_regbase; // Base address of the timer circuit
- unsigned long program_regbase; // Base address to set the program pin for the xilinx
+ resource_size_t me4000_regbase; // Base address of the ME4000
+ resource_size_t timer_regbase; // Base address of the timer circuit
+ resource_size_t program_regbase; // Base address to set the program pin for the xilinx
unsigned long plx_regbase_size; // PLX register set space
- unsigned long me4000_regbase_size; // ME4000 register set space
- unsigned long timer_regbase_size; // Timer circuit register set space
- unsigned long program_regbase_size; // Size of program base address of the ME4000
+ resource_size_t me4000_regbase_size; // ME4000 register set space
+ resource_size_t timer_regbase_size; // Timer circuit register set space
+ resource_size_t program_regbase_size; // Size of program base address of the ME4000
unsigned int serial_no; // Serial number of the board
unsigned char hw_revision; // Hardware revision of the board
@@ -451,7 +449,7 @@ typedef struct me4000_info {
int pci_func_no; // PCI function number
struct pci_dev *pci_dev_p; // General PCI information
- me4000_board_t *board_p; // Holds the board capabilities
+ struct me4000_board *board_p; // Holds the board capabilities
unsigned int irq; // IRQ assigned from the PCI BIOS
unsigned int irq_count; // Count of external interrupts
@@ -464,18 +462,18 @@ typedef struct me4000_info {
struct me4000_dio_context *dio_context; // Digital I/O specific context
struct me4000_cnt_context *cnt_context; // Counter specific context
struct me4000_ext_int_context *ext_int_context; // External interrupt specific context
-} me4000_info_t;
+};
-typedef struct me4000_ao_context {
+struct me4000_ao_context {
struct list_head list; // linked list of me4000_ao_context_t
int index; // Index in the list
int mode; // Indicates mode (0 = single, 1 = wraparound, 2 = continous)
int dac_in_use; // Indicates if already opend
spinlock_t use_lock; // Guards in_use
spinlock_t int_lock; // Used when locking out interrupts
- me4000_circ_buf_t circ_buf; // Circular buffer
+ struct me4000_circ_buf circ_buf; // Circular buffer
wait_queue_head_t wait_queue; // Wait queue to sleep while blocking write
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
unsigned int irq; // The irq associated with this ADC
int volatile pipe_flag; // Indicates broken pipe set from me4000_ao_isr()
unsigned long ctrl_reg;
@@ -486,9 +484,9 @@ typedef struct me4000_ao_context {
unsigned long irq_status_reg;
unsigned long preload_reg;
struct fasync_struct *fasync_p; // Queue for asynchronous notification
-} me4000_ao_context_t;
+};
-typedef struct me4000_ai_context {
+struct me4000_ai_context {
struct list_head list; // linked list of me4000_ai_info_t
int mode; // Indicates mode
int in_use; // Indicates if already opend
@@ -496,9 +494,9 @@ typedef struct me4000_ai_context {
spinlock_t int_lock; // Used when locking out interrupts
int number; // Number of the DAC
unsigned int irq; // The irq associated with this ADC
- me4000_circ_buf_t circ_buf; // Circular buffer
+ struct me4000_circ_buf circ_buf; // Circular buffer
wait_queue_head_t wait_queue; // Wait queue to sleep while blocking read
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
struct fasync_struct *fasync_p; // Queue for asynchronous notification
@@ -523,48 +521,48 @@ typedef struct me4000_ai_context {
unsigned long channel_list_count;
unsigned long sample_counter;
int sample_counter_reload;
-} me4000_ai_context_t;
+};
-typedef struct me4000_dio_context {
+struct me4000_dio_context {
struct list_head list; // linked list of me4000_dio_context_t
int in_use; // Indicates if already opend
spinlock_t use_lock; // Guards in_use
int number;
int dio_count;
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
unsigned long dir_reg;
unsigned long ctrl_reg;
unsigned long port_0_reg;
unsigned long port_1_reg;
unsigned long port_2_reg;
unsigned long port_3_reg;
-} me4000_dio_context_t;
+};
-typedef struct me4000_cnt_context {
+struct me4000_cnt_context {
struct list_head list; // linked list of me4000_dio_context_t
int in_use; // Indicates if already opend
spinlock_t use_lock; // Guards in_use
int number;
int cnt_count;
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
unsigned long ctrl_reg;
unsigned long counter_0_reg;
unsigned long counter_1_reg;
unsigned long counter_2_reg;
-} me4000_cnt_context_t;
+};
-typedef struct me4000_ext_int_context {
+struct me4000_ext_int_context {
struct list_head list; // linked list of me4000_dio_context_t
int in_use; // Indicates if already opend
spinlock_t use_lock; // Guards in_use
int number;
- me4000_info_t *board_info;
+ struct me4000_info *board_info;
unsigned int irq;
unsigned long int_count;
struct fasync_struct *fasync_ptr;
unsigned long ctrl_reg;
unsigned long irq_status_reg;
-} me4000_ext_int_context_t;
+};
#endif
@@ -745,12 +743,12 @@ typedef struct me4000_ext_int_context {
General type definitions
----------------------------------------------------------------------------*/
-typedef struct me4000_user_info {
+struct me4000_user_info {
int board_count; // Index of the board after detection
unsigned long plx_regbase; // PLX configuration space base address
- unsigned long me4000_regbase; // Base address of the ME4000
+ resource_size_t me4000_regbase; // Base address of the ME4000
unsigned long plx_regbase_size; // PLX register set space
- unsigned long me4000_regbase_size; // ME4000 register set space
+ resource_size_t me4000_regbase_size; // ME4000 register set space
unsigned long serial_no; // Serial number of the board
unsigned char hw_revision; // Hardware revision of the board
unsigned short vendor_id; // Meilhaus vendor id (0x1402)
@@ -773,62 +771,62 @@ typedef struct me4000_user_info {
int dio_count; // Count of digital I/O ports
int cnt_count; // Count of counters
-} me4000_user_info_t;
+};
/*-----------------------------------------------------------------------------
Type definitions for analog output
----------------------------------------------------------------------------*/
-typedef struct me4000_ao_channel_list {
+struct me4000_ao_channel_list {
unsigned long count;
unsigned long *list;
-} me4000_ao_channel_list_t;
+};
/*-----------------------------------------------------------------------------
Type definitions for analog input
----------------------------------------------------------------------------*/
-typedef struct me4000_ai_channel_list {
+struct me4000_ai_channel_list {
unsigned long count;
unsigned long *list;
-} me4000_ai_channel_list_t;
+};
-typedef struct me4000_ai_timer {
+struct me4000_ai_timer {
unsigned long pre_chan;
unsigned long chan;
unsigned long scan_low;
unsigned long scan_high;
-} me4000_ai_timer_t;
+};
-typedef struct me4000_ai_config {
- me4000_ai_timer_t timer;
- me4000_ai_channel_list_t channel_list;
+struct me4000_ai_config {
+ struct me4000_ai_timer timer;
+ struct me4000_ai_channel_list channel_list;
int sh;
-} me4000_ai_config_t;
+};
-typedef struct me4000_ai_single {
+struct me4000_ai_single {
int channel;
int range;
int mode;
short value;
unsigned long timeout;
-} me4000_ai_single_t;
+};
-typedef struct me4000_ai_trigger {
+struct me4000_ai_trigger {
int mode;
int edge;
-} me4000_ai_trigger_t;
+};
-typedef struct me4000_ai_sc {
+struct me4000_ai_sc {
unsigned long value;
int reload;
-} me4000_ai_sc_t;
+};
/*-----------------------------------------------------------------------------
Type definitions for eeprom
----------------------------------------------------------------------------*/
-typedef struct me4000_eeprom {
+struct me4000_eeprom {
unsigned long date;
short uni_10_offset;
short uni_10_fullscale;
@@ -842,45 +840,45 @@ typedef struct me4000_eeprom {
short diff_10_fullscale;
short diff_2_5_offset;
short diff_2_5_fullscale;
-} me4000_eeprom_t;
+};
/*-----------------------------------------------------------------------------
Type definitions for digital I/O
----------------------------------------------------------------------------*/
-typedef struct me4000_dio_config {
+struct me4000_dio_config {
int port;
int mode;
int function;
-} me4000_dio_config_t;
+};
-typedef struct me4000_dio_byte {
+struct me4000_dio_byte {
int port;
unsigned char byte;
-} me4000_dio_byte_t;
+};
/*-----------------------------------------------------------------------------
Type definitions for counters
----------------------------------------------------------------------------*/
-typedef struct me4000_cnt {
+struct me4000_cnt {
int counter;
unsigned short value;
-} me4000_cnt_t;
+};
-typedef struct me4000_cnt_config {
+struct me4000_cnt_config {
int counter;
int mode;
-} me4000_cnt_config_t;
+};
/*-----------------------------------------------------------------------------
Type definitions for external interrupt
----------------------------------------------------------------------------*/
-typedef struct {
+struct me4000_int {
int int1_count;
int int2_count;
-} me4000_int_type;
+};
/*-----------------------------------------------------------------------------
The ioctls of the board
@@ -888,7 +886,8 @@ typedef struct {
#define ME4000_IOCTL_MAXNR 50
#define ME4000_MAGIC 'y'
-#define ME4000_GET_USER_INFO _IOR (ME4000_MAGIC, 0, me4000_user_info_t)
+#define ME4000_GET_USER_INFO _IOR (ME4000_MAGIC, 0, \
+ struct me4000_user_info)
#define ME4000_AO_START _IOW (ME4000_MAGIC, 1, unsigned long)
#define ME4000_AO_STOP _IO (ME4000_MAGIC, 2)
@@ -904,25 +903,35 @@ typedef struct {
#define ME4000_AO_DISABLE_DO _IO (ME4000_MAGIC, 12)
#define ME4000_AO_FSM_STATE _IOR (ME4000_MAGIC, 13, int)
-#define ME4000_AI_SINGLE _IOR (ME4000_MAGIC, 14, me4000_ai_single_t)
+#define ME4000_AI_SINGLE _IOR (ME4000_MAGIC, 14, \
+ struct me4000_ai_single)
#define ME4000_AI_START _IOW (ME4000_MAGIC, 15, unsigned long)
#define ME4000_AI_STOP _IO (ME4000_MAGIC, 16)
#define ME4000_AI_IMMEDIATE_STOP _IO (ME4000_MAGIC, 17)
#define ME4000_AI_EX_TRIG_ENABLE _IO (ME4000_MAGIC, 18)
#define ME4000_AI_EX_TRIG_DISABLE _IO (ME4000_MAGIC, 19)
-#define ME4000_AI_EX_TRIG_SETUP _IOW (ME4000_MAGIC, 20, me4000_ai_trigger_t)
-#define ME4000_AI_CONFIG _IOW (ME4000_MAGIC, 21, me4000_ai_config_t)
-#define ME4000_AI_SC_SETUP _IOW (ME4000_MAGIC, 22, me4000_ai_sc_t)
+#define ME4000_AI_EX_TRIG_SETUP _IOW (ME4000_MAGIC, 20, \
+ struct me4000_ai_trigger)
+#define ME4000_AI_CONFIG _IOW (ME4000_MAGIC, 21, \
+ struct me4000_ai_config)
+#define ME4000_AI_SC_SETUP _IOW (ME4000_MAGIC, 22, \
+ struct me4000_ai_sc)
#define ME4000_AI_FSM_STATE _IOR (ME4000_MAGIC, 23, int)
-#define ME4000_DIO_CONFIG _IOW (ME4000_MAGIC, 24, me4000_dio_config_t)
-#define ME4000_DIO_GET_BYTE _IOR (ME4000_MAGIC, 25, me4000_dio_byte_t)
-#define ME4000_DIO_SET_BYTE _IOW (ME4000_MAGIC, 26, me4000_dio_byte_t)
+#define ME4000_DIO_CONFIG _IOW (ME4000_MAGIC, 24, \
+ struct me4000_dio_config)
+#define ME4000_DIO_GET_BYTE _IOR (ME4000_MAGIC, 25, \
+ struct me4000_dio_byte)
+#define ME4000_DIO_SET_BYTE _IOW (ME4000_MAGIC, 26, \
+ struct me4000_dio_byte)
#define ME4000_DIO_RESET _IO (ME4000_MAGIC, 27)
-#define ME4000_CNT_READ _IOR (ME4000_MAGIC, 28, me4000_cnt_t)
-#define ME4000_CNT_WRITE _IOW (ME4000_MAGIC, 29, me4000_cnt_t)
-#define ME4000_CNT_CONFIG _IOW (ME4000_MAGIC, 30, me4000_cnt_config_t)
+#define ME4000_CNT_READ _IOR (ME4000_MAGIC, 28, \
+ struct me4000_cnt)
+#define ME4000_CNT_WRITE _IOW (ME4000_MAGIC, 29, \
+ struct me4000_cnt)
+#define ME4000_CNT_CONFIG _IOW (ME4000_MAGIC, 30, \
+ struct me4000_cnt_config)
#define ME4000_CNT_RESET _IO (ME4000_MAGIC, 31)
#define ME4000_EXT_INT_DISABLE _IO (ME4000_MAGIC, 32)
@@ -934,13 +943,16 @@ typedef struct {
#define ME4000_AI_FULLSCALE_ENABLE _IO (ME4000_MAGIC, 37)
#define ME4000_AI_FULLSCALE_DISABLE _IO (ME4000_MAGIC, 38)
-#define ME4000_AI_EEPROM_READ _IOR (ME4000_MAGIC, 39, me4000_eeprom_t)
-#define ME4000_AI_EEPROM_WRITE _IOW (ME4000_MAGIC, 40, me4000_eeprom_t)
+#define ME4000_AI_EEPROM_READ _IOR (ME4000_MAGIC, 39, \
+ struct me4000_eeprom)
+#define ME4000_AI_EEPROM_WRITE _IOW (ME4000_MAGIC, 40, \
+ struct me4000_eeprom)
#define ME4000_AO_SIMULTANEOUS_EX_TRIG _IO (ME4000_MAGIC, 41)
#define ME4000_AO_SIMULTANEOUS_SW _IO (ME4000_MAGIC, 42)
#define ME4000_AO_SIMULTANEOUS_DISABLE _IO (ME4000_MAGIC, 43)
-#define ME4000_AO_SIMULTANEOUS_UPDATE _IOW (ME4000_MAGIC, 44, me4000_ao_channel_list_t)
+#define ME4000_AO_SIMULTANEOUS_UPDATE _IOW (ME4000_MAGIC, 44, \
+ struct me4000_ao_channel_list)
#define ME4000_AO_SYNCHRONOUS_EX_TRIG _IO (ME4000_MAGIC, 45)
#define ME4000_AO_SYNCHRONOUS_SW _IO (ME4000_MAGIC, 46)
diff --git a/drivers/staging/poch/Kconfig b/drivers/staging/poch/Kconfig
new file mode 100644
index 00000000000..b3b33b984a5
--- /dev/null
+++ b/drivers/staging/poch/Kconfig
@@ -0,0 +1,6 @@
+config POCH
+ tristate "Redrapids Pocket Change CardBus support"
+ depends on PCI && UIO
+ default N
+ ---help---
+ Enable support for Redrapids Pocket Change CardBus devices.
diff --git a/drivers/staging/poch/Makefile b/drivers/staging/poch/Makefile
new file mode 100644
index 00000000000..d2b96805cb9
--- /dev/null
+++ b/drivers/staging/poch/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_POCH) += poch.o
diff --git a/drivers/staging/poch/README b/drivers/staging/poch/README
new file mode 100644
index 00000000000..f65e979743b
--- /dev/null
+++ b/drivers/staging/poch/README
@@ -0,0 +1,7 @@
+TODO:
+ - fix transmit overflows
+ - audit userspace interfaces
+ - get reserved major/minor if needed
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
+Vijay Kumar <vijaykumar@bravegnu.org> and Jaya Kumar <jayakumar.lkml@gmail.com>
diff --git a/drivers/staging/poch/poch.c b/drivers/staging/poch/poch.c
new file mode 100644
index 00000000000..0e113f9a158
--- /dev/null
+++ b/drivers/staging/poch/poch.c
@@ -0,0 +1,1425 @@
+/*
+ * User-space DMA and UIO based Redrapids Pocket Change CardBus driver
+ *
+ * Copyright 2008 Vijay Kumar <vijaykumar@bravegnu.org>
+ *
+ * Licensed under GPL version 2 only.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+#include <linux/spinlock.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/poll.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/io.h>
+
+#include "poch.h"
+
+#include <asm/cacheflush.h>
+
+#ifndef PCI_VENDOR_ID_RRAPIDS
+#define PCI_VENDOR_ID_RRAPIDS 0x17D2
+#endif
+
+#ifndef PCI_DEVICE_ID_RRAPIDS_POCKET_CHANGE
+#define PCI_DEVICE_ID_RRAPIDS_POCKET_CHANGE 0x0351
+#endif
+
+#define POCH_NCHANNELS 2
+
+#define MAX_POCH_CARDS 8
+#define MAX_POCH_DEVICES (MAX_POCH_CARDS * POCH_NCHANNELS)
+
+#define DRV_NAME "poch"
+#define PFX DRV_NAME ": "
+
+/*
+ * BAR0 Bridge Register Definitions
+ */
+
+#define BRIDGE_REV_REG 0x0
+#define BRIDGE_INT_MASK_REG 0x4
+#define BRIDGE_INT_STAT_REG 0x8
+
+#define BRIDGE_INT_ACTIVE (0x1 << 31)
+#define BRIDGE_INT_FPGA (0x1 << 2)
+#define BRIDGE_INT_TEMP_FAIL (0x1 << 1)
+#define BRIDGE_INT_TEMP_WARN (0x1 << 0)
+
+#define BRIDGE_FPGA_RESET_REG 0xC
+
+#define BRIDGE_CARD_POWER_REG 0x10
+#define BRIDGE_CARD_POWER_EN (0x1 << 0)
+#define BRIDGE_CARD_POWER_PROG_DONE (0x1 << 31)
+
+#define BRIDGE_JTAG_REG 0x14
+#define BRIDGE_DMA_GO_REG 0x18
+#define BRIDGE_STAT_0_REG 0x1C
+#define BRIDGE_STAT_1_REG 0x20
+#define BRIDGE_STAT_2_REG 0x24
+#define BRIDGE_STAT_3_REG 0x28
+#define BRIDGE_TEMP_STAT_REG 0x2C
+#define BRIDGE_TEMP_THRESH_REG 0x30
+#define BRIDGE_EEPROM_REVSEL_REG 0x34
+#define BRIDGE_CIS_STRUCT_REG 0x100
+#define BRIDGE_BOARDREV_REG 0x124
+
+/*
+ * BAR1 FPGA Register Definitions
+ */
+
+#define FPGA_IFACE_REV_REG 0x0
+#define FPGA_RX_BLOCK_SIZE_REG 0x8
+#define FPGA_TX_BLOCK_SIZE_REG 0xC
+#define FPGA_RX_BLOCK_COUNT_REG 0x10
+#define FPGA_TX_BLOCK_COUNT_REG 0x14
+#define FPGA_RX_CURR_DMA_BLOCK_REG 0x18
+#define FPGA_TX_CURR_DMA_BLOCK_REG 0x1C
+#define FPGA_RX_GROUP_COUNT_REG 0x20
+#define FPGA_TX_GROUP_COUNT_REG 0x24
+#define FPGA_RX_CURR_GROUP_REG 0x28
+#define FPGA_TX_CURR_GROUP_REG 0x2C
+#define FPGA_RX_CURR_PCI_REG 0x38
+#define FPGA_TX_CURR_PCI_REG 0x3C
+#define FPGA_RX_GROUP0_START_REG 0x40
+#define FPGA_TX_GROUP0_START_REG 0xC0
+#define FPGA_DMA_DESC_1_REG 0x140
+#define FPGA_DMA_DESC_2_REG 0x144
+#define FPGA_DMA_DESC_3_REG 0x148
+#define FPGA_DMA_DESC_4_REG 0x14C
+
+#define FPGA_DMA_INT_STAT_REG 0x150
+#define FPGA_DMA_INT_MASK_REG 0x154
+#define FPGA_DMA_INT_RX (1 << 0)
+#define FPGA_DMA_INT_TX (1 << 1)
+
+#define FPGA_RX_GROUPS_PER_INT_REG 0x158
+#define FPGA_TX_GROUPS_PER_INT_REG 0x15C
+#define FPGA_DMA_ADR_PAGE_REG 0x160
+#define FPGA_FPGA_REV_REG 0x200
+
+#define FPGA_ADC_CLOCK_CTL_REG 0x204
+#define FPGA_ADC_CLOCK_CTL_OSC_EN (0x1 << 3)
+#define FPGA_ADC_CLOCK_LOCAL_CLK (0x1 | FPGA_ADC_CLOCK_CTL_OSC_EN)
+#define FPGA_ADC_CLOCK_EXT_SAMP_CLK 0X0
+
+#define FPGA_ADC_DAC_EN_REG 0x208
+#define FPGA_ADC_DAC_EN_DAC_OFF (0x1 << 1)
+#define FPGA_ADC_DAC_EN_ADC_OFF (0x1 << 0)
+
+#define FPGA_INT_STAT_REG 0x20C
+#define FPGA_INT_MASK_REG 0x210
+#define FPGA_INT_PLL_UNLOCKED (0x1 << 9)
+#define FPGA_INT_DMA_CORE (0x1 << 8)
+#define FPGA_INT_TX_FF_EMPTY (0x1 << 7)
+#define FPGA_INT_RX_FF_EMPTY (0x1 << 6)
+#define FPGA_INT_TX_FF_OVRFLW (0x1 << 3)
+#define FPGA_INT_RX_FF_OVRFLW (0x1 << 2)
+#define FPGA_INT_TX_ACQ_DONE (0x1 << 1)
+#define FPGA_INT_RX_ACQ_DONE (0x1)
+
+#define FPGA_RX_ADC_CTL_REG 0x214
+#define FPGA_RX_ADC_CTL_CONT_CAP (0x0)
+#define FPGA_RX_ADC_CTL_SNAP_CAP (0x1)
+
+#define FPGA_RX_ARM_REG 0x21C
+
+#define FPGA_DOM_REG 0x224
+#define FPGA_DOM_DCM_RESET (0x1 << 5)
+#define FPGA_DOM_SOFT_RESET (0x1 << 4)
+#define FPGA_DOM_DUAL_M_SG_DMA (0x0)
+#define FPGA_DOM_TARGET_ACCESS (0x1)
+
+#define FPGA_TX_CTL_REG 0x228
+#define FPGA_TX_CTL_FIFO_FLUSH (0x1 << 9)
+#define FPGA_TX_CTL_OUTPUT_ZERO (0x0 << 2)
+#define FPGA_TX_CTL_OUTPUT_CARDBUS (0x1 << 2)
+#define FPGA_TX_CTL_OUTPUT_ADC (0x2 << 2)
+#define FPGA_TX_CTL_OUTPUT_SNAPSHOT (0x3 << 2)
+#define FPGA_TX_CTL_LOOPBACK (0x1 << 0)
+
+#define FPGA_ENDIAN_MODE_REG 0x22C
+#define FPGA_RX_FIFO_COUNT_REG 0x28C
+#define FPGA_TX_ENABLE_REG 0x298
+#define FPGA_TX_TRIGGER_REG 0x29C
+#define FPGA_TX_DATAMEM_COUNT_REG 0x2A8
+#define FPGA_CAP_FIFO_REG 0x300
+#define FPGA_TX_SNAPSHOT_REG 0x8000
+
+/*
+ * Channel Index Definitions
+ */
+
+enum {
+ CHNO_RX_CHANNEL,
+ CHNO_TX_CHANNEL,
+};
+
+struct poch_dev;
+
+enum channel_dir {
+ CHANNEL_DIR_RX,
+ CHANNEL_DIR_TX,
+};
+
+struct poch_group_info {
+ struct page *pg;
+ dma_addr_t dma_addr;
+ unsigned long user_offset;
+};
+
+struct channel_info {
+ unsigned int chno;
+
+ atomic_t sys_block_size;
+ atomic_t sys_group_size;
+ atomic_t sys_group_count;
+
+ enum channel_dir dir;
+
+ unsigned long block_size;
+ unsigned long group_size;
+ unsigned long group_count;
+
+ /* Contains the DMA address and VM offset of each group. */
+ struct poch_group_info *groups;
+
+ /* Contains the header and circular buffer exported to userspace. */
+ spinlock_t group_offsets_lock;
+ struct poch_cbuf_header *header;
+ struct page *header_pg;
+ unsigned long header_size;
+
+ /* Last group indicated as 'complete' to user space. */
+ unsigned int transfer;
+
+ wait_queue_head_t wq;
+
+ union {
+ unsigned int data_available;
+ unsigned int space_available;
+ };
+
+ void __iomem *bridge_iomem;
+ void __iomem *fpga_iomem;
+ spinlock_t *iomem_lock;
+
+ atomic_t free;
+ atomic_t inited;
+
+ /* Error counters */
+ struct poch_counters counters;
+ spinlock_t counters_lock;
+
+ struct device *dev;
+};
+
+struct poch_dev {
+ struct uio_info uio;
+ struct pci_dev *pci_dev;
+ unsigned int nchannels;
+ struct channel_info channels[POCH_NCHANNELS];
+ struct cdev cdev;
+
+ /* Counts the no. of channels that have been opened. On first
+ * open, the card is powered on. On last channel close, the
+ * card is powered off.
+ */
+ atomic_t usage;
+
+ void __iomem *bridge_iomem;
+ void __iomem *fpga_iomem;
+ spinlock_t iomem_lock;
+
+ struct device *dev;
+};
+
+static dev_t poch_first_dev;
+static struct class *poch_cls;
+static DEFINE_IDR(poch_ids);
+
+static ssize_t store_block_size(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct channel_info *channel = dev_get_drvdata(dev);
+ unsigned long block_size;
+
+ sscanf(buf, "%lu", &block_size);
+ atomic_set(&channel->sys_block_size, block_size);
+
+ return count;
+}
+static DEVICE_ATTR(block_size, S_IWUSR|S_IWGRP, NULL, store_block_size);
+
+static ssize_t store_group_size(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct channel_info *channel = dev_get_drvdata(dev);
+ unsigned long group_size;
+
+ sscanf(buf, "%lu", &group_size);
+ atomic_set(&channel->sys_group_size, group_size);
+
+ return count;
+}
+static DEVICE_ATTR(group_size, S_IWUSR|S_IWGRP, NULL, store_group_size);
+
+static ssize_t store_group_count(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct channel_info *channel = dev_get_drvdata(dev);
+ unsigned long group_count;
+
+ sscanf(buf, "%lu", &group_count);
+ atomic_set(&channel->sys_group_count, group_count);
+
+ return count;
+}
+static DEVICE_ATTR(group_count, S_IWUSR|S_IWGRP, NULL, store_group_count);
+
+static ssize_t show_direction(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct channel_info *channel = dev_get_drvdata(dev);
+ int len;
+
+ len = sprintf(buf, "%s\n", (channel->dir ? "tx" : "rx"));
+ return len;
+}
+static DEVICE_ATTR(dir, S_IRUSR|S_IRGRP, show_direction, NULL);
+
+static ssize_t show_mmap_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct channel_info *channel = dev_get_drvdata(dev);
+ int len;
+ unsigned long mmap_size;
+ unsigned long group_pages;
+ unsigned long header_pages;
+ unsigned long total_group_pages;
+
+ /* FIXME: We do not have to add 1, if group_size a multiple of
+ PAGE_SIZE. */
+ group_pages = (channel->group_size / PAGE_SIZE) + 1;
+ header_pages = (channel->header_size / PAGE_SIZE) + 1;
+ total_group_pages = group_pages * channel->group_count;
+
+ mmap_size = (header_pages + total_group_pages) * PAGE_SIZE;
+ len = sprintf(buf, "%lu\n", mmap_size);
+ return len;
+}
+static DEVICE_ATTR(mmap_size, S_IRUSR|S_IRGRP, show_mmap_size, NULL);
+
+static struct device_attribute *poch_class_attrs[] = {
+ &dev_attr_block_size,
+ &dev_attr_group_size,
+ &dev_attr_group_count,
+ &dev_attr_dir,
+ &dev_attr_mmap_size,
+};
+
+static void poch_channel_free_groups(struct channel_info *channel)
+{
+ unsigned long i;
+
+ for (i = 0; i < channel->group_count; i++) {
+ struct poch_group_info *group;
+ unsigned int order;
+
+ group = &channel->groups[i];
+ order = get_order(channel->group_size);
+ if (group->pg)
+ __free_pages(group->pg, order);
+ }
+}
+
+static int poch_channel_alloc_groups(struct channel_info *channel)
+{
+ unsigned long i;
+ unsigned long group_pages;
+ unsigned long header_pages;
+
+ group_pages = (channel->group_size / PAGE_SIZE) + 1;
+ header_pages = (channel->header_size / PAGE_SIZE) + 1;
+
+ for (i = 0; i < channel->group_count; i++) {
+ struct poch_group_info *group;
+ unsigned int order;
+ gfp_t gfp_mask;
+
+ group = &channel->groups[i];
+ order = get_order(channel->group_size);
+
+ /*
+ * __GFP_COMP is required here since we are going to
+ * perform non-linear mapping to userspace. For more
+ * information read the vm_insert_page() function
+ * comments.
+ */
+
+ gfp_mask = GFP_KERNEL | GFP_DMA32 | __GFP_ZERO;
+ group->pg = alloc_pages(gfp_mask, order);
+ if (!group->pg) {
+ poch_channel_free_groups(channel);
+ return -ENOMEM;
+ }
+
+ /* FIXME: This is the physical address not the bus
+ * address! This won't work in architectures that
+ * have an IOMMU. Can we use pci_map_single() for
+ * this?
+ */
+ group->dma_addr = page_to_pfn(group->pg) * PAGE_SIZE;
+ group->user_offset =
+ (header_pages + (i * group_pages)) * PAGE_SIZE;
+
+ printk(KERN_INFO PFX "%ld: user_offset: 0x%lx dma: 0x%x\n", i,
+ group->user_offset, group->dma_addr);
+ }
+
+ return 0;
+}
+
+static void channel_latch_attr(struct channel_info *channel)
+{
+ channel->group_count = atomic_read(&channel->sys_group_count);
+ channel->group_size = atomic_read(&channel->sys_group_size);
+ channel->block_size = atomic_read(&channel->sys_block_size);
+}
+
+/*
+ * Configure DMA group registers
+ */
+static void channel_dma_init(struct channel_info *channel)
+{
+ void __iomem *fpga = channel->fpga_iomem;
+ u32 group_regs_base;
+ u32 group_reg;
+ unsigned int page;
+ unsigned int group_in_page;
+ unsigned long i;
+ u32 block_size_reg;
+ u32 block_count_reg;
+ u32 group_count_reg;
+ u32 groups_per_int_reg;
+ u32 curr_pci_reg;
+
+ if (channel->chno == CHNO_RX_CHANNEL) {
+ group_regs_base = FPGA_RX_GROUP0_START_REG;
+ block_size_reg = FPGA_RX_BLOCK_SIZE_REG;
+ block_count_reg = FPGA_RX_BLOCK_COUNT_REG;
+ group_count_reg = FPGA_RX_GROUP_COUNT_REG;
+ groups_per_int_reg = FPGA_RX_GROUPS_PER_INT_REG;
+ curr_pci_reg = FPGA_RX_CURR_PCI_REG;
+ } else {
+ group_regs_base = FPGA_TX_GROUP0_START_REG;
+ block_size_reg = FPGA_TX_BLOCK_SIZE_REG;
+ block_count_reg = FPGA_TX_BLOCK_COUNT_REG;
+ group_count_reg = FPGA_TX_GROUP_COUNT_REG;
+ groups_per_int_reg = FPGA_TX_GROUPS_PER_INT_REG;
+ curr_pci_reg = FPGA_TX_CURR_PCI_REG;
+ }
+
+ printk(KERN_WARNING "block_size, group_size, group_count\n");
+ iowrite32(channel->block_size, fpga + block_size_reg);
+ iowrite32(channel->group_size / channel->block_size,
+ fpga + block_count_reg);
+ iowrite32(channel->group_count, fpga + group_count_reg);
+ /* FIXME: Hardcoded groups per int. Get it from sysfs? */
+ iowrite32(1, fpga + groups_per_int_reg);
+
+ /* Unlock PCI address? Not defined in the data sheet, but used
+ * in the reference code by Redrapids.
+ */
+ iowrite32(0x1, fpga + curr_pci_reg);
+
+ /* The DMA address page register is shared between the RX and
+ * TX channels, so acquire lock.
+ */
+ spin_lock(channel->iomem_lock);
+ for (i = 0; i < channel->group_count; i++) {
+ page = i / 32;
+ group_in_page = i % 32;
+
+ group_reg = group_regs_base + (group_in_page * 4);
+
+ iowrite32(page, fpga + FPGA_DMA_ADR_PAGE_REG);
+ iowrite32(channel->groups[i].dma_addr, fpga + group_reg);
+ }
+ for (i = 0; i < channel->group_count; i++) {
+ page = i / 32;
+ group_in_page = i % 32;
+
+ group_reg = group_regs_base + (group_in_page * 4);
+
+ iowrite32(page, fpga + FPGA_DMA_ADR_PAGE_REG);
+ printk(KERN_INFO PFX "%ld: read dma_addr: 0x%x\n", i,
+ ioread32(fpga + group_reg));
+ }
+ spin_unlock(channel->iomem_lock);
+
+}
+
+static int poch_channel_alloc_header(struct channel_info *channel)
+{
+ struct poch_cbuf_header *header = channel->header;
+ unsigned long group_offset_size;
+ unsigned long tot_group_offsets_size;
+
+ /* Allocate memory to hold header exported userspace */
+ group_offset_size = sizeof(header->group_offsets[0]);
+ tot_group_offsets_size = group_offset_size * channel->group_count;
+ channel->header_size = sizeof(*header) + tot_group_offsets_size;
+ channel->header_pg = alloc_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(channel->header_size));
+ if (!channel->header_pg)
+ return -ENOMEM;
+
+ channel->header = page_address(channel->header_pg);
+
+ return 0;
+}
+
+static void poch_channel_free_header(struct channel_info *channel)
+{
+ unsigned int order;
+
+ order = get_order(channel->header_size);
+ __free_pages(channel->header_pg, order);
+}
+
+static void poch_channel_init_header(struct channel_info *channel)
+{
+ int i;
+ struct poch_group_info *groups;
+ s32 *group_offsets;
+
+ channel->header->group_size_bytes = channel->group_size;
+ channel->header->group_count = channel->group_count;
+
+ spin_lock_init(&channel->group_offsets_lock);
+
+ group_offsets = channel->header->group_offsets;
+ groups = channel->groups;
+
+ for (i = 0; i < channel->group_count; i++) {
+ if (channel->dir == CHANNEL_DIR_RX)
+ group_offsets[i] = -1;
+ else
+ group_offsets[i] = groups[i].user_offset;
+ }
+}
+
+static void __poch_channel_clear_counters(struct channel_info *channel)
+{
+ channel->counters.pll_unlock = 0;
+ channel->counters.fifo_empty = 0;
+ channel->counters.fifo_overflow = 0;
+}
+
+static int poch_channel_init(struct channel_info *channel,
+ struct poch_dev *poch_dev)
+{
+ struct pci_dev *pdev = poch_dev->pci_dev;
+ struct device *dev = &pdev->dev;
+ unsigned long alloc_size;
+ int ret;
+
+ printk(KERN_WARNING "channel_latch_attr\n");
+
+ channel_latch_attr(channel);
+
+ channel->transfer = 0;
+
+ /* Allocate memory to hold group information. */
+ alloc_size = channel->group_count * sizeof(struct poch_group_info);
+ channel->groups = kzalloc(alloc_size, GFP_KERNEL);
+ if (!channel->groups) {
+ dev_err(dev, "error allocating memory for group info\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ printk(KERN_WARNING "poch_channel_alloc_groups\n");
+
+ ret = poch_channel_alloc_groups(channel);
+ if (ret) {
+ dev_err(dev, "error allocating groups of order %d\n",
+ get_order(channel->group_size));
+ goto out_free_group_info;
+ }
+
+ ret = poch_channel_alloc_header(channel);
+ if (ret) {
+ dev_err(dev, "error allocating user space header\n");
+ goto out_free_groups;
+ }
+
+ channel->fpga_iomem = poch_dev->fpga_iomem;
+ channel->bridge_iomem = poch_dev->bridge_iomem;
+ channel->iomem_lock = &poch_dev->iomem_lock;
+ spin_lock_init(&channel->counters_lock);
+
+ __poch_channel_clear_counters(channel);
+
+ printk(KERN_WARNING "poch_channel_init_header\n");
+
+ poch_channel_init_header(channel);
+
+ return 0;
+
+ out_free_groups:
+ poch_channel_free_groups(channel);
+ out_free_group_info:
+ kfree(channel->groups);
+ out:
+ return ret;
+}
+
+static int poch_wait_fpga_prog(void __iomem *bridge)
+{
+ unsigned long total_wait;
+ const unsigned long wait_period = 100;
+ /* FIXME: Get the actual timeout */
+ const unsigned long prog_timeo = 10000; /* 10 Seconds */
+ u32 card_power;
+
+ printk(KERN_WARNING "poch_wait_fpg_prog\n");
+
+ printk(KERN_INFO PFX "programming fpga ...\n");
+ total_wait = 0;
+ while (1) {
+ msleep(wait_period);
+ total_wait += wait_period;
+
+ card_power = ioread32(bridge + BRIDGE_CARD_POWER_REG);
+ if (card_power & BRIDGE_CARD_POWER_PROG_DONE) {
+ printk(KERN_INFO PFX "programming done\n");
+ return 0;
+ }
+ if (total_wait > prog_timeo) {
+ printk(KERN_ERR PFX
+ "timed out while programming FPGA\n");
+ return -EIO;
+ }
+ }
+}
+
+static void poch_card_power_off(struct poch_dev *poch_dev)
+{
+ void __iomem *bridge = poch_dev->bridge_iomem;
+ u32 card_power;
+
+ iowrite32(0, bridge + BRIDGE_INT_MASK_REG);
+ iowrite32(0, bridge + BRIDGE_DMA_GO_REG);
+
+ card_power = ioread32(bridge + BRIDGE_CARD_POWER_REG);
+ iowrite32(card_power & ~BRIDGE_CARD_POWER_EN,
+ bridge + BRIDGE_CARD_POWER_REG);
+}
+
+enum clk_src {
+ CLK_SRC_ON_BOARD,
+ CLK_SRC_EXTERNAL
+};
+
+static void poch_card_clock_on(void __iomem *fpga)
+{
+ /* FIXME: Get this data through sysfs? */
+ enum clk_src clk_src = CLK_SRC_ON_BOARD;
+
+ if (clk_src == CLK_SRC_ON_BOARD) {
+ iowrite32(FPGA_ADC_CLOCK_LOCAL_CLK | FPGA_ADC_CLOCK_CTL_OSC_EN,
+ fpga + FPGA_ADC_CLOCK_CTL_REG);
+ } else if (clk_src == CLK_SRC_EXTERNAL) {
+ iowrite32(FPGA_ADC_CLOCK_EXT_SAMP_CLK,
+ fpga + FPGA_ADC_CLOCK_CTL_REG);
+ }
+}
+
+static int poch_card_power_on(struct poch_dev *poch_dev)
+{
+ void __iomem *bridge = poch_dev->bridge_iomem;
+ void __iomem *fpga = poch_dev->fpga_iomem;
+
+ iowrite32(BRIDGE_CARD_POWER_EN, bridge + BRIDGE_CARD_POWER_REG);
+
+ if (poch_wait_fpga_prog(bridge) != 0) {
+ poch_card_power_off(poch_dev);
+ return -EIO;
+ }
+
+ poch_card_clock_on(fpga);
+
+ /* Sync to new clock, reset state machines, set DMA mode. */
+ iowrite32(FPGA_DOM_DCM_RESET | FPGA_DOM_SOFT_RESET
+ | FPGA_DOM_DUAL_M_SG_DMA, fpga + FPGA_DOM_REG);
+
+ /* FIXME: The time required for sync. needs to be tuned. */
+ msleep(1000);
+
+ return 0;
+}
+
+static void poch_channel_analog_on(struct channel_info *channel)
+{
+ void __iomem *fpga = channel->fpga_iomem;
+ u32 adc_dac_en;
+
+ spin_lock(channel->iomem_lock);
+ adc_dac_en = ioread32(fpga + FPGA_ADC_DAC_EN_REG);
+ switch (channel->chno) {
+ case CHNO_RX_CHANNEL:
+ iowrite32(adc_dac_en & ~FPGA_ADC_DAC_EN_ADC_OFF,
+ fpga + FPGA_ADC_DAC_EN_REG);
+ break;
+ case CHNO_TX_CHANNEL:
+ iowrite32(adc_dac_en & ~FPGA_ADC_DAC_EN_DAC_OFF,
+ fpga + FPGA_ADC_DAC_EN_REG);
+ break;
+ }
+ spin_unlock(channel->iomem_lock);
+}
+
+static int poch_open(struct inode *inode, struct file *filp)
+{
+ struct poch_dev *poch_dev;
+ struct channel_info *channel;
+ void __iomem *bridge;
+ void __iomem *fpga;
+ int chno;
+ int usage;
+ int ret;
+
+ poch_dev = container_of(inode->i_cdev, struct poch_dev, cdev);
+ bridge = poch_dev->bridge_iomem;
+ fpga = poch_dev->fpga_iomem;
+
+ chno = iminor(inode) % poch_dev->nchannels;
+ channel = &poch_dev->channels[chno];
+
+ if (!atomic_dec_and_test(&channel->free)) {
+ atomic_inc(&channel->free);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ usage = atomic_inc_return(&poch_dev->usage);
+
+ printk(KERN_WARNING "poch_card_power_on\n");
+
+ if (usage == 1) {
+ ret = poch_card_power_on(poch_dev);
+ if (ret)
+ goto out_dec_usage;
+ }
+
+ printk(KERN_INFO "CardBus Bridge Revision: %x\n",
+ ioread32(bridge + BRIDGE_REV_REG));
+ printk(KERN_INFO "CardBus Interface Revision: %x\n",
+ ioread32(fpga + FPGA_IFACE_REV_REG));
+
+ channel->chno = chno;
+ filp->private_data = channel;
+
+ printk(KERN_WARNING "poch_channel_init\n");
+
+ ret = poch_channel_init(channel, poch_dev);
+ if (ret)
+ goto out_power_off;
+
+ poch_channel_analog_on(channel);
+
+ printk(KERN_WARNING "channel_dma_init\n");
+
+ channel_dma_init(channel);
+
+ printk(KERN_WARNING "poch_channel_analog_on\n");
+
+ if (usage == 1) {
+ printk(KERN_WARNING "setting up DMA\n");
+
+ /* Initialize DMA Controller. */
+ iowrite32(FPGA_CAP_FIFO_REG, bridge + BRIDGE_STAT_2_REG);
+ iowrite32(FPGA_DMA_DESC_1_REG, bridge + BRIDGE_STAT_3_REG);
+
+ ioread32(fpga + FPGA_DMA_INT_STAT_REG);
+ ioread32(fpga + FPGA_INT_STAT_REG);
+ ioread32(bridge + BRIDGE_INT_STAT_REG);
+
+ /* Initialize Interrupts. FIXME: Enable temperature
+ * handling We are enabling both Tx and Rx channel
+ * interrupts here. Do we need to enable interrupts
+ * only for the current channel? Anyways we won't get
+ * the interrupt unless the DMA is activated.
+ */
+ iowrite32(BRIDGE_INT_FPGA, bridge + BRIDGE_INT_MASK_REG);
+ iowrite32(FPGA_INT_DMA_CORE
+ | FPGA_INT_PLL_UNLOCKED
+ | FPGA_INT_TX_FF_EMPTY
+ | FPGA_INT_RX_FF_EMPTY
+ | FPGA_INT_TX_FF_OVRFLW
+ | FPGA_INT_RX_FF_OVRFLW,
+ fpga + FPGA_INT_MASK_REG);
+ iowrite32(FPGA_DMA_INT_RX | FPGA_DMA_INT_TX,
+ fpga + FPGA_DMA_INT_MASK_REG);
+ }
+
+ if (channel->dir == CHANNEL_DIR_TX) {
+ /* Flush TX FIFO and output data from cardbus. */
+ iowrite32(FPGA_TX_CTL_FIFO_FLUSH
+ | FPGA_TX_CTL_OUTPUT_CARDBUS,
+ fpga + FPGA_TX_CTL_REG);
+ }
+
+ atomic_inc(&channel->inited);
+
+ return 0;
+
+ out_power_off:
+ if (usage == 1)
+ poch_card_power_off(poch_dev);
+ out_dec_usage:
+ atomic_dec(&poch_dev->usage);
+ atomic_inc(&channel->free);
+ out:
+ return ret;
+}
+
+static int poch_release(struct inode *inode, struct file *filp)
+{
+ struct channel_info *channel = filp->private_data;
+ struct poch_dev *poch_dev;
+ int usage;
+
+ poch_dev = container_of(inode->i_cdev, struct poch_dev, cdev);
+
+ usage = atomic_dec_return(&poch_dev->usage);
+ if (usage == 0) {
+ printk(KERN_WARNING "poch_card_power_off\n");
+ poch_card_power_off(poch_dev);
+ }
+
+ atomic_dec(&channel->inited);
+ poch_channel_free_header(channel);
+ poch_channel_free_groups(channel);
+ kfree(channel->groups);
+ atomic_inc(&channel->free);
+
+ return 0;
+}
+
+/*
+ * Map the header and the group buffers, to user space.
+ */
+static int poch_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct channel_info *channel = filp->private_data;
+
+ unsigned long start;
+ unsigned long size;
+
+ unsigned long group_pages;
+ unsigned long header_pages;
+ unsigned long total_group_pages;
+
+ int pg_num;
+ struct page *pg;
+
+ int i;
+ int ret;
+
+ printk(KERN_WARNING "poch_mmap\n");
+
+ if (vma->vm_pgoff) {
+ printk(KERN_WARNING PFX "page offset: %lu\n", vma->vm_pgoff);
+ return -EINVAL;
+ }
+
+ group_pages = (channel->group_size / PAGE_SIZE) + 1;
+ header_pages = (channel->header_size / PAGE_SIZE) + 1;
+ total_group_pages = group_pages * channel->group_count;
+
+ size = vma->vm_end - vma->vm_start;
+ if (size != (header_pages + total_group_pages) * PAGE_SIZE) {
+ printk(KERN_WARNING PFX "required %lu bytes\n", size);
+ return -EINVAL;
+ }
+
+ start = vma->vm_start;
+
+ /* FIXME: Cleanup required on failure? */
+ pg = channel->header_pg;
+ for (pg_num = 0; pg_num < header_pages; pg_num++, pg++) {
+ printk(KERN_DEBUG PFX "page_count: %d\n", page_count(pg));
+ printk(KERN_DEBUG PFX "%d: header: 0x%lx\n", pg_num, start);
+ ret = vm_insert_page(vma, start, pg);
+ if (ret) {
+ printk(KERN_DEBUG "vm_insert 1 failed at %lx\n", start);
+ return ret;
+ }
+ start += PAGE_SIZE;
+ }
+
+ for (i = 0; i < channel->group_count; i++) {
+ pg = channel->groups[i].pg;
+ for (pg_num = 0; pg_num < group_pages; pg_num++, pg++) {
+ printk(KERN_DEBUG PFX "%d: group %d: 0x%lx\n",
+ pg_num, i, start);
+ ret = vm_insert_page(vma, start, pg);
+ if (ret) {
+ printk(KERN_DEBUG PFX
+ "vm_insert 2 failed at %d\n", pg_num);
+ return ret;
+ }
+ start += PAGE_SIZE;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Check whether there is some group that the user space has not
+ * consumed yet. When the user space consumes a group, it sets it to
+ * -1. Cosuming could be reading data in case of RX and filling a
+ * buffer in case of TX.
+ */
+static int poch_channel_available(struct channel_info *channel)
+{
+ int i;
+
+ spin_lock_irq(&channel->group_offsets_lock);
+
+ for (i = 0; i < channel->group_count; i++) {
+ if (channel->dir == CHANNEL_DIR_RX
+ && channel->header->group_offsets[i] == -1) {
+ spin_unlock_irq(&channel->group_offsets_lock);
+ return 1;
+ }
+
+ if (channel->dir == CHANNEL_DIR_TX
+ && channel->header->group_offsets[i] != -1) {
+ spin_unlock_irq(&channel->group_offsets_lock);
+ return 1;
+ }
+ }
+
+ spin_unlock_irq(&channel->group_offsets_lock);
+
+ return 0;
+}
+
+static unsigned int poch_poll(struct file *filp, poll_table *pt)
+{
+ struct channel_info *channel = filp->private_data;
+ unsigned int ret = 0;
+
+ poll_wait(filp, &channel->wq, pt);
+
+ if (poch_channel_available(channel)) {
+ if (channel->dir == CHANNEL_DIR_RX)
+ ret = POLLIN | POLLRDNORM;
+ else
+ ret = POLLOUT | POLLWRNORM;
+ }
+
+ return ret;
+}
+
+static int poch_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct channel_info *channel = filp->private_data;
+ void __iomem *fpga = channel->fpga_iomem;
+ void __iomem *bridge = channel->bridge_iomem;
+ void __user *argp = (void __user *)arg;
+ struct vm_area_struct *vms;
+ struct poch_counters counters;
+ int ret;
+
+ switch (cmd) {
+ case POCH_IOC_TRANSFER_START:
+ switch (channel->chno) {
+ case CHNO_TX_CHANNEL:
+ printk(KERN_INFO PFX "ioctl: Tx start\n");
+ iowrite32(0x1, fpga + FPGA_TX_TRIGGER_REG);
+ iowrite32(0x1, fpga + FPGA_TX_ENABLE_REG);
+
+ /* FIXME: Does it make sense to do a DMA GO
+ * twice, once in Tx and once in Rx.
+ */
+ iowrite32(0x1, bridge + BRIDGE_DMA_GO_REG);
+ break;
+ case CHNO_RX_CHANNEL:
+ printk(KERN_INFO PFX "ioctl: Rx start\n");
+ iowrite32(0x1, fpga + FPGA_RX_ARM_REG);
+ iowrite32(0x1, bridge + BRIDGE_DMA_GO_REG);
+ break;
+ }
+ break;
+ case POCH_IOC_TRANSFER_STOP:
+ switch (channel->chno) {
+ case CHNO_TX_CHANNEL:
+ printk(KERN_INFO PFX "ioctl: Tx stop\n");
+ iowrite32(0x0, fpga + FPGA_TX_ENABLE_REG);
+ iowrite32(0x0, fpga + FPGA_TX_TRIGGER_REG);
+ iowrite32(0x0, bridge + BRIDGE_DMA_GO_REG);
+ break;
+ case CHNO_RX_CHANNEL:
+ printk(KERN_INFO PFX "ioctl: Rx stop\n");
+ iowrite32(0x0, fpga + FPGA_RX_ARM_REG);
+ iowrite32(0x0, bridge + BRIDGE_DMA_GO_REG);
+ break;
+ }
+ break;
+ case POCH_IOC_GET_COUNTERS:
+ if (access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters)))
+ return -EFAULT;
+
+ spin_lock_irq(&channel->counters_lock);
+ counters = channel->counters;
+ __poch_channel_clear_counters(channel);
+ spin_unlock_irq(&channel->counters_lock);
+
+ ret = copy_to_user(argp, &counters,
+ sizeof(struct poch_counters));
+ if (ret)
+ return ret;
+
+ break;
+ case POCH_IOC_SYNC_GROUP_FOR_USER:
+ case POCH_IOC_SYNC_GROUP_FOR_DEVICE:
+ vms = find_vma(current->mm, arg);
+ if (!vms)
+ /* Address not mapped. */
+ return -EINVAL;
+ if (vms->vm_file != filp)
+ /* Address mapped from different device/file. */
+ return -EINVAL;
+
+ flush_cache_range(vms, arg, arg + channel->group_size);
+ break;
+ }
+ return 0;
+}
+
+static struct file_operations poch_fops = {
+ .owner = THIS_MODULE,
+ .open = poch_open,
+ .release = poch_release,
+ .ioctl = poch_ioctl,
+ .poll = poch_poll,
+ .mmap = poch_mmap
+};
+
+static void poch_irq_dma(struct channel_info *channel)
+{
+ u32 prev_transfer;
+ u32 curr_transfer;
+ long groups_done;
+ unsigned long i, j;
+ struct poch_group_info *groups;
+ s32 *group_offsets;
+ u32 curr_group_reg;
+
+ if (!atomic_read(&channel->inited))
+ return;
+
+ prev_transfer = channel->transfer;
+
+ if (channel->chno == CHNO_RX_CHANNEL)
+ curr_group_reg = FPGA_RX_CURR_GROUP_REG;
+ else
+ curr_group_reg = FPGA_TX_CURR_GROUP_REG;
+
+ curr_transfer = ioread32(channel->fpga_iomem + curr_group_reg);
+
+ groups_done = curr_transfer - prev_transfer;
+ /* Check wrap over, and handle it. */
+ if (groups_done <= 0)
+ groups_done += channel->group_count;
+
+ group_offsets = channel->header->group_offsets;
+ groups = channel->groups;
+
+ spin_lock(&channel->group_offsets_lock);
+
+ for (i = 0; i < groups_done; i++) {
+ j = (prev_transfer + i) % channel->group_count;
+ if (channel->dir == CHANNEL_DIR_RX)
+ group_offsets[j] = -1;
+ else
+ group_offsets[j] = groups[j].user_offset;
+ }
+
+ spin_unlock(&channel->group_offsets_lock);
+
+ channel->transfer = curr_transfer;
+
+ wake_up_interruptible(&channel->wq);
+}
+
+static irqreturn_t poch_irq_handler(int irq, void *p)
+{
+ struct poch_dev *poch_dev = p;
+ void __iomem *bridge = poch_dev->bridge_iomem;
+ void __iomem *fpga = poch_dev->fpga_iomem;
+ struct channel_info *channel_rx = &poch_dev->channels[CHNO_RX_CHANNEL];
+ struct channel_info *channel_tx = &poch_dev->channels[CHNO_TX_CHANNEL];
+ u32 bridge_stat;
+ u32 fpga_stat;
+ u32 dma_stat;
+
+ bridge_stat = ioread32(bridge + BRIDGE_INT_STAT_REG);
+ fpga_stat = ioread32(fpga + FPGA_INT_STAT_REG);
+ dma_stat = ioread32(fpga + FPGA_DMA_INT_STAT_REG);
+
+ ioread32(fpga + FPGA_DMA_INT_STAT_REG);
+ ioread32(fpga + FPGA_INT_STAT_REG);
+ ioread32(bridge + BRIDGE_INT_STAT_REG);
+
+ if (bridge_stat & BRIDGE_INT_FPGA) {
+ if (fpga_stat & FPGA_INT_DMA_CORE) {
+ if (dma_stat & FPGA_DMA_INT_RX)
+ poch_irq_dma(channel_rx);
+ if (dma_stat & FPGA_DMA_INT_TX)
+ poch_irq_dma(channel_tx);
+ }
+ if (fpga_stat & FPGA_INT_PLL_UNLOCKED) {
+ channel_tx->counters.pll_unlock++;
+ channel_rx->counters.pll_unlock++;
+ if (printk_ratelimit())
+ printk(KERN_WARNING PFX "PLL unlocked\n");
+ }
+ if (fpga_stat & FPGA_INT_TX_FF_EMPTY)
+ channel_tx->counters.fifo_empty++;
+ if (fpga_stat & FPGA_INT_TX_FF_OVRFLW)
+ channel_tx->counters.fifo_overflow++;
+ if (fpga_stat & FPGA_INT_RX_FF_EMPTY)
+ channel_rx->counters.fifo_empty++;
+ if (fpga_stat & FPGA_INT_RX_FF_OVRFLW)
+ channel_rx->counters.fifo_overflow++;
+
+ /*
+ * FIXME: These errors should be notified through the
+ * poll interface as POLLERR.
+ */
+
+ /* Re-enable interrupts. */
+ iowrite32(BRIDGE_INT_FPGA, bridge + BRIDGE_INT_MASK_REG);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static void poch_class_dev_unregister(struct poch_dev *poch_dev, int id)
+{
+ int i, j;
+ int nattrs;
+ struct channel_info *channel;
+ dev_t devno;
+
+ if (poch_dev->dev == NULL)
+ return;
+
+ for (i = 0; i < poch_dev->nchannels; i++) {
+ channel = &poch_dev->channels[i];
+ devno = poch_first_dev + (id * poch_dev->nchannels) + i;
+
+ if (!channel->dev)
+ continue;
+
+ nattrs = sizeof(poch_class_attrs)/sizeof(poch_class_attrs[0]);
+ for (j = 0; j < nattrs; j++)
+ device_remove_file(channel->dev, poch_class_attrs[j]);
+
+ device_unregister(channel->dev);
+ }
+
+ device_unregister(poch_dev->dev);
+}
+
+static int __devinit poch_class_dev_register(struct poch_dev *poch_dev,
+ int id)
+{
+ struct device *dev = &poch_dev->pci_dev->dev;
+ int i, j;
+ int nattrs;
+ int ret;
+ struct channel_info *channel;
+ dev_t devno;
+
+ poch_dev->dev = device_create(poch_cls, &poch_dev->pci_dev->dev,
+ MKDEV(0, 0), NULL, "poch%d", id);
+ if (IS_ERR(poch_dev->dev)) {
+ dev_err(dev, "error creating parent class device");
+ ret = PTR_ERR(poch_dev->dev);
+ poch_dev->dev = NULL;
+ return ret;
+ }
+
+ for (i = 0; i < poch_dev->nchannels; i++) {
+ channel = &poch_dev->channels[i];
+
+ devno = poch_first_dev + (id * poch_dev->nchannels) + i;
+ channel->dev = device_create(poch_cls, poch_dev->dev, devno,
+ NULL, "ch%d", i);
+ if (IS_ERR(channel->dev)) {
+ dev_err(dev, "error creating channel class device");
+ ret = PTR_ERR(channel->dev);
+ channel->dev = NULL;
+ poch_class_dev_unregister(poch_dev, id);
+ return ret;
+ }
+
+ dev_set_drvdata(channel->dev, channel);
+ nattrs = sizeof(poch_class_attrs)/sizeof(poch_class_attrs[0]);
+ for (j = 0; j < nattrs; j++) {
+ ret = device_create_file(channel->dev,
+ poch_class_attrs[j]);
+ if (ret) {
+ dev_err(dev, "error creating attribute file");
+ poch_class_dev_unregister(poch_dev, id);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int __devinit poch_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pci_id)
+{
+ struct device *dev = &pdev->dev;
+ struct poch_dev *poch_dev;
+ struct uio_info *uio;
+ int ret;
+ int id;
+ int i;
+
+ poch_dev = kzalloc(sizeof(struct poch_dev), GFP_KERNEL);
+ if (!poch_dev) {
+ dev_err(dev, "error allocating priv. data memory\n");
+ return -ENOMEM;
+ }
+
+ poch_dev->pci_dev = pdev;
+ uio = &poch_dev->uio;
+
+ pci_set_drvdata(pdev, poch_dev);
+
+ spin_lock_init(&poch_dev->iomem_lock);
+
+ poch_dev->nchannels = POCH_NCHANNELS;
+ poch_dev->channels[CHNO_RX_CHANNEL].dir = CHANNEL_DIR_RX;
+ poch_dev->channels[CHNO_TX_CHANNEL].dir = CHANNEL_DIR_TX;
+
+ for (i = 0; i < poch_dev->nchannels; i++) {
+ init_waitqueue_head(&poch_dev->channels[i].wq);
+ atomic_set(&poch_dev->channels[i].free, 1);
+ atomic_set(&poch_dev->channels[i].inited, 0);
+ }
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(dev, "error enabling device\n");
+ goto out_free;
+ }
+
+ ret = pci_request_regions(pdev, "poch");
+ if (ret) {
+ dev_err(dev, "error requesting resources\n");
+ goto out_disable;
+ }
+
+ uio->mem[0].addr = pci_resource_start(pdev, 1);
+ if (!uio->mem[0].addr) {
+ dev_err(dev, "invalid BAR1\n");
+ ret = -ENODEV;
+ goto out_release;
+ }
+
+ uio->mem[0].size = pci_resource_len(pdev, 1);
+ uio->mem[0].memtype = UIO_MEM_PHYS;
+
+ uio->name = "poch";
+ uio->version = "0.0.1";
+ uio->irq = -1;
+ ret = uio_register_device(dev, uio);
+ if (ret) {
+ dev_err(dev, "error register UIO device: %d\n", ret);
+ goto out_release;
+ }
+
+ poch_dev->bridge_iomem = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (poch_dev->bridge_iomem == NULL) {
+ dev_err(dev, "error mapping bridge (bar0) registers\n");
+ ret = -ENOMEM;
+ goto out_uio_unreg;
+ }
+
+ poch_dev->fpga_iomem = ioremap(pci_resource_start(pdev, 1),
+ pci_resource_len(pdev, 1));
+ if (poch_dev->fpga_iomem == NULL) {
+ dev_err(dev, "error mapping fpga (bar1) registers\n");
+ ret = -ENOMEM;
+ goto out_bar0_unmap;
+ }
+
+ ret = request_irq(pdev->irq, poch_irq_handler, IRQF_SHARED,
+ dev->bus_id, poch_dev);
+ if (ret) {
+ dev_err(dev, "error requesting IRQ %u\n", pdev->irq);
+ ret = -ENOMEM;
+ goto out_bar1_unmap;
+ }
+
+ if (!idr_pre_get(&poch_ids, GFP_KERNEL)) {
+ dev_err(dev, "error allocating memory ids\n");
+ ret = -ENOMEM;
+ goto out_free_irq;
+ }
+
+ idr_get_new(&poch_ids, poch_dev, &id);
+ if (id >= MAX_POCH_CARDS) {
+ dev_err(dev, "minors exhausted\n");
+ ret = -EBUSY;
+ goto out_free_irq;
+ }
+
+ cdev_init(&poch_dev->cdev, &poch_fops);
+ poch_dev->cdev.owner = THIS_MODULE;
+ ret = cdev_add(&poch_dev->cdev,
+ poch_first_dev + (id * poch_dev->nchannels),
+ poch_dev->nchannels);
+ if (ret) {
+ dev_err(dev, "error register character device\n");
+ goto out_idr_remove;
+ }
+
+ ret = poch_class_dev_register(poch_dev, id);
+ if (ret)
+ goto out_cdev_del;
+
+ return 0;
+
+ out_cdev_del:
+ cdev_del(&poch_dev->cdev);
+ out_idr_remove:
+ idr_remove(&poch_ids, id);
+ out_free_irq:
+ free_irq(pdev->irq, poch_dev);
+ out_bar1_unmap:
+ iounmap(poch_dev->fpga_iomem);
+ out_bar0_unmap:
+ iounmap(poch_dev->bridge_iomem);
+ out_uio_unreg:
+ uio_unregister_device(uio);
+ out_release:
+ pci_release_regions(pdev);
+ out_disable:
+ pci_disable_device(pdev);
+ out_free:
+ kfree(poch_dev);
+ return ret;
+}
+
+/*
+ * FIXME: We are yet to handle the hot unplug case.
+ */
+static void poch_pci_remove(struct pci_dev *pdev)
+{
+ struct poch_dev *poch_dev = pci_get_drvdata(pdev);
+ struct uio_info *uio = &poch_dev->uio;
+ unsigned int minor = MINOR(poch_dev->cdev.dev);
+ unsigned int id = minor / poch_dev->nchannels;
+
+ /* FIXME: unmap fpga_iomem and bridge_iomem */
+
+ poch_class_dev_unregister(poch_dev, id);
+ cdev_del(&poch_dev->cdev);
+ idr_remove(&poch_ids, id);
+ free_irq(pdev->irq, poch_dev);
+ uio_unregister_device(uio);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ iounmap(uio->mem[0].internal_addr);
+
+ kfree(poch_dev);
+}
+
+static const struct pci_device_id poch_pci_ids[] /* __devinitconst */ = {
+ { PCI_DEVICE(PCI_VENDOR_ID_RRAPIDS,
+ PCI_DEVICE_ID_RRAPIDS_POCKET_CHANGE) },
+ { 0, }
+};
+
+static struct pci_driver poch_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = poch_pci_ids,
+ .probe = poch_pci_probe,
+ .remove = poch_pci_remove,
+};
+
+static int __init poch_init_module(void)
+{
+ int ret = 0;
+
+ ret = alloc_chrdev_region(&poch_first_dev, 0,
+ MAX_POCH_DEVICES, DRV_NAME);
+ if (ret) {
+ printk(KERN_ERR PFX "error allocating device no.");
+ return ret;
+ }
+
+ poch_cls = class_create(THIS_MODULE, "pocketchange");
+ if (IS_ERR(poch_cls)) {
+ ret = PTR_ERR(poch_cls);
+ goto out_unreg_chrdev;
+ }
+
+ ret = pci_register_driver(&poch_pci_driver);
+ if (ret) {
+ printk(KERN_ERR PFX "error register PCI device");
+ goto out_class_destroy;
+ }
+
+ return 0;
+
+ out_class_destroy:
+ class_destroy(poch_cls);
+
+ out_unreg_chrdev:
+ unregister_chrdev_region(poch_first_dev, MAX_POCH_DEVICES);
+
+ return ret;
+}
+
+static void __exit poch_exit_module(void)
+{
+ pci_unregister_driver(&poch_pci_driver);
+ class_destroy(poch_cls);
+ unregister_chrdev_region(poch_first_dev, MAX_POCH_DEVICES);
+}
+
+module_init(poch_init_module);
+module_exit(poch_exit_module);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/poch/poch.h b/drivers/staging/poch/poch.h
new file mode 100644
index 00000000000..51a2d145798
--- /dev/null
+++ b/drivers/staging/poch/poch.h
@@ -0,0 +1,29 @@
+/*
+ * User-space DMA and UIO based Redrapids Pocket Change CardBus driver
+ *
+ * Copyright 2008 Vijay Kumar <vijaykumar@bravegnu.org>
+ *
+ * Part of userspace API. Should be moved to a header file in
+ * include/linux for final version.
+ *
+ */
+struct poch_cbuf_header {
+ __s32 group_size_bytes;
+ __s32 group_count;
+ __s32 group_offsets[0];
+};
+
+struct poch_counters {
+ __u32 fifo_empty;
+ __u32 fifo_overflow;
+ __u32 pll_unlock;
+};
+
+#define POCH_IOC_NUM '9'
+
+#define POCH_IOC_TRANSFER_START _IO(POCH_IOC_NUM, 0)
+#define POCH_IOC_TRANSFER_STOP _IO(POCH_IOC_NUM, 1)
+#define POCH_IOC_GET_COUNTERS _IOR(POCH_IOC_NUM, 2, \
+ struct poch_counters)
+#define POCH_IOC_SYNC_GROUP_FOR_USER _IO(POCH_IOC_NUM, 3)
+#define POCH_IOC_SYNC_GROUP_FOR_DEVICE _IO(POCH_IOC_NUM, 4)
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index b61ac4b2db9..8fa9490b3e2 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -54,7 +54,6 @@
* IS-NIC driver.
*/
-#include <linux/version.h>
#define SLIC_DUMP_ENABLED 0
#define KLUDGE_FOR_4GB_BOUNDARY 1
@@ -96,17 +95,9 @@
#include <linux/moduleparam.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/pci.h>
#include <linux/dma-mapping.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
-#include <linux/skbuff.h>
-#include <linux/string.h>
#include <asm/unaligned.h>
#include <linux/ethtool.h>
@@ -275,7 +266,6 @@ static void slic_dbg_register_trace(struct adapter *adapter,
card->reg_value[i], card->reg_valueh[i]);
}
}
-}
#endif
static void slic_init_adapter(struct net_device *netdev,
@@ -606,6 +596,7 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
uint mmio_len = 0;
struct adapter *adapter = (struct adapter *) netdev_priv(dev);
struct sliccard *card;
+ struct mcast_address *mcaddr, *mlist;
ASSERT(adapter);
DBG_MSG("slicoss: %s ENTER dev[%p] adapter[%p]\n", __func__, dev,
@@ -625,6 +616,13 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
DBG_MSG("slicoss: %s iounmap dev->base_addr[%x]\n", __func__,
(uint) dev->base_addr);
iounmap((void __iomem *)dev->base_addr);
+ /* free multicast addresses */
+ mlist = adapter->mcastaddrs;
+ while (mlist) {
+ mcaddr = mlist;
+ mlist = mlist->next;
+ kfree(mcaddr);
+ }
ASSERT(adapter->card);
card = adapter->card;
ASSERT(card->adapters_allocated);
diff --git a/drivers/staging/sxg/Kconfig b/drivers/staging/sxg/Kconfig
index 1ae35080660..6e6cf0b9ef9 100644
--- a/drivers/staging/sxg/Kconfig
+++ b/drivers/staging/sxg/Kconfig
@@ -1,6 +1,7 @@
config SXG
tristate "Alacritech SLIC Technology Non-Accelerated 10Gbe support"
depends on PCI && NETDEV_10000
+ depends on X86
default n
help
This driver supports the Alacritech SLIC Technology Non-Accelerated
diff --git a/drivers/staging/sxg/README b/drivers/staging/sxg/README
index 4d1ddbe4c33..d514d184880 100644
--- a/drivers/staging/sxg/README
+++ b/drivers/staging/sxg/README
@@ -7,6 +7,7 @@ TODO:
- remove wrappers
- checkpatch.pl cleanups
- new functionality that the card needs
+ - remove reliance on x86
Please send patches to:
Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/sxg/sxg.c b/drivers/staging/sxg/sxg.c
index 6ccbee875ab..5272a18e204 100644
--- a/drivers/staging/sxg/sxg.c
+++ b/drivers/staging/sxg/sxg.c
@@ -112,12 +112,16 @@ static bool sxg_mac_filter(p_adapter_t adapter,
static struct net_device_stats *sxg_get_stats(p_net_device dev);
#endif
+#define XXXTODO 0
+
+#if XXXTODO
static int sxg_mac_set_address(p_net_device dev, void *ptr);
+static void sxg_mcast_set_list(p_net_device dev);
+#endif
static void sxg_adapter_set_hwaddr(p_adapter_t adapter);
static void sxg_unmap_mmio_space(p_adapter_t adapter);
-static void sxg_mcast_set_mask(p_adapter_t adapter);
static int sxg_initialize_adapter(p_adapter_t adapter);
static void sxg_stock_rcv_buffers(p_adapter_t adapter);
@@ -132,9 +136,6 @@ static int sxg_write_mdio_reg(p_adapter_t adapter,
u32 DevAddr, u32 RegAddr, u32 Value);
static int sxg_read_mdio_reg(p_adapter_t adapter,
u32 DevAddr, u32 RegAddr, u32 *pValue);
-static void sxg_mcast_set_list(p_net_device dev);
-
-#define XXXTODO 0
static unsigned int sxg_first_init = 1;
static char *sxg_banner =
@@ -202,7 +203,7 @@ static void sxg_init_driver(void)
{
if (sxg_first_init) {
DBG_ERROR("sxg: %s sxg_first_init set jiffies[%lx]\n",
- __FUNCTION__, jiffies);
+ __func__, jiffies);
sxg_first_init = 0;
spin_lock_init(&sxg_global.driver_lock);
}
@@ -223,7 +224,7 @@ static void sxg_dbg_macaddrs(p_adapter_t adapter)
return;
}
-// SXG Globals
+/* SXG Globals */
static SXG_DRIVER SxgDriver;
#ifdef ATKDBG
@@ -250,7 +251,7 @@ static bool sxg_download_microcode(p_adapter_t adapter, SXG_UCODE_SEL UcodeSel)
u32 ThisSectionSize;
u32 *Instruction = NULL;
u32 BaseAddress, AddressOffset, Address;
-// u32 Failure;
+/* u32 Failure; */
u32 ValueRead;
u32 i;
u32 numSections = 0;
@@ -259,10 +260,10 @@ static bool sxg_download_microcode(p_adapter_t adapter, SXG_UCODE_SEL UcodeSel)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DnldUcod",
adapter, 0, 0, 0);
- DBG_ERROR("sxg: %s ENTER\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENTER\n", __func__);
switch (UcodeSel) {
- case SXG_UCODE_SAHARA: // Sahara operational ucode
+ case SXG_UCODE_SAHARA: /* Sahara operational ucode */
numSections = SNumSections;
for (i = 0; i < numSections; i++) {
sectionSize[i] = SSectionSize[i];
@@ -276,13 +277,13 @@ static bool sxg_download_microcode(p_adapter_t adapter, SXG_UCODE_SEL UcodeSel)
}
DBG_ERROR("sxg: RESET THE CARD\n");
- // First, reset the card
+ /* First, reset the card */
WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH);
- // Download each section of the microcode as specified in
- // its download file. The *download.c file is generated using
- // the saharaobjtoc facility which converts the metastep .obj
- // file to a .c file which contains a two dimentional array.
+ /* Download each section of the microcode as specified in */
+ /* its download file. The *download.c file is generated using */
+ /* the saharaobjtoc facility which converts the metastep .obj */
+ /* file to a .c file which contains a two dimentional array. */
for (Section = 0; Section < numSections; Section++) {
DBG_ERROR("sxg: SECTION # %d\n", Section);
switch (UcodeSel) {
@@ -294,35 +295,35 @@ static bool sxg_download_microcode(p_adapter_t adapter, SXG_UCODE_SEL UcodeSel)
break;
}
BaseAddress = sectionStart[Section];
- ThisSectionSize = sectionSize[Section] / 12; // Size in instructions
+ ThisSectionSize = sectionSize[Section] / 12; /* Size in instructions */
for (AddressOffset = 0; AddressOffset < ThisSectionSize;
AddressOffset++) {
Address = BaseAddress + AddressOffset;
ASSERT((Address & ~MICROCODE_ADDRESS_MASK) == 0);
- // Write instruction bits 31 - 0
+ /* Write instruction bits 31 - 0 */
WRITE_REG(HwRegs->UcodeDataLow, *Instruction, FLUSH);
- // Write instruction bits 63-32
+ /* Write instruction bits 63-32 */
WRITE_REG(HwRegs->UcodeDataMiddle, *(Instruction + 1),
FLUSH);
- // Write instruction bits 95-64
+ /* Write instruction bits 95-64 */
WRITE_REG(HwRegs->UcodeDataHigh, *(Instruction + 2),
FLUSH);
- // Write instruction address with the WRITE bit set
+ /* Write instruction address with the WRITE bit set */
WRITE_REG(HwRegs->UcodeAddr,
(Address | MICROCODE_ADDRESS_WRITE), FLUSH);
- // Sahara bug in the ucode download logic - the write to DataLow
- // for the next instruction could get corrupted. To avoid this,
- // write to DataLow again for this instruction (which may get
- // corrupted, but it doesn't matter), then increment the address
- // and write the data for the next instruction to DataLow. That
- // write should succeed.
+ /* Sahara bug in the ucode download logic - the write to DataLow */
+ /* for the next instruction could get corrupted. To avoid this, */
+ /* write to DataLow again for this instruction (which may get */
+ /* corrupted, but it doesn't matter), then increment the address */
+ /* and write the data for the next instruction to DataLow. That */
+ /* write should succeed. */
WRITE_REG(HwRegs->UcodeDataLow, *Instruction, TRUE);
- // Advance 3 u32S to start of next instruction
+ /* Advance 3 u32S to start of next instruction */
Instruction += 3;
}
}
- // Now repeat the entire operation reading the instruction back and
- // checking for parity errors
+ /* Now repeat the entire operation reading the instruction back and */
+ /* checking for parity errors */
for (Section = 0; Section < numSections; Section++) {
DBG_ERROR("sxg: check SECTION # %d\n", Section);
switch (UcodeSel) {
@@ -334,74 +335,74 @@ static bool sxg_download_microcode(p_adapter_t adapter, SXG_UCODE_SEL UcodeSel)
break;
}
BaseAddress = sectionStart[Section];
- ThisSectionSize = sectionSize[Section] / 12; // Size in instructions
+ ThisSectionSize = sectionSize[Section] / 12; /* Size in instructions */
for (AddressOffset = 0; AddressOffset < ThisSectionSize;
AddressOffset++) {
Address = BaseAddress + AddressOffset;
- // Write the address with the READ bit set
+ /* Write the address with the READ bit set */
WRITE_REG(HwRegs->UcodeAddr,
(Address | MICROCODE_ADDRESS_READ), FLUSH);
- // Read it back and check parity bit.
+ /* Read it back and check parity bit. */
READ_REG(HwRegs->UcodeAddr, ValueRead);
if (ValueRead & MICROCODE_ADDRESS_PARITY) {
DBG_ERROR("sxg: %s PARITY ERROR\n",
- __FUNCTION__);
+ __func__);
- return (FALSE); // Parity error
+ return (FALSE); /* Parity error */
}
ASSERT((ValueRead & MICROCODE_ADDRESS_MASK) == Address);
- // Read the instruction back and compare
+ /* Read the instruction back and compare */
READ_REG(HwRegs->UcodeDataLow, ValueRead);
if (ValueRead != *Instruction) {
DBG_ERROR("sxg: %s MISCOMPARE LOW\n",
- __FUNCTION__);
- return (FALSE); // Miscompare
+ __func__);
+ return (FALSE); /* Miscompare */
}
READ_REG(HwRegs->UcodeDataMiddle, ValueRead);
if (ValueRead != *(Instruction + 1)) {
DBG_ERROR("sxg: %s MISCOMPARE MIDDLE\n",
- __FUNCTION__);
- return (FALSE); // Miscompare
+ __func__);
+ return (FALSE); /* Miscompare */
}
READ_REG(HwRegs->UcodeDataHigh, ValueRead);
if (ValueRead != *(Instruction + 2)) {
DBG_ERROR("sxg: %s MISCOMPARE HIGH\n",
- __FUNCTION__);
- return (FALSE); // Miscompare
+ __func__);
+ return (FALSE); /* Miscompare */
}
- // Advance 3 u32S to start of next instruction
+ /* Advance 3 u32S to start of next instruction */
Instruction += 3;
}
}
- // Everything OK, Go.
+ /* Everything OK, Go. */
WRITE_REG(HwRegs->UcodeAddr, MICROCODE_ADDRESS_GO, FLUSH);
- // Poll the CardUp register to wait for microcode to initialize
- // Give up after 10,000 attemps (500ms).
+ /* Poll the CardUp register to wait for microcode to initialize */
+ /* Give up after 10,000 attemps (500ms). */
for (i = 0; i < 10000; i++) {
udelay(50);
READ_REG(adapter->UcodeRegs[0].CardUp, ValueRead);
if (ValueRead == 0xCAFE) {
- DBG_ERROR("sxg: %s BOO YA 0xCAFE\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s BOO YA 0xCAFE\n", __func__);
break;
}
}
if (i == 10000) {
- DBG_ERROR("sxg: %s TIMEOUT\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s TIMEOUT\n", __func__);
- return (FALSE); // Timeout
+ return (FALSE); /* Timeout */
}
- // Now write the LoadSync register. This is used to
- // synchronize with the card so it can scribble on the memory
- // that contained 0xCAFE from the "CardUp" step above
+ /* Now write the LoadSync register. This is used to */
+ /* synchronize with the card so it can scribble on the memory */
+ /* that contained 0xCAFE from the "CardUp" step above */
if (UcodeSel == SXG_UCODE_SAHARA) {
WRITE_REG(adapter->UcodeRegs[0].LoadSync, 0, FLUSH);
}
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDnldUcd",
adapter, 0, 0, 0);
- DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s EXIT\n", __func__);
return (TRUE);
}
@@ -420,29 +421,29 @@ static int sxg_allocate_resources(p_adapter_t adapter)
int status;
u32 i;
u32 RssIds, IsrCount;
-// PSXG_XMT_RING XmtRing;
-// PSXG_RCV_RING RcvRing;
+/* PSXG_XMT_RING XmtRing; */
+/* PSXG_RCV_RING RcvRing; */
- DBG_ERROR("%s ENTER\n", __FUNCTION__);
+ DBG_ERROR("%s ENTER\n", __func__);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocRes",
adapter, 0, 0, 0);
- // Windows tells us how many CPUs it plans to use for
- // RSS
+ /* Windows tells us how many CPUs it plans to use for */
+ /* RSS */
RssIds = SXG_RSS_CPU_COUNT(adapter);
IsrCount = adapter->MsiEnabled ? RssIds : 1;
- DBG_ERROR("%s Setup the spinlocks\n", __FUNCTION__);
+ DBG_ERROR("%s Setup the spinlocks\n", __func__);
- // Allocate spinlocks and initialize listheads first.
+ /* Allocate spinlocks and initialize listheads first. */
spin_lock_init(&adapter->RcvQLock);
spin_lock_init(&adapter->SglQLock);
spin_lock_init(&adapter->XmtZeroLock);
spin_lock_init(&adapter->Bit64RegLock);
spin_lock_init(&adapter->AdapterLock);
- DBG_ERROR("%s Setup the lists\n", __FUNCTION__);
+ DBG_ERROR("%s Setup the lists\n", __func__);
InitializeListHead(&adapter->FreeRcvBuffers);
InitializeListHead(&adapter->FreeRcvBlocks);
@@ -450,39 +451,39 @@ static int sxg_allocate_resources(p_adapter_t adapter)
InitializeListHead(&adapter->FreeSglBuffers);
InitializeListHead(&adapter->AllSglBuffers);
- // Mark these basic allocations done. This flags essentially
- // tells the SxgFreeResources routine that it can grab spinlocks
- // and reference listheads.
+ /* Mark these basic allocations done. This flags essentially */
+ /* tells the SxgFreeResources routine that it can grab spinlocks */
+ /* and reference listheads. */
adapter->BasicAllocations = TRUE;
- // Main allocation loop. Start with the maximum supported by
- // the microcode and back off if memory allocation
- // fails. If we hit a minimum, fail.
+ /* Main allocation loop. Start with the maximum supported by */
+ /* the microcode and back off if memory allocation */
+ /* fails. If we hit a minimum, fail. */
for (;;) {
- DBG_ERROR("%s Allocate XmtRings size[%lx]\n", __FUNCTION__,
- (sizeof(SXG_XMT_RING) * 1));
+ DBG_ERROR("%s Allocate XmtRings size[%x]\n", __func__,
+ (unsigned int)(sizeof(SXG_XMT_RING) * 1));
- // Start with big items first - receive and transmit rings. At the moment
- // I'm going to keep the ring size fixed and adjust the number of
- // TCBs if we fail. Later we might consider reducing the ring size as well..
+ /* Start with big items first - receive and transmit rings. At the moment */
+ /* I'm going to keep the ring size fixed and adjust the number of */
+ /* TCBs if we fail. Later we might consider reducing the ring size as well.. */
adapter->XmtRings = pci_alloc_consistent(adapter->pcidev,
sizeof(SXG_XMT_RING) *
1,
&adapter->PXmtRings);
- DBG_ERROR("%s XmtRings[%p]\n", __FUNCTION__, adapter->XmtRings);
+ DBG_ERROR("%s XmtRings[%p]\n", __func__, adapter->XmtRings);
if (!adapter->XmtRings) {
goto per_tcb_allocation_failed;
}
memset(adapter->XmtRings, 0, sizeof(SXG_XMT_RING) * 1);
- DBG_ERROR("%s Allocate RcvRings size[%lx]\n", __FUNCTION__,
- (sizeof(SXG_RCV_RING) * 1));
+ DBG_ERROR("%s Allocate RcvRings size[%x]\n", __func__,
+ (unsigned int)(sizeof(SXG_RCV_RING) * 1));
adapter->RcvRings =
pci_alloc_consistent(adapter->pcidev,
sizeof(SXG_RCV_RING) * 1,
&adapter->PRcvRings);
- DBG_ERROR("%s RcvRings[%p]\n", __FUNCTION__, adapter->RcvRings);
+ DBG_ERROR("%s RcvRings[%p]\n", __func__, adapter->RcvRings);
if (!adapter->RcvRings) {
goto per_tcb_allocation_failed;
}
@@ -490,7 +491,7 @@ static int sxg_allocate_resources(p_adapter_t adapter)
break;
per_tcb_allocation_failed:
- // an allocation failed. Free any successful allocations.
+ /* an allocation failed. Free any successful allocations. */
if (adapter->XmtRings) {
pci_free_consistent(adapter->pcidev,
sizeof(SXG_XMT_RING) * 4096,
@@ -505,22 +506,22 @@ static int sxg_allocate_resources(p_adapter_t adapter)
adapter->PRcvRings);
adapter->RcvRings = NULL;
}
- // Loop around and try again....
+ /* Loop around and try again.... */
}
- DBG_ERROR("%s Initialize RCV ZERO and XMT ZERO rings\n", __FUNCTION__);
- // Initialize rcv zero and xmt zero rings
+ DBG_ERROR("%s Initialize RCV ZERO and XMT ZERO rings\n", __func__);
+ /* Initialize rcv zero and xmt zero rings */
SXG_INITIALIZE_RING(adapter->RcvRingZeroInfo, SXG_RCV_RING_SIZE);
SXG_INITIALIZE_RING(adapter->XmtRingZeroInfo, SXG_XMT_RING_SIZE);
- // Sanity check receive data structure format
+ /* Sanity check receive data structure format */
ASSERT((adapter->ReceiveBufferSize == SXG_RCV_DATA_BUFFER_SIZE) ||
(adapter->ReceiveBufferSize == SXG_RCV_JUMBO_BUFFER_SIZE));
ASSERT(sizeof(SXG_RCV_DESCRIPTOR_BLOCK) ==
SXG_RCV_DESCRIPTOR_BLOCK_SIZE);
- // Allocate receive data buffers. We allocate a block of buffers and
- // a corresponding descriptor block at once. See sxghw.h:SXG_RCV_BLOCK
+ /* Allocate receive data buffers. We allocate a block of buffers and */
+ /* a corresponding descriptor block at once. See sxghw.h:SXG_RCV_BLOCK */
for (i = 0; i < SXG_INITIAL_RCV_DATA_BUFFERS;
i += SXG_RCV_DESCRIPTORS_PER_BLOCK) {
sxg_allocate_buffer_memory(adapter,
@@ -528,8 +529,8 @@ static int sxg_allocate_resources(p_adapter_t adapter)
ReceiveBufferSize),
SXG_BUFFER_TYPE_RCV);
}
- // NBL resource allocation can fail in the 'AllocateComplete' routine, which
- // doesn't return status. Make sure we got the number of buffers we requested
+ /* NBL resource allocation can fail in the 'AllocateComplete' routine, which */
+ /* doesn't return status. Make sure we got the number of buffers we requested */
if (adapter->FreeRcvBufferCount < SXG_INITIAL_RCV_DATA_BUFFERS) {
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF6",
adapter, adapter->FreeRcvBufferCount, SXG_MAX_ENTRIES,
@@ -537,17 +538,17 @@ static int sxg_allocate_resources(p_adapter_t adapter)
return (STATUS_RESOURCES);
}
- DBG_ERROR("%s Allocate EventRings size[%lx]\n", __FUNCTION__,
- (sizeof(SXG_EVENT_RING) * RssIds));
+ DBG_ERROR("%s Allocate EventRings size[%x]\n", __func__,
+ (unsigned int)(sizeof(SXG_EVENT_RING) * RssIds));
- // Allocate event queues.
+ /* Allocate event queues. */
adapter->EventRings = pci_alloc_consistent(adapter->pcidev,
sizeof(SXG_EVENT_RING) *
RssIds,
&adapter->PEventRings);
if (!adapter->EventRings) {
- // Caller will call SxgFreeAdapter to clean up above allocations
+ /* Caller will call SxgFreeAdapter to clean up above allocations */
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF8",
adapter, SXG_MAX_ENTRIES, 0, 0);
status = STATUS_RESOURCES;
@@ -555,12 +556,12 @@ static int sxg_allocate_resources(p_adapter_t adapter)
}
memset(adapter->EventRings, 0, sizeof(SXG_EVENT_RING) * RssIds);
- DBG_ERROR("%s Allocate ISR size[%x]\n", __FUNCTION__, IsrCount);
- // Allocate ISR
+ DBG_ERROR("%s Allocate ISR size[%x]\n", __func__, IsrCount);
+ /* Allocate ISR */
adapter->Isr = pci_alloc_consistent(adapter->pcidev,
IsrCount, &adapter->PIsr);
if (!adapter->Isr) {
- // Caller will call SxgFreeAdapter to clean up above allocations
+ /* Caller will call SxgFreeAdapter to clean up above allocations */
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF9",
adapter, SXG_MAX_ENTRIES, 0, 0);
status = STATUS_RESOURCES;
@@ -568,10 +569,10 @@ static int sxg_allocate_resources(p_adapter_t adapter)
}
memset(adapter->Isr, 0, sizeof(u32) * IsrCount);
- DBG_ERROR("%s Allocate shared XMT ring zero index location size[%lx]\n",
- __FUNCTION__, sizeof(u32));
+ DBG_ERROR("%s Allocate shared XMT ring zero index location size[%x]\n",
+ __func__, (unsigned int)sizeof(u32));
- // Allocate shared XMT ring zero index location
+ /* Allocate shared XMT ring zero index location */
adapter->XmtRingZeroIndex = pci_alloc_consistent(adapter->pcidev,
sizeof(u32),
&adapter->
@@ -587,7 +588,7 @@ static int sxg_allocate_resources(p_adapter_t adapter)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlcResS",
adapter, SXG_MAX_ENTRIES, 0, 0);
- DBG_ERROR("%s EXIT\n", __FUNCTION__);
+ DBG_ERROR("%s EXIT\n", __func__);
return (STATUS_SUCCESS);
}
@@ -606,17 +607,17 @@ static void sxg_config_pci(struct pci_dev *pcidev)
u16 new_command;
pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
- DBG_ERROR("sxg: %s PCI command[%4.4x]\n", __FUNCTION__, pci_command);
- // Set the command register
- new_command = pci_command | (PCI_COMMAND_MEMORY | // Memory Space Enable
- PCI_COMMAND_MASTER | // Bus master enable
- PCI_COMMAND_INVALIDATE | // Memory write and invalidate
- PCI_COMMAND_PARITY | // Parity error response
- PCI_COMMAND_SERR | // System ERR
- PCI_COMMAND_FAST_BACK); // Fast back-to-back
+ DBG_ERROR("sxg: %s PCI command[%4.4x]\n", __func__, pci_command);
+ /* Set the command register */
+ new_command = pci_command | (PCI_COMMAND_MEMORY | /* Memory Space Enable */
+ PCI_COMMAND_MASTER | /* Bus master enable */
+ PCI_COMMAND_INVALIDATE | /* Memory write and invalidate */
+ PCI_COMMAND_PARITY | /* Parity error response */
+ PCI_COMMAND_SERR | /* System ERR */
+ PCI_COMMAND_FAST_BACK); /* Fast back-to-back */
if (pci_command != new_command) {
DBG_ERROR("%s -- Updating PCI COMMAND register %4.4x->%4.4x.\n",
- __FUNCTION__, pci_command, new_command);
+ __func__, pci_command, new_command);
pci_write_config_word(pcidev, PCI_COMMAND, new_command);
}
}
@@ -634,9 +635,9 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
ulong mmio_len = 0;
DBG_ERROR("sxg: %s 2.6 VERSION ENTER jiffies[%lx] cpu %d\n",
- __FUNCTION__, jiffies, smp_processor_id());
+ __func__, jiffies, smp_processor_id());
- // Initialize trace buffer
+ /* Initialize trace buffer */
#ifdef ATKDBG
SxgTraceBuffer = &LSxgTraceBuffer;
SXG_TRACE_INIT(SxgTraceBuffer, TRACE_NOISY);
@@ -701,11 +702,11 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
mmio_start, mmio_len);
memmapped_ioaddr = ioremap(mmio_start, mmio_len);
- DBG_ERROR("sxg: %s MEMMAPPED_IOADDR [%p]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s MEMMAPPED_IOADDR [%p]\n", __func__,
memmapped_ioaddr);
if (!memmapped_ioaddr) {
DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
- __FUNCTION__, mmio_len, mmio_start);
+ __func__, mmio_len, mmio_start);
goto err_out_free_mmio_region;
}
@@ -727,7 +728,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
memmapped_ioaddr);
if (!memmapped_ioaddr) {
DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
- __FUNCTION__, mmio_len, mmio_start);
+ __func__, mmio_len, mmio_start);
goto err_out_free_mmio_region;
}
@@ -738,13 +739,13 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
adapter->UcodeRegs = (void *)memmapped_ioaddr;
adapter->State = SXG_STATE_INITIALIZING;
- // Maintain a list of all adapters anchored by
- // the global SxgDriver structure.
+ /* Maintain a list of all adapters anchored by */
+ /* the global SxgDriver structure. */
adapter->Next = SxgDriver.Adapters;
SxgDriver.Adapters = adapter;
adapter->AdapterID = ++SxgDriver.AdapterID;
- // Initialize CRC table used to determine multicast hash
+ /* Initialize CRC table used to determine multicast hash */
sxg_mcast_init_crc32();
adapter->JumboEnabled = FALSE;
@@ -757,18 +758,18 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
adapter->ReceiveBufferSize = SXG_RCV_DATA_BUFFER_SIZE;
}
-// status = SXG_READ_EEPROM(adapter);
-// if (!status) {
-// goto sxg_init_bad;
-// }
+/* status = SXG_READ_EEPROM(adapter); */
+/* if (!status) { */
+/* goto sxg_init_bad; */
+/* } */
- DBG_ERROR("sxg: %s ENTER sxg_config_pci\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENTER sxg_config_pci\n", __func__);
sxg_config_pci(pcidev);
- DBG_ERROR("sxg: %s EXIT sxg_config_pci\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s EXIT sxg_config_pci\n", __func__);
- DBG_ERROR("sxg: %s ENTER sxg_init_driver\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENTER sxg_init_driver\n", __func__);
sxg_init_driver();
- DBG_ERROR("sxg: %s EXIT sxg_init_driver\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s EXIT sxg_init_driver\n", __func__);
adapter->vendid = pci_tbl_entry->vendor;
adapter->devid = pci_tbl_entry->device;
@@ -780,23 +781,23 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
adapter->irq = pcidev->irq;
adapter->next_netdevice = head_netdevice;
head_netdevice = netdev;
-// adapter->chipid = chip_idx;
- adapter->port = 0; //adapter->functionnumber;
+/* adapter->chipid = chip_idx; */
+ adapter->port = 0; /*adapter->functionnumber; */
adapter->cardindex = adapter->port;
- // Allocate memory and other resources
- DBG_ERROR("sxg: %s ENTER sxg_allocate_resources\n", __FUNCTION__);
+ /* Allocate memory and other resources */
+ DBG_ERROR("sxg: %s ENTER sxg_allocate_resources\n", __func__);
status = sxg_allocate_resources(adapter);
DBG_ERROR("sxg: %s EXIT sxg_allocate_resources status %x\n",
- __FUNCTION__, status);
+ __func__, status);
if (status != STATUS_SUCCESS) {
goto err_out_unmap;
}
- DBG_ERROR("sxg: %s ENTER sxg_download_microcode\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENTER sxg_download_microcode\n", __func__);
if (sxg_download_microcode(adapter, SXG_UCODE_SAHARA)) {
DBG_ERROR("sxg: %s ENTER sxg_adapter_set_hwaddr\n",
- __FUNCTION__);
+ __func__);
sxg_adapter_set_hwaddr(adapter);
} else {
adapter->state = ADAPT_FAIL;
@@ -819,7 +820,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
#endif
strcpy(netdev->name, "eth%d");
-// strcpy(netdev->name, pci_name(pcidev));
+/* strcpy(netdev->name, pci_name(pcidev)); */
if ((err = register_netdev(netdev))) {
DBG_ERROR("Cannot register net device, aborting. %s\n",
netdev->name);
@@ -832,11 +833,11 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3],
netdev->dev_addr[4], netdev->dev_addr[5]);
-//sxg_init_bad:
+/*sxg_init_bad: */
ASSERT(status == FALSE);
-// sxg_free_adapter(adapter);
+/* sxg_free_adapter(adapter); */
- DBG_ERROR("sxg: %s EXIT status[%x] jiffies[%lx] cpu %d\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s EXIT status[%x] jiffies[%lx] cpu %d\n", __func__,
status, jiffies, smp_processor_id());
return status;
@@ -848,7 +849,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev,
err_out_exit_sxg_probe:
- DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __FUNCTION__, jiffies,
+ DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __func__, jiffies,
smp_processor_id());
return -ENODEV;
@@ -874,12 +875,12 @@ static void sxg_disable_interrupt(p_adapter_t adapter)
{
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DisIntr",
adapter, adapter->InterruptsEnabled, 0, 0);
- // For now, RSS is disabled with line based interrupts
+ /* For now, RSS is disabled with line based interrupts */
ASSERT(adapter->RssEnabled == FALSE);
ASSERT(adapter->MsiEnabled == FALSE);
- //
- // Turn off interrupts by writing to the icr register.
- //
+ /* */
+ /* Turn off interrupts by writing to the icr register. */
+ /* */
WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_DISABLE), TRUE);
adapter->InterruptsEnabled = 0;
@@ -905,12 +906,12 @@ static void sxg_enable_interrupt(p_adapter_t adapter)
{
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "EnIntr",
adapter, adapter->InterruptsEnabled, 0, 0);
- // For now, RSS is disabled with line based interrupts
+ /* For now, RSS is disabled with line based interrupts */
ASSERT(adapter->RssEnabled == FALSE);
ASSERT(adapter->MsiEnabled == FALSE);
- //
- // Turn on interrupts by writing to the icr register.
- //
+ /* */
+ /* Turn on interrupts by writing to the icr register. */
+ /* */
WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_ENABLE), TRUE);
adapter->InterruptsEnabled = 1;
@@ -935,29 +936,29 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
{
p_net_device dev = (p_net_device) dev_id;
p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
-// u32 CpuMask = 0, i;
+/* u32 CpuMask = 0, i; */
adapter->Stats.NumInts++;
if (adapter->Isr[0] == 0) {
- // The SLIC driver used to experience a number of spurious interrupts
- // due to the delay associated with the masking of the interrupt
- // (we'd bounce back in here). If we see that again with Sahara,
- // add a READ_REG of the Icr register after the WRITE_REG below.
+ /* The SLIC driver used to experience a number of spurious interrupts */
+ /* due to the delay associated with the masking of the interrupt */
+ /* (we'd bounce back in here). If we see that again with Sahara, */
+ /* add a READ_REG of the Icr register after the WRITE_REG below. */
adapter->Stats.FalseInts++;
return IRQ_NONE;
}
- //
- // Move the Isr contents and clear the value in
- // shared memory, and mask interrupts
- //
+ /* */
+ /* Move the Isr contents and clear the value in */
+ /* shared memory, and mask interrupts */
+ /* */
adapter->IsrCopy[0] = adapter->Isr[0];
adapter->Isr[0] = 0;
WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE);
-// ASSERT(adapter->IsrDpcsPending == 0);
-#if XXXTODO // RSS Stuff
- // If RSS is enabled and the ISR specifies
- // SXG_ISR_EVENT, then schedule DPC's
- // based on event queues.
+/* ASSERT(adapter->IsrDpcsPending == 0); */
+#if XXXTODO /* RSS Stuff */
+ /* If RSS is enabled and the ISR specifies */
+ /* SXG_ISR_EVENT, then schedule DPC's */
+ /* based on event queues. */
if (adapter->RssEnabled && (adapter->IsrCopy[0] & SXG_ISR_EVENT)) {
for (i = 0;
i < adapter->RssSystemInfo->ProcessorInfo.RssCpuCount;
@@ -973,8 +974,8 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
}
}
}
- // Now, either schedule the CPUs specified by the CpuMask,
- // or queue default
+ /* Now, either schedule the CPUs specified by the CpuMask, */
+ /* or queue default */
if (CpuMask) {
*QueueDefault = FALSE;
} else {
@@ -983,9 +984,9 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
}
*TargetCpus = CpuMask;
#endif
- //
- // There are no DPCs in Linux, so call the handler now
- //
+ /* */
+ /* There are no DPCs in Linux, so call the handler now */
+ /* */
sxg_handle_interrupt(adapter);
return IRQ_HANDLED;
@@ -993,7 +994,7 @@ static irqreturn_t sxg_isr(int irq, void *dev_id)
static void sxg_handle_interrupt(p_adapter_t adapter)
{
-// unsigned char RssId = 0;
+/* unsigned char RssId = 0; */
u32 NewIsr;
if (adapter->Stats.RcvNoBuffer < 5) {
@@ -1002,32 +1003,32 @@ static void sxg_handle_interrupt(p_adapter_t adapter)
}
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr",
adapter, adapter->IsrCopy[0], 0, 0);
- // For now, RSS is disabled with line based interrupts
+ /* For now, RSS is disabled with line based interrupts */
ASSERT(adapter->RssEnabled == FALSE);
ASSERT(adapter->MsiEnabled == FALSE);
ASSERT(adapter->IsrCopy[0]);
-/////////////////////////////
+/*/////////////////////////// */
- // Always process the event queue.
+ /* Always process the event queue. */
sxg_process_event_queue(adapter,
(adapter->RssEnabled ? /*RssId */ 0 : 0));
-#if XXXTODO // RSS stuff
+#if XXXTODO /* RSS stuff */
if (--adapter->IsrDpcsPending) {
- // We're done.
+ /* We're done. */
ASSERT(adapter->RssEnabled);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DPCsPend",
adapter, 0, 0, 0);
return;
}
#endif
- //
- // Last (or only) DPC processes the ISR and clears the interrupt.
- //
+ /* */
+ /* Last (or only) DPC processes the ISR and clears the interrupt. */
+ /* */
NewIsr = sxg_process_isr(adapter, 0);
- //
- // Reenable interrupts
- //
+ /* */
+ /* Reenable interrupts */
+ /* */
adapter->IsrCopy[0] = 0;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr",
adapter, NewIsr, 0, 0);
@@ -1063,75 +1064,75 @@ static int sxg_process_isr(p_adapter_t adapter, u32 MessageId)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ProcIsr",
adapter, Isr, 0, 0);
- // Error
+ /* Error */
if (Isr & SXG_ISR_ERR) {
if (Isr & SXG_ISR_PDQF) {
adapter->Stats.PdqFull++;
- DBG_ERROR("%s: SXG_ISR_ERR PDQF!!\n", __FUNCTION__);
+ DBG_ERROR("%s: SXG_ISR_ERR PDQF!!\n", __func__);
}
- // No host buffer
+ /* No host buffer */
if (Isr & SXG_ISR_RMISS) {
- // There is a bunch of code in the SLIC driver which
- // attempts to process more receive events per DPC
- // if we start to fall behind. We'll probably
- // need to do something similar here, but hold
- // off for now. I don't want to make the code more
- // complicated than strictly needed.
+ /* There is a bunch of code in the SLIC driver which */
+ /* attempts to process more receive events per DPC */
+ /* if we start to fall behind. We'll probably */
+ /* need to do something similar here, but hold */
+ /* off for now. I don't want to make the code more */
+ /* complicated than strictly needed. */
adapter->Stats.RcvNoBuffer++;
if (adapter->Stats.RcvNoBuffer < 5) {
DBG_ERROR("%s: SXG_ISR_ERR RMISS!!\n",
- __FUNCTION__);
+ __func__);
}
}
- // Card crash
+ /* Card crash */
if (Isr & SXG_ISR_DEAD) {
- // Set aside the crash info and set the adapter state to RESET
+ /* Set aside the crash info and set the adapter state to RESET */
adapter->CrashCpu =
(unsigned char)((Isr & SXG_ISR_CPU) >>
SXG_ISR_CPU_SHIFT);
adapter->CrashLocation = (ushort) (Isr & SXG_ISR_CRASH);
adapter->Dead = TRUE;
- DBG_ERROR("%s: ISR_DEAD %x, CPU: %d\n", __FUNCTION__,
+ DBG_ERROR("%s: ISR_DEAD %x, CPU: %d\n", __func__,
adapter->CrashLocation, adapter->CrashCpu);
}
- // Event ring full
+ /* Event ring full */
if (Isr & SXG_ISR_ERFULL) {
- // Same issue as RMISS, really. This means the
- // host is falling behind the card. Need to increase
- // event ring size, process more events per interrupt,
- // and/or reduce/remove interrupt aggregation.
+ /* Same issue as RMISS, really. This means the */
+ /* host is falling behind the card. Need to increase */
+ /* event ring size, process more events per interrupt, */
+ /* and/or reduce/remove interrupt aggregation. */
adapter->Stats.EventRingFull++;
DBG_ERROR("%s: SXG_ISR_ERR EVENT RING FULL!!\n",
- __FUNCTION__);
+ __func__);
}
- // Transmit drop - no DRAM buffers or XMT error
+ /* Transmit drop - no DRAM buffers or XMT error */
if (Isr & SXG_ISR_XDROP) {
adapter->Stats.XmtDrops++;
adapter->Stats.XmtErrors++;
- DBG_ERROR("%s: SXG_ISR_ERR XDROP!!\n", __FUNCTION__);
+ DBG_ERROR("%s: SXG_ISR_ERR XDROP!!\n", __func__);
}
}
- // Slowpath send completions
+ /* Slowpath send completions */
if (Isr & SXG_ISR_SPSEND) {
sxg_complete_slow_send(adapter);
}
- // Dump
+ /* Dump */
if (Isr & SXG_ISR_UPC) {
- ASSERT(adapter->DumpCmdRunning); // Maybe change when debug is added..
+ ASSERT(adapter->DumpCmdRunning); /* Maybe change when debug is added.. */
adapter->DumpCmdRunning = FALSE;
}
- // Link event
+ /* Link event */
if (Isr & SXG_ISR_LINK) {
sxg_link_event(adapter);
}
- // Debug - breakpoint hit
+ /* Debug - breakpoint hit */
if (Isr & SXG_ISR_BREAK) {
- // At the moment AGDB isn't written to support interactive
- // debug sessions. When it is, this interrupt will be used
- // to signal AGDB that it has hit a breakpoint. For now, ASSERT.
+ /* At the moment AGDB isn't written to support interactive */
+ /* debug sessions. When it is, this interrupt will be used */
+ /* to signal AGDB that it has hit a breakpoint. For now, ASSERT. */
ASSERT(0);
}
- // Heartbeat response
+ /* Heartbeat response */
if (Isr & SXG_ISR_PING) {
adapter->PingOutstanding = FALSE;
}
@@ -1171,39 +1172,39 @@ static u32 sxg_process_event_queue(p_adapter_t adapter, u32 RssId)
(adapter->State == SXG_STATE_PAUSING) ||
(adapter->State == SXG_STATE_PAUSED) ||
(adapter->State == SXG_STATE_HALTING));
- // We may still have unprocessed events on the queue if
- // the card crashed. Don't process them.
+ /* We may still have unprocessed events on the queue if */
+ /* the card crashed. Don't process them. */
if (adapter->Dead) {
return (0);
}
- // In theory there should only be a single processor that
- // accesses this queue, and only at interrupt-DPC time. So
- // we shouldn't need a lock for any of this.
+ /* In theory there should only be a single processor that */
+ /* accesses this queue, and only at interrupt-DPC time. So */
+ /* we shouldn't need a lock for any of this. */
while (Event->Status & EVENT_STATUS_VALID) {
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event",
Event, Event->Code, Event->Status,
adapter->NextEvent);
switch (Event->Code) {
case EVENT_CODE_BUFFERS:
- ASSERT(!(Event->CommandIndex & 0xFF00)); // SXG_RING_INFO Head & Tail == unsigned char
- //
+ ASSERT(!(Event->CommandIndex & 0xFF00)); /* SXG_RING_INFO Head & Tail == unsigned char */
+ /* */
sxg_complete_descriptor_blocks(adapter,
Event->CommandIndex);
- //
+ /* */
break;
case EVENT_CODE_SLOWRCV:
--adapter->RcvBuffersOnCard;
if ((skb = sxg_slow_receive(adapter, Event))) {
u32 rx_bytes;
#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
- // Add it to our indication list
+ /* Add it to our indication list */
SXG_ADD_RCV_PACKET(adapter, skb, prev_skb,
IndicationList, num_skbs);
- // In Linux, we just pass up each skb to the protocol above at this point,
- // there is no capability of an indication list.
+ /* In Linux, we just pass up each skb to the protocol above at this point, */
+ /* there is no capability of an indication list. */
#else
-// CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE);
- rx_bytes = Event->Length; // (rcvbuf->length & IRHDDR_FLEN_MSK);
+/* CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE); */
+ rx_bytes = Event->Length; /* (rcvbuf->length & IRHDDR_FLEN_MSK); */
skb_put(skb, rx_bytes);
adapter->stats.rx_packets++;
adapter->stats.rx_bytes += rx_bytes;
@@ -1218,43 +1219,43 @@ static u32 sxg_process_event_queue(p_adapter_t adapter, u32 RssId)
break;
default:
DBG_ERROR("%s: ERROR Invalid EventCode %d\n",
- __FUNCTION__, Event->Code);
-// ASSERT(0);
+ __func__, Event->Code);
+/* ASSERT(0); */
}
- // See if we need to restock card receive buffers.
- // There are two things to note here:
- // First - This test is not SMP safe. The
- // adapter->BuffersOnCard field is protected via atomic interlocked calls, but
- // we do not protect it with respect to these tests. The only way to do that
- // is with a lock, and I don't want to grab a lock every time we adjust the
- // BuffersOnCard count. Instead, we allow the buffer replenishment to be off
- // once in a while. The worst that can happen is the card is given one
- // more-or-less descriptor block than the arbitrary value we've chosen.
- // No big deal
- // In short DO NOT ADD A LOCK HERE, OR WHERE RcvBuffersOnCard is adjusted.
- // Second - We expect this test to rarely evaluate to true. We attempt to
- // refill descriptor blocks as they are returned to us
- // (sxg_complete_descriptor_blocks), so The only time this should evaluate
- // to true is when sxg_complete_descriptor_blocks failed to allocate
- // receive buffers.
+ /* See if we need to restock card receive buffers. */
+ /* There are two things to note here: */
+ /* First - This test is not SMP safe. The */
+ /* adapter->BuffersOnCard field is protected via atomic interlocked calls, but */
+ /* we do not protect it with respect to these tests. The only way to do that */
+ /* is with a lock, and I don't want to grab a lock every time we adjust the */
+ /* BuffersOnCard count. Instead, we allow the buffer replenishment to be off */
+ /* once in a while. The worst that can happen is the card is given one */
+ /* more-or-less descriptor block than the arbitrary value we've chosen. */
+ /* No big deal */
+ /* In short DO NOT ADD A LOCK HERE, OR WHERE RcvBuffersOnCard is adjusted. */
+ /* Second - We expect this test to rarely evaluate to true. We attempt to */
+ /* refill descriptor blocks as they are returned to us */
+ /* (sxg_complete_descriptor_blocks), so The only time this should evaluate */
+ /* to true is when sxg_complete_descriptor_blocks failed to allocate */
+ /* receive buffers. */
if (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) {
sxg_stock_rcv_buffers(adapter);
}
- // It's more efficient to just set this to zero.
- // But clearing the top bit saves potential debug info...
+ /* It's more efficient to just set this to zero. */
+ /* But clearing the top bit saves potential debug info... */
Event->Status &= ~EVENT_STATUS_VALID;
- // Advanct to the next event
+ /* Advanct to the next event */
SXG_ADVANCE_INDEX(adapter->NextEvent[RssId], EVENT_RING_SIZE);
Event = &EventRing->Ring[adapter->NextEvent[RssId]];
EventsProcessed++;
if (EventsProcessed == EVENT_RING_BATCH) {
- // Release a batch of events back to the card
+ /* Release a batch of events back to the card */
WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
EVENT_RING_BATCH, FALSE);
EventsProcessed = 0;
- // If we've processed our batch limit, break out of the
- // loop and return SXG_ISR_EVENT to arrange for us to
- // be called again
+ /* If we've processed our batch limit, break out of the */
+ /* loop and return SXG_ISR_EVENT to arrange for us to */
+ /* be called again */
if (Batches++ == EVENT_BATCH_LIMIT) {
SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
TRACE_NOISY, "EvtLimit", Batches,
@@ -1265,14 +1266,14 @@ static u32 sxg_process_event_queue(p_adapter_t adapter, u32 RssId)
}
}
#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
- //
- // Indicate any received dumb-nic frames
- //
+ /* */
+ /* Indicate any received dumb-nic frames */
+ /* */
SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs);
#endif
- //
- // Release events back to the card.
- //
+ /* */
+ /* Release events back to the card. */
+ /* */
if (EventsProcessed) {
WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
EventsProcessed, FALSE);
@@ -1299,43 +1300,43 @@ static void sxg_complete_slow_send(p_adapter_t adapter)
u32 *ContextType;
PSXG_CMD XmtCmd;
- // NOTE - This lock is dropped and regrabbed in this loop.
- // This means two different processors can both be running
- // through this loop. Be *very* careful.
+ /* NOTE - This lock is dropped and regrabbed in this loop. */
+ /* This means two different processors can both be running */
+ /* through this loop. Be *very* careful. */
spin_lock(&adapter->XmtZeroLock);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnds",
adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
while (XmtRingInfo->Tail != *adapter->XmtRingZeroIndex) {
- // Locate the current Cmd (ring descriptor entry), and
- // associated SGL, and advance the tail
+ /* Locate the current Cmd (ring descriptor entry), and */
+ /* associated SGL, and advance the tail */
SXG_RETURN_CMD(XmtRing, XmtRingInfo, XmtCmd, ContextType);
ASSERT(ContextType);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd",
XmtRingInfo->Head, XmtRingInfo->Tail, XmtCmd, 0);
- // Clear the SGL field.
+ /* Clear the SGL field. */
XmtCmd->Sgl = 0;
switch (*ContextType) {
case SXG_SGL_DUMB:
{
struct sk_buff *skb;
- // Dumb-nic send. Command context is the dumb-nic SGL
+ /* Dumb-nic send. Command context is the dumb-nic SGL */
skb = (struct sk_buff *)ContextType;
- // Complete the send
+ /* Complete the send */
SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
TRACE_IMPORTANT, "DmSndCmp", skb, 0,
0, 0);
ASSERT(adapter->Stats.XmtQLen);
- adapter->Stats.XmtQLen--; // within XmtZeroLock
+ adapter->Stats.XmtQLen--; /* within XmtZeroLock */
adapter->Stats.XmtOk++;
- // Now drop the lock and complete the send back to
- // Microsoft. We need to drop the lock because
- // Microsoft can come back with a chimney send, which
- // results in a double trip in SxgTcpOuput
+ /* Now drop the lock and complete the send back to */
+ /* Microsoft. We need to drop the lock because */
+ /* Microsoft can come back with a chimney send, which */
+ /* results in a double trip in SxgTcpOuput */
spin_unlock(&adapter->XmtZeroLock);
SXG_COMPLETE_DUMB_SEND(adapter, skb);
- // and reacquire..
+ /* and reacquire.. */
spin_lock(&adapter->XmtZeroLock);
}
break;
@@ -1371,7 +1372,7 @@ static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "SlowRcv", Event,
RcvDataBufferHdr, RcvDataBufferHdr->State,
RcvDataBufferHdr->VirtualAddress);
- // Drop rcv frames in non-running state
+ /* Drop rcv frames in non-running state */
switch (adapter->State) {
case SXG_STATE_RUNNING:
break;
@@ -1384,12 +1385,12 @@ static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event)
goto drop;
}
- // Change buffer state to UPSTREAM
+ /* Change buffer state to UPSTREAM */
RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM;
if (Event->Status & EVENT_STATUS_RCVERR) {
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvError",
Event, Event->Status, Event->HostHandle, 0);
- // XXXTODO - Remove this print later
+ /* XXXTODO - Remove this print later */
DBG_ERROR("SXG: Receive error %x\n", *(u32 *)
SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr));
sxg_process_rcv_error(adapter, *(u32 *)
@@ -1397,8 +1398,8 @@ static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event)
(RcvDataBufferHdr));
goto drop;
}
-#if XXXTODO // VLAN stuff
- // If there's a VLAN tag, extract it and validate it
+#if XXXTODO /* VLAN stuff */
+ /* If there's a VLAN tag, extract it and validate it */
if (((p_ether_header) (SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)))->
EtherType == ETHERTYPE_VLAN) {
if (SxgExtractVlanHeader(adapter, RcvDataBufferHdr, Event) !=
@@ -1411,9 +1412,9 @@ static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event)
}
}
#endif
- //
- // Dumb-nic frame. See if it passes our mac filter and update stats
- //
+ /* */
+ /* Dumb-nic frame. See if it passes our mac filter and update stats */
+ /* */
if (!sxg_mac_filter(adapter, (p_ether_header)
SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
Event->Length)) {
@@ -1427,9 +1428,9 @@ static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumbRcv",
RcvDataBufferHdr, Packet, Event->Length, 0);
- //
- // Lastly adjust the receive packet length.
- //
+ /* */
+ /* Lastly adjust the receive packet length. */
+ /* */
SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event);
return (Packet);
@@ -1541,7 +1542,7 @@ static bool sxg_mac_filter(p_adapter_t adapter, p_ether_header EtherHdr,
if (SXG_MULTICAST_PACKET(EtherHdr)) {
if (SXG_BROADCAST_PACKET(EtherHdr)) {
- // broadcast
+ /* broadcast */
if (adapter->MacFilter & MAC_BCAST) {
adapter->Stats.DumbRcvBcastPkts++;
adapter->Stats.DumbRcvBcastBytes += length;
@@ -1550,7 +1551,7 @@ static bool sxg_mac_filter(p_adapter_t adapter, p_ether_header EtherHdr,
return (TRUE);
}
} else {
- // multicast
+ /* multicast */
if (adapter->MacFilter & MAC_ALLMCAST) {
adapter->Stats.DumbRcvMcastPkts++;
adapter->Stats.DumbRcvMcastBytes += length;
@@ -1580,9 +1581,9 @@ static bool sxg_mac_filter(p_adapter_t adapter, p_ether_header EtherHdr,
}
}
} else if (adapter->MacFilter & MAC_DIRECTED) {
- // Not broadcast or multicast. Must be directed at us or
- // the card is in promiscuous mode. Either way, consider it
- // ours if MAC_DIRECTED is set
+ /* Not broadcast or multicast. Must be directed at us or */
+ /* the card is in promiscuous mode. Either way, consider it */
+ /* ours if MAC_DIRECTED is set */
adapter->Stats.DumbRcvUcastPkts++;
adapter->Stats.DumbRcvUcastBytes += length;
adapter->Stats.DumbRcvPkts++;
@@ -1590,7 +1591,7 @@ static bool sxg_mac_filter(p_adapter_t adapter, p_ether_header EtherHdr,
return (TRUE);
}
if (adapter->MacFilter & MAC_PROMISC) {
- // Whatever it is, keep it.
+ /* Whatever it is, keep it. */
adapter->Stats.DumbRcvPkts++;
adapter->Stats.DumbRcvBytes += length;
return (TRUE);
@@ -1606,7 +1607,7 @@ static int sxg_register_interrupt(p_adapter_t adapter)
DBG_ERROR
("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x] %x\n",
- __FUNCTION__, adapter, adapter->netdev->irq, NR_IRQS);
+ __func__, adapter, adapter->netdev->irq, NR_IRQS);
spin_unlock_irqrestore(&sxg_global.driver_lock,
sxg_global.flags);
@@ -1625,18 +1626,18 @@ static int sxg_register_interrupt(p_adapter_t adapter)
}
adapter->intrregistered = 1;
adapter->IntRegistered = TRUE;
- // Disable RSS with line-based interrupts
+ /* Disable RSS with line-based interrupts */
adapter->MsiEnabled = FALSE;
adapter->RssEnabled = FALSE;
DBG_ERROR("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x]\n",
- __FUNCTION__, adapter, adapter->netdev->irq);
+ __func__, adapter, adapter->netdev->irq);
}
return (STATUS_SUCCESS);
}
static void sxg_deregister_interrupt(p_adapter_t adapter)
{
- DBG_ERROR("sxg: %s ENTER adapter[%p]\n", __FUNCTION__, adapter);
+ DBG_ERROR("sxg: %s ENTER adapter[%p]\n", __func__, adapter);
#if XXXTODO
slic_init_cleanup(adapter);
#endif
@@ -1651,7 +1652,7 @@ static void sxg_deregister_interrupt(p_adapter_t adapter)
adapter->rcv_broadcasts = 0;
adapter->rcv_multicasts = 0;
adapter->rcv_unicasts = 0;
- DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s EXIT\n", __func__);
}
/*
@@ -1666,7 +1667,7 @@ static int sxg_if_init(p_adapter_t adapter)
int status = 0;
DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d:%d] flags[%x]\n",
- __FUNCTION__, adapter->netdev->name,
+ __func__, adapter->netdev->name,
adapter->queues_initialized, adapter->state,
adapter->linkstate, dev->flags);
@@ -1680,7 +1681,7 @@ static int sxg_if_init(p_adapter_t adapter)
adapter->devflags_prev = dev->flags;
adapter->macopts = MAC_DIRECTED;
if (dev->flags) {
- DBG_ERROR("sxg: %s (%s) Set MAC options: ", __FUNCTION__,
+ DBG_ERROR("sxg: %s (%s) Set MAC options: ", __func__,
adapter->netdev->name);
if (dev->flags & IFF_BROADCAST) {
adapter->macopts |= MAC_BCAST;
@@ -1713,7 +1714,7 @@ static int sxg_if_init(p_adapter_t adapter)
/*
* clear any pending events, then enable interrupts
*/
- DBG_ERROR("sxg: %s ENABLE interrupts(slic)\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENABLE interrupts(slic)\n", __func__);
return (STATUS_SUCCESS);
}
@@ -1724,11 +1725,11 @@ static int sxg_entry_open(p_net_device dev)
int status;
ASSERT(adapter);
- DBG_ERROR("sxg: %s adapter->activated[%d]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s adapter->activated[%d]\n", __func__,
adapter->activated);
DBG_ERROR
("sxg: %s (%s): [jiffies[%lx] cpu %d] dev[%p] adapt[%p] port[%d]\n",
- __FUNCTION__, adapter->netdev->name, jiffies, smp_processor_id(),
+ __func__, adapter->netdev->name, jiffies, smp_processor_id(),
adapter->netdev, adapter, adapter->port);
netif_stop_queue(adapter->netdev);
@@ -1738,16 +1739,16 @@ static int sxg_entry_open(p_net_device dev)
sxg_global.num_sxg_ports_active++;
adapter->activated = 1;
}
- // Initialize the adapter
- DBG_ERROR("sxg: %s ENTER sxg_initialize_adapter\n", __FUNCTION__);
+ /* Initialize the adapter */
+ DBG_ERROR("sxg: %s ENTER sxg_initialize_adapter\n", __func__);
status = sxg_initialize_adapter(adapter);
DBG_ERROR("sxg: %s EXIT sxg_initialize_adapter status[%x]\n",
- __FUNCTION__, status);
+ __func__, status);
if (status == STATUS_SUCCESS) {
- DBG_ERROR("sxg: %s ENTER sxg_if_init\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENTER sxg_if_init\n", __func__);
status = sxg_if_init(adapter);
- DBG_ERROR("sxg: %s EXIT sxg_if_init status[%x]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s EXIT sxg_if_init status[%x]\n", __func__,
status);
}
@@ -1760,12 +1761,12 @@ static int sxg_entry_open(p_net_device dev)
sxg_global.flags);
return (status);
}
- DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __func__);
- // Enable interrupts
+ /* Enable interrupts */
SXG_ENABLE_ALL_INTERRUPTS(adapter);
- DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s EXIT\n", __func__);
spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
return STATUS_SUCCESS;
@@ -1779,27 +1780,27 @@ static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
ASSERT(adapter);
- DBG_ERROR("sxg: %s ENTER dev[%p] adapter[%p]\n", __FUNCTION__, dev,
+ DBG_ERROR("sxg: %s ENTER dev[%p] adapter[%p]\n", __func__, dev,
adapter);
sxg_deregister_interrupt(adapter);
sxg_unmap_mmio_space(adapter);
- DBG_ERROR("sxg: %s unregister_netdev\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s unregister_netdev\n", __func__);
unregister_netdev(dev);
mmio_start = pci_resource_start(pcidev, 0);
mmio_len = pci_resource_len(pcidev, 0);
- DBG_ERROR("sxg: %s rel_region(0) start[%x] len[%x]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s rel_region(0) start[%x] len[%x]\n", __func__,
mmio_start, mmio_len);
release_mem_region(mmio_start, mmio_len);
- DBG_ERROR("sxg: %s iounmap dev->base_addr[%x]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s iounmap dev->base_addr[%x]\n", __func__,
(unsigned int)dev->base_addr);
iounmap((char *)dev->base_addr);
- DBG_ERROR("sxg: %s deallocate device\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s deallocate device\n", __func__);
kfree(dev);
- DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s EXIT\n", __func__);
}
static int sxg_entry_halt(p_net_device dev)
@@ -1807,17 +1808,17 @@ static int sxg_entry_halt(p_net_device dev)
p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
- DBG_ERROR("sxg: %s (%s) ENTER\n", __FUNCTION__, dev->name);
+ DBG_ERROR("sxg: %s (%s) ENTER\n", __func__, dev->name);
netif_stop_queue(adapter->netdev);
adapter->state = ADAPT_DOWN;
adapter->linkstate = LINK_DOWN;
adapter->devflags_prev = 0;
DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n",
- __FUNCTION__, dev->name, adapter, adapter->state);
+ __func__, dev->name, adapter, adapter->state);
- DBG_ERROR("sxg: %s (%s) EXIT\n", __FUNCTION__, dev->name);
- DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+ DBG_ERROR("sxg: %s (%s) EXIT\n", __func__, dev->name);
+ DBG_ERROR("sxg: %s EXIT\n", __func__);
spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
return (STATUS_SUCCESS);
}
@@ -1825,11 +1826,11 @@ static int sxg_entry_halt(p_net_device dev)
static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd)
{
ASSERT(rq);
-// DBG_ERROR("sxg: %s cmd[%x] rq[%p] dev[%p]\n", __FUNCTION__, cmd, rq, dev);
+/* DBG_ERROR("sxg: %s cmd[%x] rq[%p] dev[%p]\n", __func__, cmd, rq, dev); */
switch (cmd) {
case SIOCSLICSETINTAGG:
{
-// p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+/* p_adapter_t adapter = (p_adapter_t) netdev_priv(dev); */
u32 data[7];
u32 intagg;
@@ -1841,12 +1842,12 @@ static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd)
intagg = data[0];
printk(KERN_EMERG
"%s: set interrupt aggregation to %d\n",
- __FUNCTION__, intagg);
+ __func__, intagg);
return 0;
}
default:
-// DBG_ERROR("sxg: %s UNSUPPORTED[%x]\n", __FUNCTION__, cmd);
+/* DBG_ERROR("sxg: %s UNSUPPORTED[%x]\n", __func__, cmd); */
return -EOPNOTSUPP;
}
return 0;
@@ -1870,15 +1871,15 @@ static int sxg_send_packets(struct sk_buff *skb, p_net_device dev)
p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
u32 status = STATUS_SUCCESS;
- DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __func__,
skb);
- // Check the adapter state
+ /* Check the adapter state */
switch (adapter->State) {
case SXG_STATE_INITIALIZING:
case SXG_STATE_HALTED:
case SXG_STATE_SHUTDOWN:
- ASSERT(0); // unexpected
- // fall through
+ ASSERT(0); /* unexpected */
+ /* fall through */
case SXG_STATE_RESETTING:
case SXG_STATE_SLEEP:
case SXG_STATE_BOOTDIAG:
@@ -1898,23 +1899,23 @@ static int sxg_send_packets(struct sk_buff *skb, p_net_device dev)
if (status != STATUS_SUCCESS) {
goto xmit_fail;
}
- // send a packet
+ /* send a packet */
status = sxg_transmit_packet(adapter, skb);
if (status == STATUS_SUCCESS) {
goto xmit_done;
}
xmit_fail:
- // reject & complete all the packets if they cant be sent
+ /* reject & complete all the packets if they cant be sent */
if (status != STATUS_SUCCESS) {
#if XXXTODO
-// sxg_send_packets_fail(adapter, skb, status);
+/* sxg_send_packets_fail(adapter, skb, status); */
#else
SXG_DROP_DUMB_SEND(adapter, skb);
adapter->stats.tx_dropped++;
#endif
}
- DBG_ERROR("sxg: %s EXIT sxg_send_packets status[%x]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s EXIT sxg_send_packets status[%x]\n", __func__,
status);
xmit_done:
@@ -1940,12 +1941,12 @@ static int sxg_transmit_packet(p_adapter_t adapter, struct sk_buff *skb)
void *SglBuffer;
u32 SglBufferLength;
- // The vast majority of work is done in the shared
- // sxg_dumb_sgl routine.
+ /* The vast majority of work is done in the shared */
+ /* sxg_dumb_sgl routine. */
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSend",
adapter, skb, 0, 0);
- // Allocate a SGL buffer
+ /* Allocate a SGL buffer */
SXG_GET_SGL_BUFFER(adapter, SxgSgl);
if (!SxgSgl) {
adapter->Stats.NoSglBuf++;
@@ -1963,9 +1964,9 @@ static int sxg_transmit_packet(p_adapter_t adapter, struct sk_buff *skb)
SxgSgl->DumbPacket = skb;
pSgl = NULL;
- // Call the common sxg_dumb_sgl routine to complete the send.
+ /* Call the common sxg_dumb_sgl routine to complete the send. */
sxg_dumb_sgl(pSgl, SxgSgl);
- // Return success sxg_dumb_sgl (or something later) will complete it.
+ /* Return success sxg_dumb_sgl (or something later) will complete it. */
return (STATUS_SUCCESS);
}
@@ -1983,39 +1984,39 @@ static void sxg_dumb_sgl(PSCATTER_GATHER_LIST pSgl, PSXG_SCATTER_GATHER SxgSgl)
{
p_adapter_t adapter = SxgSgl->adapter;
struct sk_buff *skb = SxgSgl->DumbPacket;
- // For now, all dumb-nic sends go on RSS queue zero
+ /* For now, all dumb-nic sends go on RSS queue zero */
PSXG_XMT_RING XmtRing = &adapter->XmtRings[0];
PSXG_RING_INFO XmtRingInfo = &adapter->XmtRingZeroInfo;
PSXG_CMD XmtCmd = NULL;
-// u32 Index = 0;
+/* u32 Index = 0; */
u32 DataLength = skb->len;
-// unsigned int BufLen;
-// u32 SglOffset;
+/* unsigned int BufLen; */
+/* u32 SglOffset; */
u64 phys_addr;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
pSgl, SxgSgl, 0, 0);
- // Set aside a pointer to the sgl
+ /* Set aside a pointer to the sgl */
SxgSgl->pSgl = pSgl;
- // Sanity check that our SGL format is as we expect.
+ /* Sanity check that our SGL format is as we expect. */
ASSERT(sizeof(SXG_X64_SGE) == sizeof(SCATTER_GATHER_ELEMENT));
- // Shouldn't be a vlan tag on this frame
+ /* Shouldn't be a vlan tag on this frame */
ASSERT(SxgSgl->VlanTag.VlanTci == 0);
ASSERT(SxgSgl->VlanTag.VlanTpid == 0);
- // From here below we work with the SGL placed in our
- // buffer.
+ /* From here below we work with the SGL placed in our */
+ /* buffer. */
SxgSgl->Sgl.NumberOfElements = 1;
- // Grab the spinlock and acquire a command
+ /* Grab the spinlock and acquire a command */
spin_lock(&adapter->XmtZeroLock);
SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
if (XmtCmd == NULL) {
- // Call sxg_complete_slow_send to see if we can
- // free up any XmtRingZero entries and then try again
+ /* Call sxg_complete_slow_send to see if we can */
+ /* free up any XmtRingZero entries and then try again */
spin_unlock(&adapter->XmtZeroLock);
sxg_complete_slow_send(adapter);
spin_lock(&adapter->XmtZeroLock);
@@ -2027,10 +2028,10 @@ static void sxg_dumb_sgl(PSCATTER_GATHER_LIST pSgl, PSXG_SCATTER_GATHER SxgSgl)
}
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
- // Update stats
+ /* Update stats */
adapter->Stats.DumbXmtPkts++;
adapter->Stats.DumbXmtBytes += DataLength;
-#if XXXTODO // Stats stuff
+#if XXXTODO /* Stats stuff */
if (SXG_MULTICAST_PACKET(EtherHdr)) {
if (SXG_BROADCAST_PACKET(EtherHdr)) {
adapter->Stats.DumbXmtBcastPkts++;
@@ -2044,8 +2045,8 @@ static void sxg_dumb_sgl(PSCATTER_GATHER_LIST pSgl, PSXG_SCATTER_GATHER SxgSgl)
adapter->Stats.DumbXmtUcastBytes += DataLength;
}
#endif
- // Fill in the command
- // Copy out the first SGE to the command and adjust for offset
+ /* Fill in the command */
+ /* Copy out the first SGE to the command and adjust for offset */
phys_addr =
pci_map_single(adapter->pcidev, skb->data, skb->len,
PCI_DMA_TODEVICE);
@@ -2053,54 +2054,54 @@ static void sxg_dumb_sgl(PSCATTER_GATHER_LIST pSgl, PSXG_SCATTER_GATHER SxgSgl)
XmtCmd->Buffer.FirstSgeAddress = XmtCmd->Buffer.FirstSgeAddress << 32;
XmtCmd->Buffer.FirstSgeAddress =
XmtCmd->Buffer.FirstSgeAddress | SXG_GET_ADDR_LOW(phys_addr);
-// XmtCmd->Buffer.FirstSgeAddress = SxgSgl->Sgl.Elements[Index].Address;
-// XmtCmd->Buffer.FirstSgeAddress.LowPart += MdlOffset;
+/* XmtCmd->Buffer.FirstSgeAddress = SxgSgl->Sgl.Elements[Index].Address; */
+/* XmtCmd->Buffer.FirstSgeAddress.LowPart += MdlOffset; */
XmtCmd->Buffer.FirstSgeLength = DataLength;
- // Set a pointer to the remaining SGL entries
-// XmtCmd->Sgl = SxgSgl->PhysicalAddress;
- // Advance the physical address of the SxgSgl structure to
- // the second SGE
-// SglOffset = (u32)((u32 *)(&SxgSgl->Sgl.Elements[Index+1]) -
-// (u32 *)SxgSgl);
-// XmtCmd->Sgl.LowPart += SglOffset;
+ /* Set a pointer to the remaining SGL entries */
+/* XmtCmd->Sgl = SxgSgl->PhysicalAddress; */
+ /* Advance the physical address of the SxgSgl structure to */
+ /* the second SGE */
+/* SglOffset = (u32)((u32 *)(&SxgSgl->Sgl.Elements[Index+1]) - */
+/* (u32 *)SxgSgl); */
+/* XmtCmd->Sgl.LowPart += SglOffset; */
XmtCmd->Buffer.SgeOffset = 0;
- // Note - TotalLength might be overwritten with MSS below..
+ /* Note - TotalLength might be overwritten with MSS below.. */
XmtCmd->Buffer.TotalLength = DataLength;
- XmtCmd->SgEntries = 1; //(ushort)(SxgSgl->Sgl.NumberOfElements - Index);
+ XmtCmd->SgEntries = 1; /*(ushort)(SxgSgl->Sgl.NumberOfElements - Index); */
XmtCmd->Flags = 0;
- //
- // Advance transmit cmd descripter by 1.
- // NOTE - See comments in SxgTcpOutput where we write
- // to the XmtCmd register regarding CPU ID values and/or
- // multiple commands.
- //
- //
+ /* */
+ /* Advance transmit cmd descripter by 1. */
+ /* NOTE - See comments in SxgTcpOutput where we write */
+ /* to the XmtCmd register regarding CPU ID values and/or */
+ /* multiple commands. */
+ /* */
+ /* */
WRITE_REG(adapter->UcodeRegs[0].XmtCmd, 1, TRUE);
- //
- //
- adapter->Stats.XmtQLen++; // Stats within lock
+ /* */
+ /* */
+ adapter->Stats.XmtQLen++; /* Stats within lock */
spin_unlock(&adapter->XmtZeroLock);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
XmtCmd, pSgl, SxgSgl, 0);
return;
abortcmd:
- // NOTE - Only jump to this label AFTER grabbing the
- // XmtZeroLock, and DO NOT DROP IT between the
- // command allocation and the following abort.
+ /* NOTE - Only jump to this label AFTER grabbing the */
+ /* XmtZeroLock, and DO NOT DROP IT between the */
+ /* command allocation and the following abort. */
if (XmtCmd) {
SXG_ABORT_CMD(XmtRingInfo);
}
spin_unlock(&adapter->XmtZeroLock);
-// failsgl:
- // Jump to this label if failure occurs before the
- // XmtZeroLock is grabbed
+/* failsgl: */
+ /* Jump to this label if failure occurs before the */
+ /* XmtZeroLock is grabbed */
adapter->Stats.XmtErrors++;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumSGFal",
pSgl, SxgSgl, XmtRingInfo->Head, XmtRingInfo->Tail);
- SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket); // SxgSgl->DumbPacket is the skb
+ SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket); /* SxgSgl->DumbPacket is the skb */
}
/***************************************************************
@@ -2127,122 +2128,122 @@ static int sxg_initialize_link(p_adapter_t adapter)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitLink",
adapter, 0, 0, 0);
- // Reset PHY and XGXS module
+ /* Reset PHY and XGXS module */
WRITE_REG(HwRegs->LinkStatus, LS_SERDES_POWER_DOWN, TRUE);
- // Reset transmit configuration register
+ /* Reset transmit configuration register */
WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_RESET, TRUE);
- // Reset receive configuration register
+ /* Reset receive configuration register */
WRITE_REG(HwRegs->RcvConfig, RCV_CONFIG_RESET, TRUE);
- // Reset all MAC modules
+ /* Reset all MAC modules */
WRITE_REG(HwRegs->MacConfig0, AXGMAC_CFG0_SUB_RESET, TRUE);
- // Link address 0
- // XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f)
- // is stored with the first nibble (0a) in the byte 0
- // of the Mac address. Possibly reverse?
+ /* Link address 0 */
+ /* XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f) */
+ /* is stored with the first nibble (0a) in the byte 0 */
+ /* of the Mac address. Possibly reverse? */
Value = *(u32 *) adapter->MacAddr;
WRITE_REG(HwRegs->LinkAddress0Low, Value, TRUE);
- // also write the MAC address to the MAC. Endian is reversed.
+ /* also write the MAC address to the MAC. Endian is reversed. */
WRITE_REG(HwRegs->MacAddressLow, ntohl(Value), TRUE);
Value = (*(u16 *) & adapter->MacAddr[4] & 0x0000FFFF);
WRITE_REG(HwRegs->LinkAddress0High, Value | LINK_ADDRESS_ENABLE, TRUE);
- // endian swap for the MAC (put high bytes in bits [31:16], swapped)
+ /* endian swap for the MAC (put high bytes in bits [31:16], swapped) */
Value = ntohl(Value);
WRITE_REG(HwRegs->MacAddressHigh, Value, TRUE);
- // Link address 1
+ /* Link address 1 */
WRITE_REG(HwRegs->LinkAddress1Low, 0, TRUE);
WRITE_REG(HwRegs->LinkAddress1High, 0, TRUE);
- // Link address 2
+ /* Link address 2 */
WRITE_REG(HwRegs->LinkAddress2Low, 0, TRUE);
WRITE_REG(HwRegs->LinkAddress2High, 0, TRUE);
- // Link address 3
+ /* Link address 3 */
WRITE_REG(HwRegs->LinkAddress3Low, 0, TRUE);
WRITE_REG(HwRegs->LinkAddress3High, 0, TRUE);
- // Enable MAC modules
+ /* Enable MAC modules */
WRITE_REG(HwRegs->MacConfig0, 0, TRUE);
- // Configure MAC
- WRITE_REG(HwRegs->MacConfig1, (AXGMAC_CFG1_XMT_PAUSE | // Allow sending of pause
- AXGMAC_CFG1_XMT_EN | // Enable XMT
- AXGMAC_CFG1_RCV_PAUSE | // Enable detection of pause
- AXGMAC_CFG1_RCV_EN | // Enable receive
- AXGMAC_CFG1_SHORT_ASSERT | // short frame detection
- AXGMAC_CFG1_CHECK_LEN | // Verify frame length
- AXGMAC_CFG1_GEN_FCS | // Generate FCS
- AXGMAC_CFG1_PAD_64), // Pad frames to 64 bytes
+ /* Configure MAC */
+ WRITE_REG(HwRegs->MacConfig1, (AXGMAC_CFG1_XMT_PAUSE | /* Allow sending of pause */
+ AXGMAC_CFG1_XMT_EN | /* Enable XMT */
+ AXGMAC_CFG1_RCV_PAUSE | /* Enable detection of pause */
+ AXGMAC_CFG1_RCV_EN | /* Enable receive */
+ AXGMAC_CFG1_SHORT_ASSERT | /* short frame detection */
+ AXGMAC_CFG1_CHECK_LEN | /* Verify frame length */
+ AXGMAC_CFG1_GEN_FCS | /* Generate FCS */
+ AXGMAC_CFG1_PAD_64), /* Pad frames to 64 bytes */
TRUE);
- // Set AXGMAC max frame length if jumbo. Not needed for standard MTU
+ /* Set AXGMAC max frame length if jumbo. Not needed for standard MTU */
if (adapter->JumboEnabled) {
WRITE_REG(HwRegs->MacMaxFrameLen, AXGMAC_MAXFRAME_JUMBO, TRUE);
}
- // AMIIM Configuration Register -
- // The value placed in the AXGMAC_AMIIM_CFG_HALF_CLOCK portion
- // (bottom bits) of this register is used to determine the
- // MDC frequency as specified in the A-XGMAC Design Document.
- // This value must not be zero. The following value (62 or 0x3E)
- // is based on our MAC transmit clock frequency (MTCLK) of 312.5 MHz.
- // Given a maximum MDIO clock frequency of 2.5 MHz (see the PHY spec),
- // we get: 312.5/(2*(X+1)) < 2.5 ==> X = 62.
- // This value happens to be the default value for this register,
- // so we really don't have to do this.
+ /* AMIIM Configuration Register - */
+ /* The value placed in the AXGMAC_AMIIM_CFG_HALF_CLOCK portion */
+ /* (bottom bits) of this register is used to determine the */
+ /* MDC frequency as specified in the A-XGMAC Design Document. */
+ /* This value must not be zero. The following value (62 or 0x3E) */
+ /* is based on our MAC transmit clock frequency (MTCLK) of 312.5 MHz. */
+ /* Given a maximum MDIO clock frequency of 2.5 MHz (see the PHY spec), */
+ /* we get: 312.5/(2*(X+1)) < 2.5 ==> X = 62. */
+ /* This value happens to be the default value for this register, */
+ /* so we really don't have to do this. */
WRITE_REG(HwRegs->MacAmiimConfig, 0x0000003E, TRUE);
- // Power up and enable PHY and XAUI/XGXS/Serdes logic
+ /* Power up and enable PHY and XAUI/XGXS/Serdes logic */
WRITE_REG(HwRegs->LinkStatus,
(LS_PHY_CLR_RESET |
LS_XGXS_ENABLE |
LS_XGXS_CTL | LS_PHY_CLK_EN | LS_ATTN_ALARM), TRUE);
DBG_ERROR("After Power Up and enable PHY in sxg_initialize_link\n");
- // Per information given by Aeluros, wait 100 ms after removing reset.
- // It's not enough to wait for the self-clearing reset bit in reg 0 to clear.
+ /* Per information given by Aeluros, wait 100 ms after removing reset. */
+ /* It's not enough to wait for the self-clearing reset bit in reg 0 to clear. */
mdelay(100);
- // Verify the PHY has come up by checking that the Reset bit has cleared.
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- PHY_PMA_CONTROL1, // PMA/PMD control register
+ /* Verify the PHY has come up by checking that the Reset bit has cleared. */
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ PHY_PMA_CONTROL1, /* PMA/PMD control register */
&Value);
if (status != STATUS_SUCCESS)
return (STATUS_FAILURE);
- if (Value & PMA_CONTROL1_RESET) // reset complete if bit is 0
+ if (Value & PMA_CONTROL1_RESET) /* reset complete if bit is 0 */
return (STATUS_FAILURE);
- // The SERDES should be initialized by now - confirm
+ /* The SERDES should be initialized by now - confirm */
READ_REG(HwRegs->LinkStatus, Value);
- if (Value & LS_SERDES_DOWN) // verify SERDES is initialized
+ if (Value & LS_SERDES_DOWN) /* verify SERDES is initialized */
return (STATUS_FAILURE);
- // The XAUI link should also be up - confirm
- if (!(Value & LS_XAUI_LINK_UP)) // verify XAUI link is up
+ /* The XAUI link should also be up - confirm */
+ if (!(Value & LS_XAUI_LINK_UP)) /* verify XAUI link is up */
return (STATUS_FAILURE);
- // Initialize the PHY
+ /* Initialize the PHY */
status = sxg_phy_init(adapter);
if (status != STATUS_SUCCESS)
return (STATUS_FAILURE);
- // Enable the Link Alarm
- status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- LASI_CONTROL, // LASI control register
- LASI_CTL_LS_ALARM_ENABLE); // enable link alarm bit
+ /* Enable the Link Alarm */
+ status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ LASI_CONTROL, /* LASI control register */
+ LASI_CTL_LS_ALARM_ENABLE); /* enable link alarm bit */
if (status != STATUS_SUCCESS)
return (STATUS_FAILURE);
- // XXXTODO - temporary - verify bit is set
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- LASI_CONTROL, // LASI control register
+ /* XXXTODO - temporary - verify bit is set */
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ LASI_CONTROL, /* LASI control register */
&Value);
if (status != STATUS_SUCCESS)
return (STATUS_FAILURE);
if (!(Value & LASI_CTL_LS_ALARM_ENABLE)) {
DBG_ERROR("Error! LASI Control Alarm Enable bit not set!\n");
}
- // Enable receive
+ /* Enable receive */
MaxFrame = adapter->JumboEnabled ? JUMBOMAXFRAME : ETHERMAXFRAME;
ConfigData = (RCV_CONFIG_ENABLE |
RCV_CONFIG_ENPARSE |
@@ -2256,7 +2257,7 @@ static int sxg_initialize_link(p_adapter_t adapter)
WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_ENABLE, TRUE);
- // Mark the link as down. We'll get a link event when it comes up.
+ /* Mark the link as down. We'll get a link event when it comes up. */
sxg_link_state(adapter, SXG_LINK_DOWN);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInitLnk",
@@ -2279,35 +2280,35 @@ static int sxg_phy_init(p_adapter_t adapter)
PPHY_UCODE p;
int status;
- DBG_ERROR("ENTER %s\n", __FUNCTION__);
+ DBG_ERROR("ENTER %s\n", __func__);
- // Read a register to identify the PHY type
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- 0xC205, // PHY ID register (?)
- &Value); // XXXTODO - add def
+ /* Read a register to identify the PHY type */
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ 0xC205, /* PHY ID register (?) */
+ &Value); /* XXXTODO - add def */
if (status != STATUS_SUCCESS)
return (STATUS_FAILURE);
- if (Value == 0x0012) { // 0x0012 == AEL2005C PHY(?) - XXXTODO - add def
+ if (Value == 0x0012) { /* 0x0012 == AEL2005C PHY(?) - XXXTODO - add def */
DBG_ERROR
("AEL2005C PHY detected. Downloading PHY microcode.\n");
- // Initialize AEL2005C PHY and download PHY microcode
+ /* Initialize AEL2005C PHY and download PHY microcode */
for (p = PhyUcode; p->Addr != 0xFFFF; p++) {
if (p->Addr == 0) {
- // if address == 0, data == sleep time in ms
+ /* if address == 0, data == sleep time in ms */
mdelay(p->Data);
} else {
- // write the given data to the specified address
- status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- p->Addr, // PHY address
- p->Data); // PHY data
+ /* write the given data to the specified address */
+ status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ p->Addr, /* PHY address */
+ p->Data); /* PHY data */
if (status != STATUS_SUCCESS)
return (STATUS_FAILURE);
}
}
}
- DBG_ERROR("EXIT %s\n", __FUNCTION__);
+ DBG_ERROR("EXIT %s\n", __func__);
return (STATUS_SUCCESS);
}
@@ -2330,42 +2331,42 @@ static void sxg_link_event(p_adapter_t adapter)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "LinkEvnt",
adapter, 0, 0, 0);
- DBG_ERROR("ENTER %s\n", __FUNCTION__);
+ DBG_ERROR("ENTER %s\n", __func__);
- // Check the Link Status register. We should have a Link Alarm.
+ /* Check the Link Status register. We should have a Link Alarm. */
READ_REG(HwRegs->LinkStatus, Value);
if (Value & LS_LINK_ALARM) {
- // We got a Link Status alarm. First, pause to let the
- // link state settle (it can bounce a number of times)
+ /* We got a Link Status alarm. First, pause to let the */
+ /* link state settle (it can bounce a number of times) */
mdelay(10);
- // Now clear the alarm by reading the LASI status register.
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- LASI_STATUS, // LASI status register
+ /* Now clear the alarm by reading the LASI status register. */
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ LASI_STATUS, /* LASI status register */
&Value);
if (status != STATUS_SUCCESS) {
DBG_ERROR("Error reading LASI Status MDIO register!\n");
sxg_link_state(adapter, SXG_LINK_DOWN);
-// ASSERT(0);
+/* ASSERT(0); */
}
ASSERT(Value & LASI_STATUS_LS_ALARM);
- // Now get and set the link state
+ /* Now get and set the link state */
LinkState = sxg_get_link_state(adapter);
sxg_link_state(adapter, LinkState);
DBG_ERROR("SXG: Link Alarm occurred. Link is %s\n",
((LinkState == SXG_LINK_UP) ? "UP" : "DOWN"));
} else {
- // XXXTODO - Assuming Link Attention is only being generated for the
- // Link Alarm pin (and not for a XAUI Link Status change), then it's
- // impossible to get here. Yet we've gotten here twice (under extreme
- // conditions - bouncing the link up and down many times a second).
- // Needs further investigation.
+ /* XXXTODO - Assuming Link Attention is only being generated for the */
+ /* Link Alarm pin (and not for a XAUI Link Status change), then it's */
+ /* impossible to get here. Yet we've gotten here twice (under extreme */
+ /* conditions - bouncing the link up and down many times a second). */
+ /* Needs further investigation. */
DBG_ERROR("SXG: sxg_link_event: Can't get here!\n");
DBG_ERROR("SXG: Link Status == 0x%08X.\n", Value);
-// ASSERT(0);
+/* ASSERT(0); */
}
- DBG_ERROR("EXIT %s\n", __FUNCTION__);
+ DBG_ERROR("EXIT %s\n", __func__);
}
@@ -2383,50 +2384,50 @@ static SXG_LINK_STATE sxg_get_link_state(p_adapter_t adapter)
int status;
u32 Value;
- DBG_ERROR("ENTER %s\n", __FUNCTION__);
+ DBG_ERROR("ENTER %s\n", __func__);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "GetLink",
adapter, 0, 0, 0);
- // Per the Xenpak spec (and the IEEE 10Gb spec?), the link is up if
- // the following 3 bits (from 3 different MDIO registers) are all true.
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
- PHY_PMA_RCV_DET, // PMA/PMD Receive Signal Detect register
+ /* Per the Xenpak spec (and the IEEE 10Gb spec?), the link is up if */
+ /* the following 3 bits (from 3 different MDIO registers) are all true. */
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
+ PHY_PMA_RCV_DET, /* PMA/PMD Receive Signal Detect register */
&Value);
if (status != STATUS_SUCCESS)
goto bad;
- // If PMA/PMD receive signal detect is 0, then the link is down
+ /* If PMA/PMD receive signal detect is 0, then the link is down */
if (!(Value & PMA_RCV_DETECT))
return (SXG_LINK_DOWN);
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PCS, // PHY PCS module
- PHY_PCS_10G_STATUS1, // PCS 10GBASE-R Status 1 register
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PCS, /* PHY PCS module */
+ PHY_PCS_10G_STATUS1, /* PCS 10GBASE-R Status 1 register */
&Value);
if (status != STATUS_SUCCESS)
goto bad;
- // If PCS is not locked to receive blocks, then the link is down
+ /* If PCS is not locked to receive blocks, then the link is down */
if (!(Value & PCS_10B_BLOCK_LOCK))
return (SXG_LINK_DOWN);
- status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_XS, // PHY XS module
- PHY_XS_LANE_STATUS, // XS Lane Status register
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_XS, /* PHY XS module */
+ PHY_XS_LANE_STATUS, /* XS Lane Status register */
&Value);
if (status != STATUS_SUCCESS)
goto bad;
- // If XS transmit lanes are not aligned, then the link is down
+ /* If XS transmit lanes are not aligned, then the link is down */
if (!(Value & XS_LANE_ALIGN))
return (SXG_LINK_DOWN);
- // All 3 bits are true, so the link is up
- DBG_ERROR("EXIT %s\n", __FUNCTION__);
+ /* All 3 bits are true, so the link is up */
+ DBG_ERROR("EXIT %s\n", __func__);
return (SXG_LINK_UP);
bad:
- // An error occurred reading an MDIO register. This shouldn't happen.
+ /* An error occurred reading an MDIO register. This shouldn't happen. */
DBG_ERROR("Error reading an MDIO register!\n");
ASSERT(0);
return (SXG_LINK_DOWN);
@@ -2437,11 +2438,11 @@ static void sxg_indicate_link_state(p_adapter_t adapter,
{
if (adapter->LinkState == SXG_LINK_UP) {
DBG_ERROR("%s: LINK now UP, call netif_start_queue\n",
- __FUNCTION__);
+ __func__);
netif_start_queue(adapter->netdev);
} else {
DBG_ERROR("%s: LINK now DOWN, call netif_stop_queue\n",
- __FUNCTION__);
+ __func__);
netif_stop_queue(adapter->netdev);
}
}
@@ -2464,23 +2465,23 @@ static void sxg_link_state(p_adapter_t adapter, SXG_LINK_STATE LinkState)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "LnkINDCT",
adapter, LinkState, adapter->LinkState, adapter->State);
- DBG_ERROR("ENTER %s\n", __FUNCTION__);
+ DBG_ERROR("ENTER %s\n", __func__);
- // Hold the adapter lock during this routine. Maybe move
- // the lock to the caller.
+ /* Hold the adapter lock during this routine. Maybe move */
+ /* the lock to the caller. */
spin_lock(&adapter->AdapterLock);
if (LinkState == adapter->LinkState) {
- // Nothing changed..
+ /* Nothing changed.. */
spin_unlock(&adapter->AdapterLock);
- DBG_ERROR("EXIT #0 %s\n", __FUNCTION__);
+ DBG_ERROR("EXIT #0 %s\n", __func__);
return;
}
- // Save the adapter state
+ /* Save the adapter state */
adapter->LinkState = LinkState;
- // Drop the lock and indicate link state
+ /* Drop the lock and indicate link state */
spin_unlock(&adapter->AdapterLock);
- DBG_ERROR("EXIT #1 %s\n", __FUNCTION__);
+ DBG_ERROR("EXIT #1 %s\n", __func__);
sxg_indicate_link_state(adapter, LinkState);
}
@@ -2501,76 +2502,76 @@ static int sxg_write_mdio_reg(p_adapter_t adapter,
u32 DevAddr, u32 RegAddr, u32 Value)
{
PSXG_HW_REGS HwRegs = adapter->HwRegs;
- u32 AddrOp; // Address operation (written to MIIM field reg)
- u32 WriteOp; // Write operation (written to MIIM field reg)
- u32 Cmd; // Command (written to MIIM command reg)
+ u32 AddrOp; /* Address operation (written to MIIM field reg) */
+ u32 WriteOp; /* Write operation (written to MIIM field reg) */
+ u32 Cmd; /* Command (written to MIIM command reg) */
u32 ValueRead;
u32 Timeout;
-// DBG_ERROR("ENTER %s\n", __FUNCTION__);
+/* DBG_ERROR("ENTER %s\n", __func__); */
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO",
adapter, 0, 0, 0);
- // Ensure values don't exceed field width
- DevAddr &= 0x001F; // 5-bit field
- RegAddr &= 0xFFFF; // 16-bit field
- Value &= 0xFFFF; // 16-bit field
+ /* Ensure values don't exceed field width */
+ DevAddr &= 0x001F; /* 5-bit field */
+ RegAddr &= 0xFFFF; /* 16-bit field */
+ Value &= 0xFFFF; /* 16-bit field */
- // Set MIIM field register bits for an MIIM address operation
+ /* Set MIIM field register bits for an MIIM address operation */
AddrOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
(DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
(MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
(MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) | RegAddr;
- // Set MIIM field register bits for an MIIM write operation
+ /* Set MIIM field register bits for an MIIM write operation */
WriteOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
(DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
(MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
(MIIM_OP_WRITE << AXGMAC_AMIIM_FIELD_OP_SHIFT) | Value;
- // Set MIIM command register bits to execute an MIIM command
+ /* Set MIIM command register bits to execute an MIIM command */
Cmd = AXGMAC_AMIIM_CMD_START | AXGMAC_AMIIM_CMD_10G_OPERATION;
- // Reset the command register command bit (in case it's not 0)
+ /* Reset the command register command bit (in case it's not 0) */
WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
- // MIIM write to set the address of the specified MDIO register
+ /* MIIM write to set the address of the specified MDIO register */
WRITE_REG(HwRegs->MacAmiimField, AddrOp, TRUE);
- // Write to MIIM Command Register to execute to address operation
+ /* Write to MIIM Command Register to execute to address operation */
WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
- // Poll AMIIM Indicator register to wait for completion
+ /* Poll AMIIM Indicator register to wait for completion */
Timeout = SXG_LINK_TIMEOUT;
do {
- udelay(100); // Timeout in 100us units
+ udelay(100); /* Timeout in 100us units */
READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
if (--Timeout == 0) {
return (STATUS_FAILURE);
}
} while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
- // Reset the command register command bit
+ /* Reset the command register command bit */
WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
- // MIIM write to set up an MDIO write operation
+ /* MIIM write to set up an MDIO write operation */
WRITE_REG(HwRegs->MacAmiimField, WriteOp, TRUE);
- // Write to MIIM Command Register to execute the write operation
+ /* Write to MIIM Command Register to execute the write operation */
WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
- // Poll AMIIM Indicator register to wait for completion
+ /* Poll AMIIM Indicator register to wait for completion */
Timeout = SXG_LINK_TIMEOUT;
do {
- udelay(100); // Timeout in 100us units
+ udelay(100); /* Timeout in 100us units */
READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
if (--Timeout == 0) {
return (STATUS_FAILURE);
}
} while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
-// DBG_ERROR("EXIT %s\n", __FUNCTION__);
+/* DBG_ERROR("EXIT %s\n", __func__); */
return (STATUS_SUCCESS);
}
@@ -2591,110 +2592,78 @@ static int sxg_read_mdio_reg(p_adapter_t adapter,
u32 DevAddr, u32 RegAddr, u32 *pValue)
{
PSXG_HW_REGS HwRegs = adapter->HwRegs;
- u32 AddrOp; // Address operation (written to MIIM field reg)
- u32 ReadOp; // Read operation (written to MIIM field reg)
- u32 Cmd; // Command (written to MIIM command reg)
+ u32 AddrOp; /* Address operation (written to MIIM field reg) */
+ u32 ReadOp; /* Read operation (written to MIIM field reg) */
+ u32 Cmd; /* Command (written to MIIM command reg) */
u32 ValueRead;
u32 Timeout;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO",
adapter, 0, 0, 0);
-// DBG_ERROR("ENTER %s\n", __FUNCTION__);
+/* DBG_ERROR("ENTER %s\n", __func__); */
- // Ensure values don't exceed field width
- DevAddr &= 0x001F; // 5-bit field
- RegAddr &= 0xFFFF; // 16-bit field
+ /* Ensure values don't exceed field width */
+ DevAddr &= 0x001F; /* 5-bit field */
+ RegAddr &= 0xFFFF; /* 16-bit field */
- // Set MIIM field register bits for an MIIM address operation
+ /* Set MIIM field register bits for an MIIM address operation */
AddrOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
(DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
(MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
(MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) | RegAddr;
- // Set MIIM field register bits for an MIIM read operation
+ /* Set MIIM field register bits for an MIIM read operation */
ReadOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
(DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
(MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
(MIIM_OP_READ << AXGMAC_AMIIM_FIELD_OP_SHIFT);
- // Set MIIM command register bits to execute an MIIM command
+ /* Set MIIM command register bits to execute an MIIM command */
Cmd = AXGMAC_AMIIM_CMD_START | AXGMAC_AMIIM_CMD_10G_OPERATION;
- // Reset the command register command bit (in case it's not 0)
+ /* Reset the command register command bit (in case it's not 0) */
WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
- // MIIM write to set the address of the specified MDIO register
+ /* MIIM write to set the address of the specified MDIO register */
WRITE_REG(HwRegs->MacAmiimField, AddrOp, TRUE);
- // Write to MIIM Command Register to execute to address operation
+ /* Write to MIIM Command Register to execute to address operation */
WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
- // Poll AMIIM Indicator register to wait for completion
+ /* Poll AMIIM Indicator register to wait for completion */
Timeout = SXG_LINK_TIMEOUT;
do {
- udelay(100); // Timeout in 100us units
+ udelay(100); /* Timeout in 100us units */
READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
if (--Timeout == 0) {
return (STATUS_FAILURE);
}
} while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
- // Reset the command register command bit
+ /* Reset the command register command bit */
WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
- // MIIM write to set up an MDIO register read operation
+ /* MIIM write to set up an MDIO register read operation */
WRITE_REG(HwRegs->MacAmiimField, ReadOp, TRUE);
- // Write to MIIM Command Register to execute the read operation
+ /* Write to MIIM Command Register to execute the read operation */
WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
- // Poll AMIIM Indicator register to wait for completion
+ /* Poll AMIIM Indicator register to wait for completion */
Timeout = SXG_LINK_TIMEOUT;
do {
- udelay(100); // Timeout in 100us units
+ udelay(100); /* Timeout in 100us units */
READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
if (--Timeout == 0) {
return (STATUS_FAILURE);
}
} while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
- // Read the MDIO register data back from the field register
+ /* Read the MDIO register data back from the field register */
READ_REG(HwRegs->MacAmiimField, *pValue);
- *pValue &= 0xFFFF; // data is in the lower 16 bits
+ *pValue &= 0xFFFF; /* data is in the lower 16 bits */
-// DBG_ERROR("EXIT %s\n", __FUNCTION__);
-
- return (STATUS_SUCCESS);
-}
-
-/*
- * Allocate a mcast_address structure to hold the multicast address.
- * Link it in.
- */
-static int sxg_mcast_add_list(p_adapter_t adapter, char *address)
-{
- p_mcast_address_t mcaddr, mlist;
- bool equaladdr;
-
- /* Check to see if it already exists */
- mlist = adapter->mcastaddrs;
- while (mlist) {
- ETHER_EQ_ADDR(mlist->address, address, equaladdr);
- if (equaladdr) {
- return (STATUS_SUCCESS);
- }
- mlist = mlist->next;
- }
-
- /* Doesn't already exist. Allocate a structure to hold it */
- mcaddr = kmalloc(sizeof(mcast_address_t), GFP_ATOMIC);
- if (mcaddr == NULL)
- return 1;
-
- memcpy(mcaddr->address, address, 6);
-
- mcaddr->next = adapter->mcastaddrs;
- adapter->mcastaddrs = mcaddr;
+/* DBG_ERROR("EXIT %s\n", __func__); */
return (STATUS_SUCCESS);
}
@@ -2710,7 +2679,6 @@ static int sxg_mcast_add_list(p_adapter_t adapter, char *address)
*
*/
static u32 sxg_crc_table[256]; /* Table of CRC's for all possible byte values */
-static u32 sxg_crc_init; /* Is table initialized */
/*
* Contruct the CRC32 table
@@ -2737,6 +2705,8 @@ static void sxg_mcast_init_crc32(void)
}
}
+#if XXXTODO
+static u32 sxg_crc_init; /* Is table initialized */
/*
* Return the MAC hast as described above.
*/
@@ -2765,6 +2735,74 @@ static unsigned char sxg_mcast_get_mac_hash(char *macaddr)
return (machash);
}
+static void sxg_mcast_set_mask(p_adapter_t adapter)
+{
+ PSXG_UCODE_REGS sxg_regs = adapter->UcodeRegs;
+
+ DBG_ERROR("%s ENTER (%s) macopts[%x] mask[%llx]\n", __func__,
+ adapter->netdev->name, (unsigned int)adapter->MacFilter,
+ adapter->MulticastMask);
+
+ if (adapter->MacFilter & (MAC_ALLMCAST | MAC_PROMISC)) {
+ /* Turn on all multicast addresses. We have to do this for promiscuous
+ * mode as well as ALLMCAST mode. It saves the Microcode from having
+ * to keep state about the MAC configuration.
+ */
+/* DBG_ERROR("sxg: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n SLUT MODE!!!\n",__func__); */
+ WRITE_REG(sxg_regs->McastLow, 0xFFFFFFFF, FLUSH);
+ WRITE_REG(sxg_regs->McastHigh, 0xFFFFFFFF, FLUSH);
+/* DBG_ERROR("%s (%s) WRITE to slic_regs slic_mcastlow&high 0xFFFFFFFF\n",__func__, adapter->netdev->name); */
+
+ } else {
+ /* Commit our multicast mast to the SLIC by writing to the multicast
+ * address mask registers
+ */
+ DBG_ERROR("%s (%s) WRITE mcastlow[%lx] mcasthigh[%lx]\n",
+ __func__, adapter->netdev->name,
+ ((ulong) (adapter->MulticastMask & 0xFFFFFFFF)),
+ ((ulong)
+ ((adapter->MulticastMask >> 32) & 0xFFFFFFFF)));
+
+ WRITE_REG(sxg_regs->McastLow,
+ (u32) (adapter->MulticastMask & 0xFFFFFFFF), FLUSH);
+ WRITE_REG(sxg_regs->McastHigh,
+ (u32) ((adapter->
+ MulticastMask >> 32) & 0xFFFFFFFF), FLUSH);
+ }
+}
+
+/*
+ * Allocate a mcast_address structure to hold the multicast address.
+ * Link it in.
+ */
+static int sxg_mcast_add_list(p_adapter_t adapter, char *address)
+{
+ p_mcast_address_t mcaddr, mlist;
+ bool equaladdr;
+
+ /* Check to see if it already exists */
+ mlist = adapter->mcastaddrs;
+ while (mlist) {
+ ETHER_EQ_ADDR(mlist->address, address, equaladdr);
+ if (equaladdr) {
+ return (STATUS_SUCCESS);
+ }
+ mlist = mlist->next;
+ }
+
+ /* Doesn't already exist. Allocate a structure to hold it */
+ mcaddr = kmalloc(sizeof(mcast_address_t), GFP_ATOMIC);
+ if (mcaddr == NULL)
+ return 1;
+
+ memcpy(mcaddr->address, address, 6);
+
+ mcaddr->next = adapter->mcastaddrs;
+ adapter->mcastaddrs = mcaddr;
+
+ return (STATUS_SUCCESS);
+}
+
static void sxg_mcast_set_bit(p_adapter_t adapter, char *address)
{
unsigned char crcpoly;
@@ -2783,7 +2821,6 @@ static void sxg_mcast_set_bit(p_adapter_t adapter, char *address)
static void sxg_mcast_set_list(p_net_device dev)
{
-#if XXXTODO
p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
int status = STATUS_SUCCESS;
int i;
@@ -2809,7 +2846,7 @@ static void sxg_mcast_set_list(p_net_device dev)
}
DBG_ERROR("%s a->devflags_prev[%x] dev->flags[%x] status[%x]\n",
- __FUNCTION__, adapter->devflags_prev, dev->flags, status);
+ __func__, adapter->devflags_prev, dev->flags, status);
if (adapter->devflags_prev != dev->flags) {
adapter->macopts = MAC_DIRECTED;
if (dev->flags) {
@@ -2828,60 +2865,24 @@ static void sxg_mcast_set_list(p_net_device dev)
}
adapter->devflags_prev = dev->flags;
DBG_ERROR("%s call sxg_config_set adapter->macopts[%x]\n",
- __FUNCTION__, adapter->macopts);
+ __func__, adapter->macopts);
sxg_config_set(adapter, TRUE);
} else {
if (status == STATUS_SUCCESS) {
sxg_mcast_set_mask(adapter);
}
}
-#endif
return;
}
-
-static void sxg_mcast_set_mask(p_adapter_t adapter)
-{
- PSXG_UCODE_REGS sxg_regs = adapter->UcodeRegs;
-
- DBG_ERROR("%s ENTER (%s) macopts[%x] mask[%llx]\n", __FUNCTION__,
- adapter->netdev->name, (unsigned int)adapter->MacFilter,
- adapter->MulticastMask);
-
- if (adapter->MacFilter & (MAC_ALLMCAST | MAC_PROMISC)) {
- /* Turn on all multicast addresses. We have to do this for promiscuous
- * mode as well as ALLMCAST mode. It saves the Microcode from having
- * to keep state about the MAC configuration.
- */
-// DBG_ERROR("sxg: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n SLUT MODE!!!\n",__FUNCTION__);
- WRITE_REG(sxg_regs->McastLow, 0xFFFFFFFF, FLUSH);
- WRITE_REG(sxg_regs->McastHigh, 0xFFFFFFFF, FLUSH);
-// DBG_ERROR("%s (%s) WRITE to slic_regs slic_mcastlow&high 0xFFFFFFFF\n",__FUNCTION__, adapter->netdev->name);
-
- } else {
- /* Commit our multicast mast to the SLIC by writing to the multicast
- * address mask registers
- */
- DBG_ERROR("%s (%s) WRITE mcastlow[%lx] mcasthigh[%lx]\n",
- __FUNCTION__, adapter->netdev->name,
- ((ulong) (adapter->MulticastMask & 0xFFFFFFFF)),
- ((ulong)
- ((adapter->MulticastMask >> 32) & 0xFFFFFFFF)));
-
- WRITE_REG(sxg_regs->McastLow,
- (u32) (adapter->MulticastMask & 0xFFFFFFFF), FLUSH);
- WRITE_REG(sxg_regs->McastHigh,
- (u32) ((adapter->
- MulticastMask >> 32) & 0xFFFFFFFF), FLUSH);
- }
-}
+#endif
static void sxg_unmap_mmio_space(p_adapter_t adapter)
{
#if LINUX_FREES_ADAPTER_RESOURCES
-// if (adapter->Regs) {
-// iounmap(adapter->Regs);
-// }
-// adapter->slic_regs = NULL;
+/* if (adapter->Regs) { */
+/* iounmap(adapter->Regs); */
+/* } */
+/* adapter->slic_regs = NULL; */
#endif
}
@@ -2909,8 +2910,8 @@ void SxgFreeResources(p_adapter_t adapter)
IsrCount = adapter->MsiEnabled ? RssIds : 1;
if (adapter->BasicAllocations == FALSE) {
- // No allocations have been made, including spinlocks,
- // or listhead initializations. Return.
+ /* No allocations have been made, including spinlocks, */
+ /* or listhead initializations. Return. */
return;
}
@@ -2920,7 +2921,7 @@ void SxgFreeResources(p_adapter_t adapter)
if (!(IsListEmpty(&adapter->AllSglBuffers))) {
SxgFreeSglBuffers(adapter);
}
- // Free event queues.
+ /* Free event queues. */
if (adapter->EventRings) {
pci_free_consistent(adapter->pcidev,
sizeof(SXG_EVENT_RING) * RssIds,
@@ -2947,17 +2948,17 @@ void SxgFreeResources(p_adapter_t adapter)
SXG_FREE_PACKET_POOL(adapter->PacketPoolHandle);
SXG_FREE_BUFFER_POOL(adapter->BufferPoolHandle);
- // Unmap register spaces
+ /* Unmap register spaces */
SxgUnmapResources(adapter);
- // Deregister DMA
+ /* Deregister DMA */
if (adapter->DmaHandle) {
SXG_DEREGISTER_DMA(adapter->DmaHandle);
}
- // Deregister interrupt
+ /* Deregister interrupt */
SxgDeregisterInterrupt(adapter);
- // Possibly free system info (5.2 only)
+ /* Possibly free system info (5.2 only) */
SXG_RELEASE_SYSTEM_INFO(adapter);
SxgDiagFreeResources(adapter);
@@ -3047,23 +3048,23 @@ static int sxg_allocate_buffer_memory(p_adapter_t adapter,
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocMem",
adapter, Size, BufferType, 0);
- // Grab the adapter lock and check the state.
- // If we're in anything other than INITIALIZING or
- // RUNNING state, fail. This is to prevent
- // allocations in an improper driver state
+ /* Grab the adapter lock and check the state. */
+ /* If we're in anything other than INITIALIZING or */
+ /* RUNNING state, fail. This is to prevent */
+ /* allocations in an improper driver state */
spin_lock(&adapter->AdapterLock);
- // Increment the AllocationsPending count while holding
- // the lock. Pause processing relies on this
+ /* Increment the AllocationsPending count while holding */
+ /* the lock. Pause processing relies on this */
++adapter->AllocationsPending;
spin_unlock(&adapter->AdapterLock);
- // At initialization time allocate resources synchronously.
+ /* At initialization time allocate resources synchronously. */
Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer);
if (Buffer == NULL) {
spin_lock(&adapter->AdapterLock);
- // Decrement the AllocationsPending count while holding
- // the lock. Pause processing relies on this
+ /* Decrement the AllocationsPending count while holding */
+ /* the lock. Pause processing relies on this */
--adapter->AllocationsPending;
spin_unlock(&adapter->AdapterLock);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlcMemF1",
@@ -3113,10 +3114,10 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
ASSERT((BufferSize == SXG_RCV_DATA_BUFFER_SIZE) ||
(BufferSize == SXG_RCV_JUMBO_BUFFER_SIZE));
ASSERT(Length == SXG_RCV_BLOCK_SIZE(BufferSize));
- // First, initialize the contained pool of receive data
- // buffers. This initialization requires NBL/NB/MDL allocations,
- // If any of them fail, free the block and return without
- // queueing the shared memory
+ /* First, initialize the contained pool of receive data */
+ /* buffers. This initialization requires NBL/NB/MDL allocations, */
+ /* If any of them fail, free the block and return without */
+ /* queueing the shared memory */
RcvDataBuffer = RcvBlock;
#if 0
for (i = 0, Paddr = *PhysicalAddress;
@@ -3126,14 +3127,14 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
for (i = 0, Paddr = PhysicalAddress;
i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
i++, Paddr += BufferSize, RcvDataBuffer += BufferSize) {
- //
+ /* */
RcvDataBufferHdr =
(PSXG_RCV_DATA_BUFFER_HDR) (RcvDataBuffer +
SXG_RCV_DATA_BUFFER_HDR_OFFSET
(BufferSize));
RcvDataBufferHdr->VirtualAddress = RcvDataBuffer;
RcvDataBufferHdr->PhysicalAddress = Paddr;
- RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; // For FREE macro assertion
+ RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; /* For FREE macro assertion */
RcvDataBufferHdr->Size =
SXG_RCV_BUFFER_DATA_SIZE(BufferSize);
@@ -3143,8 +3144,8 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
}
- // Place this entire block of memory on the AllRcvBlocks queue so it can be
- // free later
+ /* Place this entire block of memory on the AllRcvBlocks queue so it can be */
+ /* free later */
RcvBlockHdr =
(PSXG_RCV_BLOCK_HDR) ((unsigned char *)RcvBlock +
SXG_RCV_BLOCK_HDR_OFFSET(BufferSize));
@@ -3155,7 +3156,7 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
InsertTailList(&adapter->AllRcvBlocks, &RcvBlockHdr->AllList);
spin_unlock(&adapter->RcvQLock);
- // Now free the contained receive data buffers that we initialized above
+ /* Now free the contained receive data buffers that we initialized above */
RcvDataBuffer = RcvBlock;
for (i = 0, Paddr = PhysicalAddress;
i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
@@ -3168,7 +3169,7 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
spin_unlock(&adapter->RcvQLock);
}
- // Locate the descriptor block and put it on a separate free queue
+ /* Locate the descriptor block and put it on a separate free queue */
RcvDescriptorBlock =
(PSXG_RCV_DESCRIPTOR_BLOCK) ((unsigned char *)RcvBlock +
SXG_RCV_DESCRIPTOR_BLOCK_OFFSET
@@ -3186,7 +3187,7 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
adapter, RcvBlock, Length, 0);
return;
fail:
- // Free any allocated resources
+ /* Free any allocated resources */
if (RcvBlock) {
RcvDataBuffer = RcvBlock;
for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
@@ -3200,7 +3201,7 @@ static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
pci_free_consistent(adapter->pcidev,
Length, RcvBlock, PhysicalAddress);
}
- DBG_ERROR("%s: OUT OF RESOURCES\n", __FUNCTION__);
+ DBG_ERROR("%s: OUT OF RESOURCES\n", __func__);
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "RcvAFail",
adapter, adapter->FreeRcvBufferCount,
adapter->FreeRcvBlockCount, adapter->AllRcvBlockCount);
@@ -3230,7 +3231,7 @@ static void sxg_allocate_sgl_buffer_complete(p_adapter_t adapter,
adapter->AllSglBufferCount++;
memset(SxgSgl, 0, sizeof(SXG_SCATTER_GATHER));
SxgSgl->PhysicalAddress = PhysicalAddress; /* *PhysicalAddress; */
- SxgSgl->adapter = adapter; // Initialize backpointer once
+ SxgSgl->adapter = adapter; /* Initialize backpointer once */
InsertTailList(&adapter->AllSglBuffers, &SxgSgl->AllList);
spin_unlock(&adapter->SglQLock);
SxgSgl->State = SXG_BUFFER_BUSY;
@@ -3244,14 +3245,14 @@ static unsigned char temp_mac_address[6] =
static void sxg_adapter_set_hwaddr(p_adapter_t adapter)
{
-// DBG_ERROR ("%s ENTER card->config_set[%x] port[%d] physport[%d] funct#[%d]\n", __FUNCTION__,
-// card->config_set, adapter->port, adapter->physport, adapter->functionnumber);
-//
-// sxg_dbg_macaddrs(adapter);
+/* DBG_ERROR ("%s ENTER card->config_set[%x] port[%d] physport[%d] funct#[%d]\n", __func__, */
+/* card->config_set, adapter->port, adapter->physport, adapter->functionnumber); */
+/* */
+/* sxg_dbg_macaddrs(adapter); */
memcpy(adapter->macaddr, temp_mac_address, sizeof(SXG_CONFIG_MAC));
-// DBG_ERROR ("%s AFTER copying from config.macinfo into currmacaddr\n", __FUNCTION__);
-// sxg_dbg_macaddrs(adapter);
+/* DBG_ERROR ("%s AFTER copying from config.macinfo into currmacaddr\n", __func__); */
+/* sxg_dbg_macaddrs(adapter); */
if (!(adapter->currmacaddr[0] ||
adapter->currmacaddr[1] ||
adapter->currmacaddr[2] ||
@@ -3262,18 +3263,18 @@ static void sxg_adapter_set_hwaddr(p_adapter_t adapter)
if (adapter->netdev) {
memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6);
}
-// DBG_ERROR ("%s EXIT port %d\n", __FUNCTION__, adapter->port);
+/* DBG_ERROR ("%s EXIT port %d\n", __func__, adapter->port); */
sxg_dbg_macaddrs(adapter);
}
+#if XXXTODO
static int sxg_mac_set_address(p_net_device dev, void *ptr)
{
-#if XXXTODO
p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
struct sockaddr *addr = ptr;
- DBG_ERROR("%s ENTER (%s)\n", __FUNCTION__, adapter->netdev->name);
+ DBG_ERROR("%s ENTER (%s)\n", __func__, adapter->netdev->name);
if (netif_running(dev)) {
return -EBUSY;
@@ -3282,22 +3283,22 @@ static int sxg_mac_set_address(p_net_device dev, void *ptr)
return -EBUSY;
}
DBG_ERROR("sxg: %s (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- __FUNCTION__, adapter->netdev->name, adapter->currmacaddr[0],
+ __func__, adapter->netdev->name, adapter->currmacaddr[0],
adapter->currmacaddr[1], adapter->currmacaddr[2],
adapter->currmacaddr[3], adapter->currmacaddr[4],
adapter->currmacaddr[5]);
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
DBG_ERROR("sxg: %s (%s) new %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- __FUNCTION__, adapter->netdev->name, adapter->currmacaddr[0],
+ __func__, adapter->netdev->name, adapter->currmacaddr[0],
adapter->currmacaddr[1], adapter->currmacaddr[2],
adapter->currmacaddr[3], adapter->currmacaddr[4],
adapter->currmacaddr[5]);
sxg_config_set(adapter, TRUE);
-#endif
return 0;
}
+#endif
/*****************************************************************************/
/************* SXG DRIVER FUNCTIONS (below) ********************************/
@@ -3321,77 +3322,77 @@ static int sxg_initialize_adapter(p_adapter_t adapter)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitAdpt",
adapter, 0, 0, 0);
- RssIds = 1; // XXXTODO SXG_RSS_CPU_COUNT(adapter);
+ RssIds = 1; /* XXXTODO SXG_RSS_CPU_COUNT(adapter); */
IsrCount = adapter->MsiEnabled ? RssIds : 1;
- // Sanity check SXG_UCODE_REGS structure definition to
- // make sure the length is correct
+ /* Sanity check SXG_UCODE_REGS structure definition to */
+ /* make sure the length is correct */
ASSERT(sizeof(SXG_UCODE_REGS) == SXG_REGISTER_SIZE_PER_CPU);
- // Disable interrupts
+ /* Disable interrupts */
SXG_DISABLE_ALL_INTERRUPTS(adapter);
- // Set MTU
+ /* Set MTU */
ASSERT((adapter->FrameSize == ETHERMAXFRAME) ||
(adapter->FrameSize == JUMBOMAXFRAME));
WRITE_REG(adapter->UcodeRegs[0].LinkMtu, adapter->FrameSize, TRUE);
- // Set event ring base address and size
+ /* Set event ring base address and size */
WRITE_REG64(adapter,
adapter->UcodeRegs[0].EventBase, adapter->PEventRings, 0);
WRITE_REG(adapter->UcodeRegs[0].EventSize, EVENT_RING_SIZE, TRUE);
- // Per-ISR initialization
+ /* Per-ISR initialization */
for (i = 0; i < IsrCount; i++) {
u64 Addr;
- // Set interrupt status pointer
+ /* Set interrupt status pointer */
Addr = adapter->PIsr + (i * sizeof(u32));
WRITE_REG64(adapter, adapter->UcodeRegs[i].Isp, Addr, i);
}
- // XMT ring zero index
+ /* XMT ring zero index */
WRITE_REG64(adapter,
adapter->UcodeRegs[0].SPSendIndex,
adapter->PXmtRingZeroIndex, 0);
- // Per-RSS initialization
+ /* Per-RSS initialization */
for (i = 0; i < RssIds; i++) {
- // Release all event ring entries to the Microcode
+ /* Release all event ring entries to the Microcode */
WRITE_REG(adapter->UcodeRegs[i].EventRelease, EVENT_RING_SIZE,
TRUE);
}
- // Transmit ring base and size
+ /* Transmit ring base and size */
WRITE_REG64(adapter,
adapter->UcodeRegs[0].XmtBase, adapter->PXmtRings, 0);
WRITE_REG(adapter->UcodeRegs[0].XmtSize, SXG_XMT_RING_SIZE, TRUE);
- // Receive ring base and size
+ /* Receive ring base and size */
WRITE_REG64(adapter,
adapter->UcodeRegs[0].RcvBase, adapter->PRcvRings, 0);
WRITE_REG(adapter->UcodeRegs[0].RcvSize, SXG_RCV_RING_SIZE, TRUE);
- // Populate the card with receive buffers
+ /* Populate the card with receive buffers */
sxg_stock_rcv_buffers(adapter);
- // Initialize checksum offload capabilities. At the moment
- // we always enable IP and TCP receive checksums on the card.
- // Depending on the checksum configuration specified by the
- // user, we can choose to report or ignore the checksum
- // information provided by the card.
+ /* Initialize checksum offload capabilities. At the moment */
+ /* we always enable IP and TCP receive checksums on the card. */
+ /* Depending on the checksum configuration specified by the */
+ /* user, we can choose to report or ignore the checksum */
+ /* information provided by the card. */
WRITE_REG(adapter->UcodeRegs[0].ReceiveChecksum,
SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED, TRUE);
- // Initialize the MAC, XAUI
- DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __FUNCTION__);
+ /* Initialize the MAC, XAUI */
+ DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __func__);
status = sxg_initialize_link(adapter);
- DBG_ERROR("sxg: %s EXIT sxg_initialize_link status[%x]\n", __FUNCTION__,
+ DBG_ERROR("sxg: %s EXIT sxg_initialize_link status[%x]\n", __func__,
status);
if (status != STATUS_SUCCESS) {
return (status);
}
- // Initialize Dead to FALSE.
- // SlicCheckForHang or SlicDumpThread will take it from here.
+ /* Initialize Dead to FALSE. */
+ /* SlicCheckForHang or SlicDumpThread will take it from here. */
adapter->Dead = FALSE;
adapter->PingOutstanding = FALSE;
@@ -3428,14 +3429,14 @@ static int sxg_fill_descriptor_block(p_adapter_t adapter,
ASSERT(RcvDescriptorBlockHdr);
- // If we don't have the resources to fill the descriptor block,
- // return failure
+ /* If we don't have the resources to fill the descriptor block, */
+ /* return failure */
if ((adapter->FreeRcvBufferCount < SXG_RCV_DESCRIPTORS_PER_BLOCK) ||
SXG_RING_FULL(RcvRingInfo)) {
adapter->Stats.NoMem++;
return (STATUS_FAILURE);
}
- // Get a ring descriptor command
+ /* Get a ring descriptor command */
SXG_GET_CMD(RingZero,
RcvRingInfo, RingDescriptorCmd, RcvDescriptorBlockHdr);
ASSERT(RingDescriptorCmd);
@@ -3443,7 +3444,7 @@ static int sxg_fill_descriptor_block(p_adapter_t adapter,
RcvDescriptorBlock =
(PSXG_RCV_DESCRIPTOR_BLOCK) RcvDescriptorBlockHdr->VirtualAddress;
- // Fill in the descriptor block
+ /* Fill in the descriptor block */
for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; i++) {
SXG_GET_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
ASSERT(RcvDataBufferHdr);
@@ -3454,13 +3455,13 @@ static int sxg_fill_descriptor_block(p_adapter_t adapter,
RcvDescriptorBlock->Descriptors[i].PhysicalAddress =
RcvDataBufferHdr->PhysicalAddress;
}
- // Add the descriptor block to receive descriptor ring 0
+ /* Add the descriptor block to receive descriptor ring 0 */
RingDescriptorCmd->Sgl = RcvDescriptorBlockHdr->PhysicalAddress;
- // RcvBuffersOnCard is not protected via the receive lock (see
- // sxg_process_event_queue) We don't want to grap a lock every time a
- // buffer is returned to us, so we use atomic interlocked functions
- // instead.
+ /* RcvBuffersOnCard is not protected via the receive lock (see */
+ /* sxg_process_event_queue) We don't want to grap a lock every time a */
+ /* buffer is returned to us, so we use atomic interlocked functions */
+ /* instead. */
adapter->RcvBuffersOnCard += SXG_RCV_DESCRIPTORS_PER_BLOCK;
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DscBlk",
@@ -3490,10 +3491,10 @@ static void sxg_stock_rcv_buffers(p_adapter_t adapter)
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "StockBuf",
adapter, adapter->RcvBuffersOnCard,
adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
- // First, see if we've got less than our minimum threshold of
- // receive buffers, there isn't an allocation in progress, and
- // we haven't exceeded our maximum.. get another block of buffers
- // None of this needs to be SMP safe. It's round numbers.
+ /* First, see if we've got less than our minimum threshold of */
+ /* receive buffers, there isn't an allocation in progress, and */
+ /* we haven't exceeded our maximum.. get another block of buffers */
+ /* None of this needs to be SMP safe. It's round numbers. */
if ((adapter->FreeRcvBufferCount < SXG_MIN_RCV_DATA_BUFFERS) &&
(adapter->AllRcvBlockCount < SXG_MAX_RCV_BLOCKS) &&
(adapter->AllocationsPending == 0)) {
@@ -3502,12 +3503,12 @@ static void sxg_stock_rcv_buffers(p_adapter_t adapter)
ReceiveBufferSize),
SXG_BUFFER_TYPE_RCV);
}
- // Now grab the RcvQLock lock and proceed
+ /* Now grab the RcvQLock lock and proceed */
spin_lock(&adapter->RcvQLock);
while (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) {
PLIST_ENTRY _ple;
- // Get a descriptor block
+ /* Get a descriptor block */
RcvDescriptorBlockHdr = NULL;
if (adapter->FreeRcvBlockCount) {
_ple = RemoveHeadList(&adapter->FreeRcvBlocks);
@@ -3519,14 +3520,14 @@ static void sxg_stock_rcv_buffers(p_adapter_t adapter)
}
if (RcvDescriptorBlockHdr == NULL) {
- // Bail out..
+ /* Bail out.. */
adapter->Stats.NoMem++;
break;
}
- // Fill in the descriptor block and give it to the card
+ /* Fill in the descriptor block and give it to the card */
if (sxg_fill_descriptor_block(adapter, RcvDescriptorBlockHdr) ==
STATUS_FAILURE) {
- // Free the descriptor block
+ /* Free the descriptor block */
SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter,
RcvDescriptorBlockHdr);
break;
@@ -3560,15 +3561,15 @@ static void sxg_complete_descriptor_blocks(p_adapter_t adapter,
SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpRBlks",
adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail);
- // Now grab the RcvQLock lock and proceed
+ /* Now grab the RcvQLock lock and proceed */
spin_lock(&adapter->RcvQLock);
ASSERT(Index != RcvRingInfo->Tail);
while (RcvRingInfo->Tail != Index) {
- //
- // Locate the current Cmd (ring descriptor entry), and
- // associated receive descriptor block, and advance
- // the tail
- //
+ /* */
+ /* Locate the current Cmd (ring descriptor entry), and */
+ /* associated receive descriptor block, and advance */
+ /* the tail */
+ /* */
SXG_RETURN_CMD(RingZero,
RcvRingInfo,
RingDescriptorCmd, RcvDescriptorBlockHdr);
@@ -3576,12 +3577,12 @@ static void sxg_complete_descriptor_blocks(p_adapter_t adapter,
RcvRingInfo->Head, RcvRingInfo->Tail,
RingDescriptorCmd, RcvDescriptorBlockHdr);
- // Clear the SGL field
+ /* Clear the SGL field */
RingDescriptorCmd->Sgl = 0;
- // Attempt to refill it and hand it right back to the
- // card. If we fail to refill it, free the descriptor block
- // header. The card will be restocked later via the
- // RcvBuffersOnCard test
+ /* Attempt to refill it and hand it right back to the */
+ /* card. If we fail to refill it, free the descriptor block */
+ /* header. The card will be restocked later via the */
+ /* RcvBuffersOnCard test */
if (sxg_fill_descriptor_block(adapter, RcvDescriptorBlockHdr) ==
STATUS_FAILURE) {
SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter,
diff --git a/drivers/staging/sxg/sxg_os.h b/drivers/staging/sxg/sxg_os.h
index 26fb0ffafa5..01182689aab 100644
--- a/drivers/staging/sxg/sxg_os.h
+++ b/drivers/staging/sxg/sxg_os.h
@@ -44,7 +44,6 @@
#define FALSE (0)
#define TRUE (1)
-
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *nle_flink;
struct _LIST_ENTRY *nle_blink;
@@ -69,35 +68,32 @@ typedef struct _LIST_ENTRY {
/* These two have to be inlined since they return things. */
-static __inline PLIST_ENTRY
-RemoveHeadList(list_entry *l)
+static __inline PLIST_ENTRY RemoveHeadList(list_entry * l)
{
- list_entry *f;
- list_entry *e;
+ list_entry *f;
+ list_entry *e;
- e = l->nle_flink;
- f = e->nle_flink;
- l->nle_flink = f;
- f->nle_blink = l;
+ e = l->nle_flink;
+ f = e->nle_flink;
+ l->nle_flink = f;
+ f->nle_blink = l;
- return (e);
+ return (e);
}
-static __inline PLIST_ENTRY
-RemoveTailList(list_entry *l)
+static __inline PLIST_ENTRY RemoveTailList(list_entry * l)
{
- list_entry *b;
- list_entry *e;
+ list_entry *b;
+ list_entry *e;
- e = l->nle_blink;
- b = e->nle_blink;
- l->nle_blink = b;
- b->nle_flink = l;
+ e = l->nle_blink;
+ b = e->nle_blink;
+ l->nle_blink = b;
+ b->nle_flink = l;
- return (e);
+ return (e);
}
-
#define InsertTailList(l, e) \
do { \
list_entry *b; \
@@ -120,7 +116,6 @@ RemoveTailList(list_entry *l)
(l)->nle_flink = (e); \
} while (0)
-
#define ATK_DEBUG 1
#if ATK_DEBUG
@@ -133,7 +128,6 @@ RemoveTailList(list_entry *l)
#define SLIC_TIMESTAMP(value)
#endif
-
/****************** SXG DEFINES *****************************************/
#ifdef ATKDBG
@@ -150,5 +144,4 @@ RemoveTailList(list_entry *l)
#define WRITE_REG64(a,reg,value,cpu) sxg_reg64_write((a),(&reg),(value),(cpu))
#define READ_REG(reg,value) (value) = readl((void __iomem *)(&reg))
-#endif /* _SLIC_OS_SPECIFIC_H_ */
-
+#endif /* _SLIC_OS_SPECIFIC_H_ */
diff --git a/drivers/staging/sxg/sxgdbg.h b/drivers/staging/sxg/sxgdbg.h
index cfb6c7c77a9..4522b8d7149 100644
--- a/drivers/staging/sxg/sxgdbg.h
+++ b/drivers/staging/sxg/sxgdbg.h
@@ -58,7 +58,7 @@
{ \
if (!(a)) { \
DBG_ERROR("ASSERT() Failure: file %s, function %s line %d\n",\
- __FILE__, __FUNCTION__, __LINE__); \
+ __FILE__, __func__, __LINE__); \
} \
}
#endif
diff --git a/drivers/staging/sxg/sxghif.h b/drivers/staging/sxg/sxghif.h
index ed26ceaa131..88bffbaa3be 100644
--- a/drivers/staging/sxg/sxghif.h
+++ b/drivers/staging/sxg/sxghif.h
@@ -14,119 +14,119 @@
*******************************************************************************/
typedef struct _SXG_UCODE_REGS {
// Address 0 - 0x3F = Command codes 0-15 for TCB 0. Excode 0
- u32 Icr; // Code = 0 (extended), ExCode = 0 - Int control
- u32 RsvdReg1; // Code = 1 - TOE -NA
- u32 RsvdReg2; // Code = 2 - TOE -NA
- u32 RsvdReg3; // Code = 3 - TOE -NA
- u32 RsvdReg4; // Code = 4 - TOE -NA
- u32 RsvdReg5; // Code = 5 - TOE -NA
- u32 CardUp; // Code = 6 - Microcode initialized when 1
- u32 RsvdReg7; // Code = 7 - TOE -NA
- u32 CodeNotUsed[8]; // Codes 8-15 not used. ExCode = 0
+ u32 Icr; // Code = 0 (extended), ExCode = 0 - Int control
+ u32 RsvdReg1; // Code = 1 - TOE -NA
+ u32 RsvdReg2; // Code = 2 - TOE -NA
+ u32 RsvdReg3; // Code = 3 - TOE -NA
+ u32 RsvdReg4; // Code = 4 - TOE -NA
+ u32 RsvdReg5; // Code = 5 - TOE -NA
+ u32 CardUp; // Code = 6 - Microcode initialized when 1
+ u32 RsvdReg7; // Code = 7 - TOE -NA
+ u32 CodeNotUsed[8]; // Codes 8-15 not used. ExCode = 0
// This brings us to ExCode 1 at address 0x40 = Interrupt status pointer
- u32 Isp; // Code = 0 (extended), ExCode = 1
- u32 PadEx1[15]; // Codes 1-15 not used with extended codes
+ u32 Isp; // Code = 0 (extended), ExCode = 1
+ u32 PadEx1[15]; // Codes 1-15 not used with extended codes
// ExCode 2 = Interrupt Status Register
- u32 Isr; // Code = 0 (extended), ExCode = 2
- u32 PadEx2[15];
+ u32 Isr; // Code = 0 (extended), ExCode = 2
+ u32 PadEx2[15];
// ExCode 3 = Event base register. Location of event rings
- u32 EventBase; // Code = 0 (extended), ExCode = 3
- u32 PadEx3[15];
+ u32 EventBase; // Code = 0 (extended), ExCode = 3
+ u32 PadEx3[15];
// ExCode 4 = Event ring size
- u32 EventSize; // Code = 0 (extended), ExCode = 4
- u32 PadEx4[15];
+ u32 EventSize; // Code = 0 (extended), ExCode = 4
+ u32 PadEx4[15];
// ExCode 5 = TCB Buffers base address
- u32 TcbBase; // Code = 0 (extended), ExCode = 5
- u32 PadEx5[15];
+ u32 TcbBase; // Code = 0 (extended), ExCode = 5
+ u32 PadEx5[15];
// ExCode 6 = TCB Composite Buffers base address
- u32 TcbCompBase; // Code = 0 (extended), ExCode = 6
- u32 PadEx6[15];
+ u32 TcbCompBase; // Code = 0 (extended), ExCode = 6
+ u32 PadEx6[15];
// ExCode 7 = Transmit ring base address
- u32 XmtBase; // Code = 0 (extended), ExCode = 7
- u32 PadEx7[15];
+ u32 XmtBase; // Code = 0 (extended), ExCode = 7
+ u32 PadEx7[15];
// ExCode 8 = Transmit ring size
- u32 XmtSize; // Code = 0 (extended), ExCode = 8
- u32 PadEx8[15];
+ u32 XmtSize; // Code = 0 (extended), ExCode = 8
+ u32 PadEx8[15];
// ExCode 9 = Receive ring base address
- u32 RcvBase; // Code = 0 (extended), ExCode = 9
- u32 PadEx9[15];
+ u32 RcvBase; // Code = 0 (extended), ExCode = 9
+ u32 PadEx9[15];
// ExCode 10 = Receive ring size
- u32 RcvSize; // Code = 0 (extended), ExCode = 10
- u32 PadEx10[15];
+ u32 RcvSize; // Code = 0 (extended), ExCode = 10
+ u32 PadEx10[15];
// ExCode 11 = Read EEPROM Config
- u32 Config; // Code = 0 (extended), ExCode = 11
- u32 PadEx11[15];
+ u32 Config; // Code = 0 (extended), ExCode = 11
+ u32 PadEx11[15];
// ExCode 12 = Multicast bits 31:0
- u32 McastLow; // Code = 0 (extended), ExCode = 12
- u32 PadEx12[15];
+ u32 McastLow; // Code = 0 (extended), ExCode = 12
+ u32 PadEx12[15];
// ExCode 13 = Multicast bits 63:32
- u32 McastHigh; // Code = 0 (extended), ExCode = 13
- u32 PadEx13[15];
+ u32 McastHigh; // Code = 0 (extended), ExCode = 13
+ u32 PadEx13[15];
// ExCode 14 = Ping
- u32 Ping; // Code = 0 (extended), ExCode = 14
- u32 PadEx14[15];
+ u32 Ping; // Code = 0 (extended), ExCode = 14
+ u32 PadEx14[15];
// ExCode 15 = Link MTU
- u32 LinkMtu; // Code = 0 (extended), ExCode = 15
- u32 PadEx15[15];
+ u32 LinkMtu; // Code = 0 (extended), ExCode = 15
+ u32 PadEx15[15];
// ExCode 16 = Download synchronization
- u32 LoadSync; // Code = 0 (extended), ExCode = 16
- u32 PadEx16[15];
+ u32 LoadSync; // Code = 0 (extended), ExCode = 16
+ u32 PadEx16[15];
// ExCode 17 = Upper DRAM address bits on 32-bit systems
- u32 Upper; // Code = 0 (extended), ExCode = 17
- u32 PadEx17[15];
+ u32 Upper; // Code = 0 (extended), ExCode = 17
+ u32 PadEx17[15];
// ExCode 18 = Slowpath Send Index Address
- u32 SPSendIndex; // Code = 0 (extended), ExCode = 18
- u32 PadEx18[15];
- u32 RsvdXF; // Code = 0 (extended), ExCode = 19
- u32 PadEx19[15];
+ u32 SPSendIndex; // Code = 0 (extended), ExCode = 18
+ u32 PadEx18[15];
+ u32 RsvdXF; // Code = 0 (extended), ExCode = 19
+ u32 PadEx19[15];
// ExCode 20 = Aggregation
- u32 Aggregation; // Code = 0 (extended), ExCode = 20
- u32 PadEx20[15];
+ u32 Aggregation; // Code = 0 (extended), ExCode = 20
+ u32 PadEx20[15];
// ExCode 21 = Receive MDL push timer
- u32 PushTicks; // Code = 0 (extended), ExCode = 21
- u32 PadEx21[15];
+ u32 PushTicks; // Code = 0 (extended), ExCode = 21
+ u32 PadEx21[15];
// ExCode 22 = TOE NA
- u32 AckFrequency; // Code = 0 (extended), ExCode = 22
- u32 PadEx22[15];
+ u32 AckFrequency; // Code = 0 (extended), ExCode = 22
+ u32 PadEx22[15];
// ExCode 23 = TOE NA
- u32 RsvdReg23;
- u32 PadEx23[15];
+ u32 RsvdReg23;
+ u32 PadEx23[15];
// ExCode 24 = TOE NA
- u32 RsvdReg24;
- u32 PadEx24[15];
+ u32 RsvdReg24;
+ u32 PadEx24[15];
// ExCode 25 = TOE NA
- u32 RsvdReg25; // Code = 0 (extended), ExCode = 25
- u32 PadEx25[15];
+ u32 RsvdReg25; // Code = 0 (extended), ExCode = 25
+ u32 PadEx25[15];
// ExCode 26 = Receive checksum requirements
- u32 ReceiveChecksum; // Code = 0 (extended), ExCode = 26
- u32 PadEx26[15];
+ u32 ReceiveChecksum; // Code = 0 (extended), ExCode = 26
+ u32 PadEx26[15];
// ExCode 27 = RSS Requirements
- u32 Rss; // Code = 0 (extended), ExCode = 27
- u32 PadEx27[15];
+ u32 Rss; // Code = 0 (extended), ExCode = 27
+ u32 PadEx27[15];
// ExCode 28 = RSS Table
- u32 RssTable; // Code = 0 (extended), ExCode = 28
- u32 PadEx28[15];
+ u32 RssTable; // Code = 0 (extended), ExCode = 28
+ u32 PadEx28[15];
// ExCode 29 = Event ring release entries
- u32 EventRelease; // Code = 0 (extended), ExCode = 29
- u32 PadEx29[15];
+ u32 EventRelease; // Code = 0 (extended), ExCode = 29
+ u32 PadEx29[15];
// ExCode 30 = Number of receive bufferlist commands on ring 0
- u32 RcvCmd; // Code = 0 (extended), ExCode = 30
- u32 PadEx30[15];
+ u32 RcvCmd; // Code = 0 (extended), ExCode = 30
+ u32 PadEx30[15];
// ExCode 31 = slowpath transmit command - Data[31:0] = 1
- u32 XmtCmd; // Code = 0 (extended), ExCode = 31
- u32 PadEx31[15];
+ u32 XmtCmd; // Code = 0 (extended), ExCode = 31
+ u32 PadEx31[15];
// ExCode 32 = Dump command
- u32 DumpCmd; // Code = 0 (extended), ExCode = 32
- u32 PadEx32[15];
+ u32 DumpCmd; // Code = 0 (extended), ExCode = 32
+ u32 PadEx32[15];
// ExCode 33 = Debug command
- u32 DebugCmd; // Code = 0 (extended), ExCode = 33
- u32 PadEx33[15];
+ u32 DebugCmd; // Code = 0 (extended), ExCode = 33
+ u32 PadEx33[15];
// There are 128 possible extended commands - each of account for 16
// words (including the non-relevent base command codes 1-15).
// Pad for the remainder of these here to bring us to the next CPU
// base. As extended codes are added, reduce the first array value in
// the following field
- u32 PadToNextCpu[94][16]; // 94 = 128 - 34 (34 = Excodes 0 - 33)
+ u32 PadToNextCpu[94][16]; // 94 = 128 - 34 (34 = Excodes 0 - 33)
} SXG_UCODE_REGS, *PSXG_UCODE_REGS;
// Interrupt control register (0) values
@@ -141,7 +141,7 @@ typedef struct _SXG_UCODE_REGS {
// The Microcode supports up to 16 RSS queues
#define SXG_MAX_RSS 16
-#define SXG_MAX_RSS_TABLE_SIZE 256 // 256-byte max
+#define SXG_MAX_RSS_TABLE_SIZE 256 // 256-byte max
#define SXG_RSS_TCP6 0x00000001 // RSS TCP over IPv6
#define SXG_RSS_TCP4 0x00000002 // RSS TCP over IPv4
@@ -170,16 +170,16 @@ typedef struct _SXG_UCODE_REGS {
* SXG_UCODE_REGS definition above
*/
typedef struct _SXG_TCB_REGS {
- u32 ExCode; /* Extended codes - see SXG_UCODE_REGS */
- u32 Xmt; /* Code = 1 - # of Xmt descriptors added to ring */
- u32 Rcv; /* Code = 2 - # of Rcv descriptors added to ring */
- u32 Rsvd1; /* Code = 3 - TOE NA */
- u32 Rsvd2; /* Code = 4 - TOE NA */
- u32 Rsvd3; /* Code = 5 - TOE NA */
- u32 Invalid; /* Code = 6 - Reserved for "CardUp" see above */
- u32 Rsvd4; /* Code = 7 - TOE NA */
- u32 Rsvd5; /* Code = 8 - TOE NA */
- u32 Pad[7]; /* Codes 8-15 - Not used. */
+ u32 ExCode; /* Extended codes - see SXG_UCODE_REGS */
+ u32 Xmt; /* Code = 1 - # of Xmt descriptors added to ring */
+ u32 Rcv; /* Code = 2 - # of Rcv descriptors added to ring */
+ u32 Rsvd1; /* Code = 3 - TOE NA */
+ u32 Rsvd2; /* Code = 4 - TOE NA */
+ u32 Rsvd3; /* Code = 5 - TOE NA */
+ u32 Invalid; /* Code = 6 - Reserved for "CardUp" see above */
+ u32 Rsvd4; /* Code = 7 - TOE NA */
+ u32 Rsvd5; /* Code = 8 - TOE NA */
+ u32 Pad[7]; /* Codes 8-15 - Not used. */
} SXG_TCB_REGS, *PSXG_TCB_REGS;
/***************************************************************************
@@ -273,27 +273,27 @@ typedef struct _SXG_TCB_REGS {
*/
#pragma pack(push, 1)
typedef struct _SXG_EVENT {
- u32 Pad[1]; // not used
- u32 SndUna; // SndUna value
- u32 Resid; // receive MDL resid
+ u32 Pad[1]; // not used
+ u32 SndUna; // SndUna value
+ u32 Resid; // receive MDL resid
union {
- void * HostHandle; // Receive host handle
- u32 Rsvd1; // TOE NA
+ void *HostHandle; // Receive host handle
+ u32 Rsvd1; // TOE NA
struct {
- u32 NotUsed;
- u32 Rsvd2; // TOE NA
+ u32 NotUsed;
+ u32 Rsvd2; // TOE NA
} Flush;
};
- u32 Toeplitz; // RSS Toeplitz hash
+ u32 Toeplitz; // RSS Toeplitz hash
union {
- ushort Rsvd3; // TOE NA
- ushort HdrOffset; // Slowpath
+ ushort Rsvd3; // TOE NA
+ ushort HdrOffset; // Slowpath
};
- ushort Length; //
- unsigned char Rsvd4; // TOE NA
- unsigned char Code; // Event code
- unsigned char CommandIndex; // New ring index
- unsigned char Status; // Event status
+ ushort Length; //
+ unsigned char Rsvd4; // TOE NA
+ unsigned char Code; // Event code
+ unsigned char CommandIndex; // New ring index
+ unsigned char Status; // Event status
} SXG_EVENT, *PSXG_EVENT;
#pragma pack(pop)
@@ -318,12 +318,12 @@ typedef struct _SXG_EVENT {
// Event ring
// Size must be power of 2, between 128 and 16k
#define EVENT_RING_SIZE 4096 // ??
-#define EVENT_RING_BATCH 16 // Hand entries back 16 at a time.
-#define EVENT_BATCH_LIMIT 256 // Stop processing events after 256 (16 * 16)
+#define EVENT_RING_BATCH 16 // Hand entries back 16 at a time.
+#define EVENT_BATCH_LIMIT 256 // Stop processing events after 256 (16 * 16)
typedef struct _SXG_EVENT_RING {
- SXG_EVENT Ring[EVENT_RING_SIZE];
-}SXG_EVENT_RING, *PSXG_EVENT_RING;
+ SXG_EVENT Ring[EVENT_RING_SIZE];
+} SXG_EVENT_RING, *PSXG_EVENT_RING;
/***************************************************************************
*
@@ -341,7 +341,7 @@ typedef struct _SXG_EVENT_RING {
#define SXG_TCB_PER_BUCKET 16
#define SXG_TCB_BUCKET_MASK 0xFF0 // Bucket portion of TCB ID
#define SXG_TCB_ELEMENT_MASK 0x00F // Element within bucket
-#define SXG_TCB_BUCKETS 256 // 256 * 16 = 4k
+#define SXG_TCB_BUCKETS 256 // 256 * 16 = 4k
#define SXG_TCB_BUFFER_SIZE 512 // ASSERT format is correct
@@ -368,7 +368,6 @@ typedef struct _SXG_EVENT_RING {
&(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.Ip : \
&(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp6.Ip
-
#if DBG
// Horrible kludge to distinguish dumb-nic, slowpath, and
// fastpath traffic. Decrement the HopLimit by one
@@ -396,16 +395,16 @@ typedef struct _SXG_EVENT_RING {
* Receive and transmit rings
***************************************************************************/
#define SXG_MAX_RING_SIZE 256
-#define SXG_XMT_RING_SIZE 128 // Start with 128
-#define SXG_RCV_RING_SIZE 128 // Start with 128
+#define SXG_XMT_RING_SIZE 128 // Start with 128
+#define SXG_RCV_RING_SIZE 128 // Start with 128
#define SXG_MAX_ENTRIES 4096
// Structure and macros to manage a ring
typedef struct _SXG_RING_INFO {
- unsigned char Head; // Where we add entries - Note unsigned char:RING_SIZE
- unsigned char Tail; // Where we pull off completed entries
- ushort Size; // Ring size - Must be multiple of 2
- void * Context[SXG_MAX_RING_SIZE]; // Shadow ring
+ unsigned char Head; // Where we add entries - Note unsigned char:RING_SIZE
+ unsigned char Tail; // Where we pull off completed entries
+ ushort Size; // Ring size - Must be multiple of 2
+ void *Context[SXG_MAX_RING_SIZE]; // Shadow ring
} SXG_RING_INFO, *PSXG_RING_INFO;
#define SXG_INITIALIZE_RING(_ring, _size) { \
@@ -483,40 +482,40 @@ typedef struct _SXG_RING_INFO {
*/
#pragma pack(push, 1)
typedef struct _SXG_CMD {
- dma_addr_t Sgl; // Physical address of SGL
+ dma_addr_t Sgl; // Physical address of SGL
union {
struct {
- dma64_addr_t FirstSgeAddress;// Address of first SGE
- u32 FirstSgeLength; // Length of first SGE
+ dma64_addr_t FirstSgeAddress; // Address of first SGE
+ u32 FirstSgeLength; // Length of first SGE
union {
- u32 Rsvd1; // TOE NA
- u32 SgeOffset; // Slowpath - 2nd SGE offset
- u32 Resid; // MDL completion - clobbers update
+ u32 Rsvd1; // TOE NA
+ u32 SgeOffset; // Slowpath - 2nd SGE offset
+ u32 Resid; // MDL completion - clobbers update
};
union {
- u32 TotalLength; // Total transfer length
- u32 Mss; // LSO MSS
+ u32 TotalLength; // Total transfer length
+ u32 Mss; // LSO MSS
};
} Buffer;
};
union {
struct {
- unsigned char Flags:4; // slowpath flags
- unsigned char IpHl:4; // Ip header length (>>2)
- unsigned char MacLen; // Mac header len
+ unsigned char Flags:4; // slowpath flags
+ unsigned char IpHl:4; // Ip header length (>>2)
+ unsigned char MacLen; // Mac header len
} CsumFlags;
struct {
- ushort Flags:4; // slowpath flags
- ushort TcpHdrOff:7; // TCP
- ushort MacLen:5; // Mac header len
+ ushort Flags:4; // slowpath flags
+ ushort TcpHdrOff:7; // TCP
+ ushort MacLen:5; // Mac header len
} LsoFlags;
- ushort Flags; // flags
+ ushort Flags; // flags
};
union {
- ushort SgEntries; // SG entry count including first sge
+ ushort SgEntries; // SG entry count including first sge
struct {
- unsigned char Status; // Copied from event status
- unsigned char NotUsed;
+ unsigned char Status; // Copied from event status
+ unsigned char NotUsed;
} Status;
};
} SXG_CMD, *PSXG_CMD;
@@ -524,8 +523,8 @@ typedef struct _SXG_CMD {
#pragma pack(push, 1)
typedef struct _VLAN_HDR {
- ushort VlanTci;
- ushort VlanTpid;
+ ushort VlanTci;
+ ushort VlanTpid;
} VLAN_HDR, *PVLAN_HDR;
#pragma pack(pop)
@@ -561,16 +560,16 @@ typedef struct _VLAN_HDR {
*
*/
// Slowpath CMD flags
-#define SXG_SLOWCMD_CSUM_IP 0x01 // Checksum IP
-#define SXG_SLOWCMD_CSUM_TCP 0x02 // Checksum TCP
-#define SXG_SLOWCMD_LSO 0x04 // Large segment send
+#define SXG_SLOWCMD_CSUM_IP 0x01 // Checksum IP
+#define SXG_SLOWCMD_CSUM_TCP 0x02 // Checksum TCP
+#define SXG_SLOWCMD_LSO 0x04 // Large segment send
typedef struct _SXG_XMT_RING {
- SXG_CMD Descriptors[SXG_XMT_RING_SIZE];
+ SXG_CMD Descriptors[SXG_XMT_RING_SIZE];
} SXG_XMT_RING, *PSXG_XMT_RING;
typedef struct _SXG_RCV_RING {
- SXG_CMD Descriptors[SXG_RCV_RING_SIZE];
+ SXG_CMD Descriptors[SXG_RCV_RING_SIZE];
} SXG_RCV_RING, *PSXG_RCV_RING;
/***************************************************************************
@@ -578,8 +577,8 @@ typedef struct _SXG_RCV_RING {
* shared memory allocation
***************************************************************************/
typedef enum {
- SXG_BUFFER_TYPE_RCV, // Receive buffer
- SXG_BUFFER_TYPE_SGL // SGL buffer
+ SXG_BUFFER_TYPE_RCV, // Receive buffer
+ SXG_BUFFER_TYPE_SGL // SGL buffer
} SXG_BUFFER_TYPE;
// State for SXG buffers
@@ -668,60 +667,60 @@ typedef enum {
#define SXG_RCV_DATA_BUFFERS 4096 // Amount to give to the card
#define SXG_INITIAL_RCV_DATA_BUFFERS 8192 // Initial pool of buffers
#define SXG_MIN_RCV_DATA_BUFFERS 2048 // Minimum amount and when to get more
-#define SXG_MAX_RCV_BLOCKS 128 // = 16384 receive buffers
+#define SXG_MAX_RCV_BLOCKS 128 // = 16384 receive buffers
// Receive buffer header
typedef struct _SXG_RCV_DATA_BUFFER_HDR {
- dma_addr_t PhysicalAddress; // Buffer physical address
+ dma_addr_t PhysicalAddress; // Buffer physical address
// Note - DO NOT USE the VirtualAddress field to locate data.
// Use the sxg.h:SXG_RECEIVE_DATA_LOCATION macro instead.
- void *VirtualAddress; // Start of buffer
- LIST_ENTRY FreeList; // Free queue of buffers
- struct _SXG_RCV_DATA_BUFFER_HDR *Next; // Fastpath data buffer queue
- u32 Size; // Buffer size
- u32 ByteOffset; // See SXG_RESTORE_MDL_OFFSET
- unsigned char State; // See SXG_BUFFER state above
- unsigned char Status; // Event status (to log PUSH)
- struct sk_buff * skb; // Double mapped (nbl and pkt)
+ void *VirtualAddress; // Start of buffer
+ LIST_ENTRY FreeList; // Free queue of buffers
+ struct _SXG_RCV_DATA_BUFFER_HDR *Next; // Fastpath data buffer queue
+ u32 Size; // Buffer size
+ u32 ByteOffset; // See SXG_RESTORE_MDL_OFFSET
+ unsigned char State; // See SXG_BUFFER state above
+ unsigned char Status; // Event status (to log PUSH)
+ struct sk_buff *skb; // Double mapped (nbl and pkt)
} SXG_RCV_DATA_BUFFER_HDR, *PSXG_RCV_DATA_BUFFER_HDR;
// SxgSlowReceive uses the PACKET (skb) contained
// in the SXG_RCV_DATA_BUFFER_HDR when indicating dumb-nic data
#define SxgDumbRcvPacket skb
-#define SXG_RCV_DATA_HDR_SIZE 256 // Space for SXG_RCV_DATA_BUFFER_HDR
+#define SXG_RCV_DATA_HDR_SIZE 256 // Space for SXG_RCV_DATA_BUFFER_HDR
#define SXG_RCV_DATA_BUFFER_SIZE 2048 // Non jumbo = 2k including HDR
#define SXG_RCV_JUMBO_BUFFER_SIZE 10240 // jumbo = 10k including HDR
// Receive data descriptor
typedef struct _SXG_RCV_DATA_DESCRIPTOR {
union {
- struct sk_buff * VirtualAddress; // Host handle
- u64 ForceTo8Bytes; // Force x86 to 8-byte boundary
+ struct sk_buff *VirtualAddress; // Host handle
+ u64 ForceTo8Bytes; // Force x86 to 8-byte boundary
};
- dma_addr_t PhysicalAddress;
+ dma_addr_t PhysicalAddress;
} SXG_RCV_DATA_DESCRIPTOR, *PSXG_RCV_DATA_DESCRIPTOR;
// Receive descriptor block
#define SXG_RCV_DESCRIPTORS_PER_BLOCK 128
#define SXG_RCV_DESCRIPTOR_BLOCK_SIZE 2048 // For sanity check
typedef struct _SXG_RCV_DESCRIPTOR_BLOCK {
- SXG_RCV_DATA_DESCRIPTOR Descriptors[SXG_RCV_DESCRIPTORS_PER_BLOCK];
+ SXG_RCV_DATA_DESCRIPTOR Descriptors[SXG_RCV_DESCRIPTORS_PER_BLOCK];
} SXG_RCV_DESCRIPTOR_BLOCK, *PSXG_RCV_DESCRIPTOR_BLOCK;
// Receive descriptor block header
typedef struct _SXG_RCV_DESCRIPTOR_BLOCK_HDR {
- void * VirtualAddress; // Start of 2k buffer
- dma_addr_t PhysicalAddress; // ..and it's physical address
- LIST_ENTRY FreeList; // Free queue of descriptor blocks
- unsigned char State; // See SXG_BUFFER state above
+ void *VirtualAddress; // Start of 2k buffer
+ dma_addr_t PhysicalAddress; // ..and it's physical address
+ LIST_ENTRY FreeList; // Free queue of descriptor blocks
+ unsigned char State; // See SXG_BUFFER state above
} SXG_RCV_DESCRIPTOR_BLOCK_HDR, *PSXG_RCV_DESCRIPTOR_BLOCK_HDR;
// Receive block header
typedef struct _SXG_RCV_BLOCK_HDR {
- void * VirtualAddress; // Start of virtual memory
- dma_addr_t PhysicalAddress; // ..and it's physical address
- LIST_ENTRY AllList; // Queue of all SXG_RCV_BLOCKS
+ void *VirtualAddress; // Start of virtual memory
+ dma_addr_t PhysicalAddress; // ..and it's physical address
+ LIST_ENTRY AllList; // Queue of all SXG_RCV_BLOCKS
} SXG_RCV_BLOCK_HDR, *PSXG_RCV_BLOCK_HDR;
// Macros to determine data structure offsets into receive block
@@ -747,8 +746,8 @@ typedef struct _SXG_RCV_BLOCK_HDR {
// Use the miniport reserved portion of the NBL to locate
// our SXG_RCV_DATA_BUFFER_HDR structure.
typedef struct _SXG_RCV_NBL_RESERVED {
- PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
- void * Available;
+ PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
+ void *Available;
} SXG_RCV_NBL_RESERVED, *PSXG_RCV_NBL_RESERVED;
#define SXG_RCV_NBL_BUFFER_HDR(_NBL) (((PSXG_RCV_NBL_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(_NBL))->RcvDataBufferHdr)
@@ -760,12 +759,11 @@ typedef struct _SXG_RCV_NBL_RESERVED {
#define SXG_MIN_SGL_BUFFERS 2048 // Minimum amount and when to get more
#define SXG_MAX_SGL_BUFFERS 16384 // Maximum to allocate (note ADAPT:ushort)
-
// Self identifying structure type
typedef enum _SXG_SGL_TYPE {
- SXG_SGL_DUMB, // Dumb NIC SGL
- SXG_SGL_SLOW, // Slowpath protocol header - see below
- SXG_SGL_CHIMNEY // Chimney offload SGL
+ SXG_SGL_DUMB, // Dumb NIC SGL
+ SXG_SGL_SLOW, // Slowpath protocol header - see below
+ SXG_SGL_CHIMNEY // Chimney offload SGL
} SXG_SGL_TYPE, PSXG_SGL_TYPE;
// Note - the description below is Microsoft specific
@@ -774,14 +772,14 @@ typedef enum _SXG_SGL_TYPE {
// for the SCATTER_GATHER_LIST portion of the SXG_SCATTER_GATHER data structure.
// The following considerations apply when setting this value:
// - First, the Sahara card is designed to read the Microsoft SGL structure
-// straight out of host memory. This means that the SGL must reside in
-// shared memory. If the length here is smaller than the SGL for the
-// NET_BUFFER, then NDIS will allocate its own buffer. The buffer
-// that NDIS allocates is not in shared memory, so when this happens,
-// the SGL will need to be copied to a set of SXG_SCATTER_GATHER buffers.
-// In other words.. we don't want this value to be too small.
+// straight out of host memory. This means that the SGL must reside in
+// shared memory. If the length here is smaller than the SGL for the
+// NET_BUFFER, then NDIS will allocate its own buffer. The buffer
+// that NDIS allocates is not in shared memory, so when this happens,
+// the SGL will need to be copied to a set of SXG_SCATTER_GATHER buffers.
+// In other words.. we don't want this value to be too small.
// - On the other hand.. we're allocating up to 16k of these things. If
-// we make this too big, we start to consume a ton of memory..
+// we make this too big, we start to consume a ton of memory..
// At the moment, I'm going to limit the number of SG entries to 150.
// If each entry maps roughly 4k, then this should cover roughly 600kB
// NET_BUFFERs. Furthermore, since each entry is 24 bytes, the total
@@ -801,24 +799,23 @@ typedef enum _SXG_SGL_TYPE {
// the SGL. The following structure defines an x64
// formatted SGL entry
typedef struct _SXG_X64_SGE {
- dma64_addr_t Address; // same as wdm.h
- u32 Length; // same as wdm.h
- u32 CompilerPad;// The compiler pads to 8-bytes
- u64 Reserved; // u32 * in wdm.h. Force to 8 bytes
+ dma64_addr_t Address; // same as wdm.h
+ u32 Length; // same as wdm.h
+ u32 CompilerPad; // The compiler pads to 8-bytes
+ u64 Reserved; // u32 * in wdm.h. Force to 8 bytes
} SXG_X64_SGE, *PSXG_X64_SGE;
typedef struct _SCATTER_GATHER_ELEMENT {
- dma64_addr_t Address; // same as wdm.h
- u32 Length; // same as wdm.h
- u32 CompilerPad;// The compiler pads to 8-bytes
- u64 Reserved; // u32 * in wdm.h. Force to 8 bytes
+ dma64_addr_t Address; // same as wdm.h
+ u32 Length; // same as wdm.h
+ u32 CompilerPad; // The compiler pads to 8-bytes
+ u64 Reserved; // u32 * in wdm.h. Force to 8 bytes
} SCATTER_GATHER_ELEMENT, *PSCATTER_GATHER_ELEMENT;
-
typedef struct _SCATTER_GATHER_LIST {
- u32 NumberOfElements;
- u32 * Reserved;
- SCATTER_GATHER_ELEMENT Elements[];
+ u32 NumberOfElements;
+ u32 *Reserved;
+ SCATTER_GATHER_ELEMENT Elements[];
} SCATTER_GATHER_LIST, *PSCATTER_GATHER_LIST;
// The card doesn't care about anything except elements, so
@@ -826,26 +823,26 @@ typedef struct _SCATTER_GATHER_LIST {
// SGL structure. But redefine from wdm.h:SCATTER_GATHER_LIST so
// we can specify SXG_X64_SGE and define a fixed number of elements
typedef struct _SXG_X64_SGL {
- u32 NumberOfElements;
- u32 * Reserved;
- SXG_X64_SGE Elements[SXG_SGL_ENTRIES];
+ u32 NumberOfElements;
+ u32 *Reserved;
+ SXG_X64_SGE Elements[SXG_SGL_ENTRIES];
} SXG_X64_SGL, *PSXG_X64_SGL;
typedef struct _SXG_SCATTER_GATHER {
- SXG_SGL_TYPE Type; // FIRST! Dumb-nic or offload
- void * adapter; // Back pointer to adapter
- LIST_ENTRY FreeList; // Free SXG_SCATTER_GATHER blocks
- LIST_ENTRY AllList; // All SXG_SCATTER_GATHER blocks
- dma_addr_t PhysicalAddress;// physical address
- unsigned char State; // See SXG_BUFFER state above
- unsigned char CmdIndex; // Command ring index
- struct sk_buff * DumbPacket; // Associated Packet
- u32 Direction; // For asynchronous completions
- u32 CurOffset; // Current SGL offset
- u32 SglRef; // SGL reference count
- VLAN_HDR VlanTag; // VLAN tag to be inserted into SGL
- PSCATTER_GATHER_LIST pSgl; // SGL Addr. Possibly &Sgl
- SXG_X64_SGL Sgl; // SGL handed to card
+ SXG_SGL_TYPE Type; // FIRST! Dumb-nic or offload
+ void *adapter; // Back pointer to adapter
+ LIST_ENTRY FreeList; // Free SXG_SCATTER_GATHER blocks
+ LIST_ENTRY AllList; // All SXG_SCATTER_GATHER blocks
+ dma_addr_t PhysicalAddress; // physical address
+ unsigned char State; // See SXG_BUFFER state above
+ unsigned char CmdIndex; // Command ring index
+ struct sk_buff *DumbPacket; // Associated Packet
+ u32 Direction; // For asynchronous completions
+ u32 CurOffset; // Current SGL offset
+ u32 SglRef; // SGL reference count
+ VLAN_HDR VlanTag; // VLAN tag to be inserted into SGL
+ PSCATTER_GATHER_LIST pSgl; // SGL Addr. Possibly &Sgl
+ SXG_X64_SGL Sgl; // SGL handed to card
} SXG_SCATTER_GATHER, *PSXG_SCATTER_GATHER;
#if defined(CONFIG_X86_64)
@@ -856,6 +853,5 @@ typedef struct _SXG_SCATTER_GATHER {
#define SXG_SGL_BUFFER(_SxgSgl) NULL
#define SXG_SGL_BUF_SIZE 0
#else
- Stop Compilation;
+Stop Compilation;
#endif
-
diff --git a/drivers/staging/sxg/sxghw.h b/drivers/staging/sxg/sxghw.h
index 8f4f6effdd9..2222ae91fd9 100644
--- a/drivers/staging/sxg/sxghw.h
+++ b/drivers/staging/sxg/sxghw.h
@@ -13,11 +13,11 @@
/*******************************************************************************
* Configuration space
*******************************************************************************/
-// PCI Vendor ID
-#define SXG_VENDOR_ID 0x139A // Alacritech's Vendor ID
+/* PCI Vendor ID */
+#define SXG_VENDOR_ID 0x139A /* Alacritech's Vendor ID */
// PCI Device ID
-#define SXG_DEVICE_ID 0x0009 // Sahara Device ID
+#define SXG_DEVICE_ID 0x0009 /* Sahara Device ID */
//
// Subsystem IDs.
@@ -141,7 +141,7 @@ typedef struct _SXG_HW_REGS {
#define SXG_REGISTER_SIZE_PER_CPU 0x00002000 // Used to sanity check UCODE_REGS structure
// Sahara receive sequencer status values
-#define SXG_RCV_STATUS_ATTN 0x80000000 // Attention
+#define SXG_RCV_STATUS_ATTN 0x80000000 // Attention
#define SXG_RCV_STATUS_TRANSPORT_MASK 0x3F000000 // Transport mask
#define SXG_RCV_STATUS_TRANSPORT_ERROR 0x20000000 // Transport error
#define SXG_RCV_STATUS_TRANSPORT_CSUM 0x23000000 // Transport cksum error
@@ -156,9 +156,9 @@ typedef struct _SXG_HW_REGS {
#define SXG_RCV_STATUS_TRANSPORT_FTP 0x03000000 // Transport FTP
#define SXG_RCV_STATUS_TRANSPORT_HTTP 0x02000000 // Transport HTTP
#define SXG_RCV_STATUS_TRANSPORT_SMB 0x01000000 // Transport SMB
-#define SXG_RCV_STATUS_NETWORK_MASK 0x00FF0000 // Network mask
+#define SXG_RCV_STATUS_NETWORK_MASK 0x00FF0000 // Network mask
#define SXG_RCV_STATUS_NETWORK_ERROR 0x00800000 // Network error
-#define SXG_RCV_STATUS_NETWORK_CSUM 0x00830000 // Network cksum error
+#define SXG_RCV_STATUS_NETWORK_CSUM 0x00830000 // Network cksum error
#define SXG_RCV_STATUS_NETWORK_UFLOW 0x00820000 // Network underflow error
#define SXG_RCV_STATUS_NETWORK_HDRLEN 0x00800000 // Network header length
#define SXG_RCV_STATUS_NETWORK_OFLOW 0x00400000 // Network overflow detected
@@ -167,67 +167,67 @@ typedef struct _SXG_HW_REGS {
#define SXG_RCV_STATUS_NETWORK_OFFSET 0x00080000 // Network offset detected
#define SXG_RCV_STATUS_NETWORK_FRAGMENT 0x00040000 // Network fragment detected
#define SXG_RCV_STATUS_NETWORK_TRANS_MASK 0x00030000 // Network transport type mask
-#define SXG_RCV_STATUS_NETWORK_UDP 0x00020000 // UDP
-#define SXG_RCV_STATUS_NETWORK_TCP 0x00010000 // TCP
-#define SXG_RCV_STATUS_IPONLY 0x00008000 // IP-only not TCP
-#define SXG_RCV_STATUS_PKT_PRI 0x00006000 // Receive priority
-#define SXG_RCV_STATUS_PKT_PRI_SHFT 13 // Receive priority shift
-#define SXG_RCV_STATUS_PARITY 0x00001000 // MAC Receive RAM parity error
-#define SXG_RCV_STATUS_ADDRESS_MASK 0x00000F00 // Link address detection mask
-#define SXG_RCV_STATUS_ADDRESS_D 0x00000B00 // Link address D
-#define SXG_RCV_STATUS_ADDRESS_C 0x00000A00 // Link address C
-#define SXG_RCV_STATUS_ADDRESS_B 0x00000900 // Link address B
-#define SXG_RCV_STATUS_ADDRESS_A 0x00000800 // Link address A
+#define SXG_RCV_STATUS_NETWORK_UDP 0x00020000 // UDP
+#define SXG_RCV_STATUS_NETWORK_TCP 0x00010000 // TCP
+#define SXG_RCV_STATUS_IPONLY 0x00008000 // IP-only not TCP
+#define SXG_RCV_STATUS_PKT_PRI 0x00006000 // Receive priority
+#define SXG_RCV_STATUS_PKT_PRI_SHFT 13 // Receive priority shift
+#define SXG_RCV_STATUS_PARITY 0x00001000 // MAC Receive RAM parity error
+#define SXG_RCV_STATUS_ADDRESS_MASK 0x00000F00 // Link address detection mask
+#define SXG_RCV_STATUS_ADDRESS_D 0x00000B00 // Link address D
+#define SXG_RCV_STATUS_ADDRESS_C 0x00000A00 // Link address C
+#define SXG_RCV_STATUS_ADDRESS_B 0x00000900 // Link address B
+#define SXG_RCV_STATUS_ADDRESS_A 0x00000800 // Link address A
#define SXG_RCV_STATUS_ADDRESS_BCAST 0x00000300 // Link address broadcast
#define SXG_RCV_STATUS_ADDRESS_MCAST 0x00000200 // Link address multicast
#define SXG_RCV_STATUS_ADDRESS_CMCAST 0x00000100 // Link control multicast
-#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask
-#define SXG_RCV_STATUS_LINK_ERROR 0x00000080 // Link error
-#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask
-#define SXG_RCV_STATUS_LINK_PARITY 0x00000087 // RcvMacQ parity error
-#define SXG_RCV_STATUS_LINK_EARLY 0x00000086 // Data early
+#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask
+#define SXG_RCV_STATUS_LINK_ERROR 0x00000080 // Link error
+#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask
+#define SXG_RCV_STATUS_LINK_PARITY 0x00000087 // RcvMacQ parity error
+#define SXG_RCV_STATUS_LINK_EARLY 0x00000086 // Data early
#define SXG_RCV_STATUS_LINK_BUFOFLOW 0x00000085 // Buffer overflow
-#define SXG_RCV_STATUS_LINK_CODE 0x00000084 // Link code error
-#define SXG_RCV_STATUS_LINK_DRIBBLE 0x00000083 // Dribble nibble
-#define SXG_RCV_STATUS_LINK_CRC 0x00000082 // CRC error
-#define SXG_RCV_STATUS_LINK_OFLOW 0x00000081 // Link overflow
-#define SXG_RCV_STATUS_LINK_UFLOW 0x00000080 // Link underflow
-#define SXG_RCV_STATUS_LINK_8023 0x00000020 // 802.3
-#define SXG_RCV_STATUS_LINK_SNAP 0x00000010 // Snap
-#define SXG_RCV_STATUS_LINK_VLAN 0x00000008 // VLAN
+#define SXG_RCV_STATUS_LINK_CODE 0x00000084 // Link code error
+#define SXG_RCV_STATUS_LINK_DRIBBLE 0x00000083 // Dribble nibble
+#define SXG_RCV_STATUS_LINK_CRC 0x00000082 // CRC error
+#define SXG_RCV_STATUS_LINK_OFLOW 0x00000081 // Link overflow
+#define SXG_RCV_STATUS_LINK_UFLOW 0x00000080 // Link underflow
+#define SXG_RCV_STATUS_LINK_8023 0x00000020 // 802.3
+#define SXG_RCV_STATUS_LINK_SNAP 0x00000010 // Snap
+#define SXG_RCV_STATUS_LINK_VLAN 0x00000008 // VLAN
#define SXG_RCV_STATUS_LINK_TYPE_MASK 0x00000007 // Network type mask
-#define SXG_RCV_STATUS_LINK_CONTROL 0x00000003 // Control packet
-#define SXG_RCV_STATUS_LINK_IPV6 0x00000002 // IPv6 packet
-#define SXG_RCV_STATUS_LINK_IPV4 0x00000001 // IPv4 packet
+#define SXG_RCV_STATUS_LINK_CONTROL 0x00000003 // Control packet
+#define SXG_RCV_STATUS_LINK_IPV6 0x00000002 // IPv6 packet
+#define SXG_RCV_STATUS_LINK_IPV4 0x00000001 // IPv4 packet
/***************************************************************************
* Sahara receive and transmit configuration registers
***************************************************************************/
-#define RCV_CONFIG_RESET 0x80000000 // RcvConfig register reset
-#define RCV_CONFIG_ENABLE 0x40000000 // Enable the receive logic
-#define RCV_CONFIG_ENPARSE 0x20000000 // Enable the receive parser
-#define RCV_CONFIG_SOCKET 0x10000000 // Enable the socket detector
-#define RCV_CONFIG_RCVBAD 0x08000000 // Receive all bad frames
-#define RCV_CONFIG_CONTROL 0x04000000 // Receive all control frames
-#define RCV_CONFIG_RCVPAUSE 0x02000000 // Enable pause transmit when attn
-#define RCV_CONFIG_TZIPV6 0x01000000 // Include TCP port w/ IPv6 toeplitz
-#define RCV_CONFIG_TZIPV4 0x00800000 // Include TCP port w/ IPv4 toeplitz
-#define RCV_CONFIG_FLUSH 0x00400000 // Flush buffers
+#define RCV_CONFIG_RESET 0x80000000 // RcvConfig register reset
+#define RCV_CONFIG_ENABLE 0x40000000 // Enable the receive logic
+#define RCV_CONFIG_ENPARSE 0x20000000 // Enable the receive parser
+#define RCV_CONFIG_SOCKET 0x10000000 // Enable the socket detector
+#define RCV_CONFIG_RCVBAD 0x08000000 // Receive all bad frames
+#define RCV_CONFIG_CONTROL 0x04000000 // Receive all control frames
+#define RCV_CONFIG_RCVPAUSE 0x02000000 // Enable pause transmit when attn
+#define RCV_CONFIG_TZIPV6 0x01000000 // Include TCP port w/ IPv6 toeplitz
+#define RCV_CONFIG_TZIPV4 0x00800000 // Include TCP port w/ IPv4 toeplitz
+#define RCV_CONFIG_FLUSH 0x00400000 // Flush buffers
#define RCV_CONFIG_PRIORITY_MASK 0x00300000 // Priority level
#define RCV_CONFIG_HASH_MASK 0x00030000 // Hash depth
-#define RCV_CONFIG_HASH_8 0x00000000 // Hash depth 8
-#define RCV_CONFIG_HASH_16 0x00010000 // Hash depth 16
-#define RCV_CONFIG_HASH_4 0x00020000 // Hash depth 4
-#define RCV_CONFIG_HASH_2 0x00030000 // Hash depth 2
+#define RCV_CONFIG_HASH_8 0x00000000 // Hash depth 8
+#define RCV_CONFIG_HASH_16 0x00010000 // Hash depth 16
+#define RCV_CONFIG_HASH_4 0x00020000 // Hash depth 4
+#define RCV_CONFIG_HASH_2 0x00030000 // Hash depth 2
#define RCV_CONFIG_BUFLEN_MASK 0x0000FFF0 // Buffer length bits 15:4. ie multiple of 16.
-#define RCV_CONFIG_SKT_DIS 0x00000008 // Disable socket detection on attn
+#define RCV_CONFIG_SKT_DIS 0x00000008 // Disable socket detection on attn
// Macro to determine RCV_CONFIG_BUFLEN based on maximum frame size.
// We add 18 bytes for Sahara receive status and padding, plus 4 bytes for CRC,
// and round up to nearest 16 byte boundary
#define RCV_CONFIG_BUFSIZE(_MaxFrame) ((((_MaxFrame) + 22) + 15) & RCV_CONFIG_BUFLEN_MASK)
-#define XMT_CONFIG_RESET 0x80000000 // XmtConfig register reset
-#define XMT_CONFIG_ENABLE 0x40000000 // Enable transmit logic
+#define XMT_CONFIG_RESET 0x80000000 // XmtConfig register reset
+#define XMT_CONFIG_ENABLE 0x40000000 // Enable transmit logic
#define XMT_CONFIG_MAC_PARITY 0x20000000 // Inhibit MAC RAM parity error
#define XMT_CONFIG_BUF_PARITY 0x10000000 // Inhibit D2F buffer parity error
#define XMT_CONFIG_MEM_PARITY 0x08000000 // Inhibit 1T SRAM parity error
@@ -249,9 +249,9 @@ typedef struct _SXG_HW_REGS {
// A-XGMAC Configuration Register 1
#define AXGMAC_CFG1_XMT_PAUSE 0x80000000 // Allow the sending of Pause frames
-#define AXGMAC_CFG1_XMT_EN 0x40000000 // Enable transmit
+#define AXGMAC_CFG1_XMT_EN 0x40000000 // Enable transmit
#define AXGMAC_CFG1_RCV_PAUSE 0x20000000 // Allow the detection of Pause frames
-#define AXGMAC_CFG1_RCV_EN 0x10000000 // Enable receive
+#define AXGMAC_CFG1_RCV_EN 0x10000000 // Enable receive
#define AXGMAC_CFG1_XMT_STATE 0x04000000 // Current transmit state - READ ONLY
#define AXGMAC_CFG1_RCV_STATE 0x01000000 // Current receive state - READ ONLY
#define AXGMAC_CFG1_XOFF_SHORT 0x00001000 // Only pause for 64 slot on XOFF
@@ -262,24 +262,24 @@ typedef struct _SXG_HW_REGS {
#define AXGMAC_CFG1_RCV_FCS2 0x00000200 // Delay receive FCS 2 4-byte words
#define AXGMAC_CFG1_RCV_FCS3 0x00000300 // Delay receive FCS 3 4-byte words
#define AXGMAC_CFG1_PKT_OVERRIDE 0x00000080 // Per-packet override enable
-#define AXGMAC_CFG1_SWAP 0x00000040 // Byte swap enable
+#define AXGMAC_CFG1_SWAP 0x00000040 // Byte swap enable
#define AXGMAC_CFG1_SHORT_ASSERT 0x00000020 // ASSERT srdrpfrm on short frame (<64)
#define AXGMAC_CFG1_RCV_STRICT 0x00000010 // RCV only 802.3AE when CLEAR
#define AXGMAC_CFG1_CHECK_LEN 0x00000008 // Verify frame length
-#define AXGMAC_CFG1_GEN_FCS 0x00000004 // Generate FCS
+#define AXGMAC_CFG1_GEN_FCS 0x00000004 // Generate FCS
#define AXGMAC_CFG1_PAD_MASK 0x00000003 // Mask for pad bits
-#define AXGMAC_CFG1_PAD_64 0x00000001 // Pad frames to 64 bytes
+#define AXGMAC_CFG1_PAD_64 0x00000001 // Pad frames to 64 bytes
#define AXGMAC_CFG1_PAD_VLAN 0x00000002 // Detect VLAN and pad to 68 bytes
-#define AXGMAC_CFG1_PAD_68 0x00000003 // Pad to 68 bytes
+#define AXGMAC_CFG1_PAD_68 0x00000003 // Pad to 68 bytes
// A-XGMAC Configuration Register 2
#define AXGMAC_CFG2_GEN_PAUSE 0x80000000 // Generate single pause frame (test)
#define AXGMAC_CFG2_LF_MANUAL 0x08000000 // Manual link fault sequence
-#define AXGMAC_CFG2_LF_AUTO 0x04000000 // Auto link fault sequence
+#define AXGMAC_CFG2_LF_AUTO 0x04000000 // Auto link fault sequence
#define AXGMAC_CFG2_LF_REMOTE 0x02000000 // Remote link fault (READ ONLY)
#define AXGMAC_CFG2_LF_LOCAL 0x01000000 // Local link fault (READ ONLY)
#define AXGMAC_CFG2_IPG_MASK 0x001F0000 // Inter packet gap
-#define AXGMAC_CFG2_IPG_SHIFT 16
+#define AXGMAC_CFG2_IPG_SHIFT 16
#define AXGMAC_CFG2_PAUSE_XMT 0x00008000 // Pause transmit module
#define AXGMAC_CFG2_IPG_EXTEN 0x00000020 // Enable IPG extension algorithm
#define AXGMAC_CFG2_IPGEX_MASK 0x0000001F // IPG extension
@@ -299,9 +299,9 @@ typedef struct _SXG_HW_REGS {
#define AXGMAC_SARHIGH_OCTET_SIX 0x00FF0000 // Sixth octet
// A-XGMAC Maximum frame length register
-#define AXGMAC_MAXFRAME_XMT 0x3FFF0000 // Maximum transmit frame length
+#define AXGMAC_MAXFRAME_XMT 0x3FFF0000 // Maximum transmit frame length
#define AXGMAC_MAXFRAME_XMT_SHIFT 16
-#define AXGMAC_MAXFRAME_RCV 0x0000FFFF // Maximum receive frame length
+#define AXGMAC_MAXFRAME_RCV 0x0000FFFF // Maximum receive frame length
// This register doesn't need to be written for standard MTU.
// For jumbo, I'll just statically define the value here. This
// value sets the receive byte count to 9036 (0x234C) and the
@@ -324,34 +324,34 @@ typedef struct _SXG_HW_REGS {
// A-XGMAC AMIIM Field Register
#define AXGMAC_AMIIM_FIELD_ST 0xC0000000 // 2-bit ST field
-#define AXGMAC_AMIIM_FIELD_ST_SHIFT 30
+#define AXGMAC_AMIIM_FIELD_ST_SHIFT 30
#define AXGMAC_AMIIM_FIELD_OP 0x30000000 // 2-bit OP field
-#define AXGMAC_AMIIM_FIELD_OP_SHIFT 28
-#define AXGMAC_AMIIM_FIELD_PORT_ADDR 0x0F800000 // Port address field (hstphyadx in spec)
+#define AXGMAC_AMIIM_FIELD_OP_SHIFT 28
+#define AXGMAC_AMIIM_FIELD_PORT_ADDR 0x0F800000 // Port address field (hstphyadx in spec)
#define AXGMAC_AMIIM_FIELD_PORT_SHIFT 23
#define AXGMAC_AMIIM_FIELD_DEV_ADDR 0x007C0000 // Device address field (hstregadx in spec)
#define AXGMAC_AMIIM_FIELD_DEV_SHIFT 18
#define AXGMAC_AMIIM_FIELD_TA 0x00030000 // 2-bit TA field
-#define AXGMAC_AMIIM_FIELD_TA_SHIFT 16
+#define AXGMAC_AMIIM_FIELD_TA_SHIFT 16
#define AXGMAC_AMIIM_FIELD_DATA 0x0000FFFF // Data field
// Values for the AXGMAC_AMIIM_FIELD_OP field in the A-XGMAC AMIIM Field Register
-#define MIIM_OP_ADDR 0 // MIIM Address set operation
-#define MIIM_OP_WRITE 1 // MIIM Write register operation
-#define MIIM_OP_READ 2 // MIIM Read register operation
+#define MIIM_OP_ADDR 0 // MIIM Address set operation
+#define MIIM_OP_WRITE 1 // MIIM Write register operation
+#define MIIM_OP_READ 2 // MIIM Read register operation
#define MIIM_OP_ADDR_SHIFT (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT)
// Values for the AXGMAC_AMIIM_FIELD_PORT_ADDR field in the A-XGMAC AMIIM Field Register
-#define MIIM_PORT_NUM 1 // All Sahara MIIM modules use port 1
+#define MIIM_PORT_NUM 1 // All Sahara MIIM modules use port 1
// Values for the AXGMAC_AMIIM_FIELD_DEV_ADDR field in the A-XGMAC AMIIM Field Register
-#define MIIM_DEV_PHY_PMA 1 // PHY PMA/PMD module MIIM device number
-#define MIIM_DEV_PHY_PCS 3 // PHY PCS module MIIM device number
-#define MIIM_DEV_PHY_XS 4 // PHY XS module MIIM device number
-#define MIIM_DEV_XGXS 5 // XGXS MIIM device number
+#define MIIM_DEV_PHY_PMA 1 // PHY PMA/PMD module MIIM device number
+#define MIIM_DEV_PHY_PCS 3 // PHY PCS module MIIM device number
+#define MIIM_DEV_PHY_XS 4 // PHY XS module MIIM device number
+#define MIIM_DEV_XGXS 5 // XGXS MIIM device number
// Values for the AXGMAC_AMIIM_FIELD_TA field in the A-XGMAC AMIIM Field Register
-#define MIIM_TA_10GB 2 // set to 2 for 10 GB operation
+#define MIIM_TA_10GB 2 // set to 2 for 10 GB operation
// A-XGMAC AMIIM Configuration Register
#define AXGMAC_AMIIM_CFG_NOPREAM 0x00000080 // Bypass preamble of mngmt frame
@@ -365,25 +365,25 @@ typedef struct _SXG_HW_REGS {
#define AXGMAC_AMIIM_INDC_BUSY 0x00000001 // Set until cmd operation complete
// Link Status and Control Register
-#define LS_PHY_CLR_RESET 0x80000000 // Clear reset signal to PHY
+#define LS_PHY_CLR_RESET 0x80000000 // Clear reset signal to PHY
#define LS_SERDES_POWER_DOWN 0x40000000 // Power down the Sahara Serdes
-#define LS_XGXS_ENABLE 0x20000000 // Enable the XAUI XGXS logic
-#define LS_XGXS_CTL 0x10000000 // Hold XAUI XGXS logic reset until Serdes is up
-#define LS_SERDES_DOWN 0x08000000 // When 0, XAUI Serdes is up and initialization is complete
-#define LS_TRACE_DOWN 0x04000000 // When 0, Trace Serdes is up and initialization is complete
-#define LS_PHY_CLK_25MHZ 0x02000000 // Set PHY clock to 25 MHz (else 156.125 MHz)
-#define LS_PHY_CLK_EN 0x01000000 // Enable clock to PHY
-#define LS_XAUI_LINK_UP 0x00000010 // XAUI link is up
-#define LS_XAUI_LINK_CHNG 0x00000008 // XAUI link status has changed
-#define LS_LINK_ALARM 0x00000004 // Link alarm pin
-#define LS_ATTN_CTRL_MASK 0x00000003 // Mask link attention control bits
-#define LS_ATTN_ALARM 0x00000000 // 00 => Attn on link alarm
+#define LS_XGXS_ENABLE 0x20000000 // Enable the XAUI XGXS logic
+#define LS_XGXS_CTL 0x10000000 // Hold XAUI XGXS logic reset until Serdes is up
+#define LS_SERDES_DOWN 0x08000000 // When 0, XAUI Serdes is up and initialization is complete
+#define LS_TRACE_DOWN 0x04000000 // When 0, Trace Serdes is up and initialization is complete
+#define LS_PHY_CLK_25MHZ 0x02000000 // Set PHY clock to 25 MHz (else 156.125 MHz)
+#define LS_PHY_CLK_EN 0x01000000 // Enable clock to PHY
+#define LS_XAUI_LINK_UP 0x00000010 // XAUI link is up
+#define LS_XAUI_LINK_CHNG 0x00000008 // XAUI link status has changed
+#define LS_LINK_ALARM 0x00000004 // Link alarm pin
+#define LS_ATTN_CTRL_MASK 0x00000003 // Mask link attention control bits
+#define LS_ATTN_ALARM 0x00000000 // 00 => Attn on link alarm
#define LS_ATTN_ALARM_OR_STAT_CHNG 0x00000001 // 01 => Attn on link alarm or status change
-#define LS_ATTN_STAT_CHNG 0x00000002 // 10 => Attn on link status change
-#define LS_ATTN_NONE 0x00000003 // 11 => no Attn
+#define LS_ATTN_STAT_CHNG 0x00000002 // 10 => Attn on link status change
+#define LS_ATTN_NONE 0x00000003 // 11 => no Attn
// Link Address High Registers
-#define LINK_ADDR_ENABLE 0x80000000 // Enable this link address
+#define LINK_ADDR_ENABLE 0x80000000 // Enable this link address
/***************************************************************************
@@ -396,7 +396,7 @@ typedef struct _SXG_HW_REGS {
#define XGXS_ADDRESS_STATUS1 0x0001 // XS Status 1
#define XGXS_ADDRESS_DEVID_LOW 0x0002 // XS Device ID (low)
#define XGXS_ADDRESS_DEVID_HIGH 0x0003 // XS Device ID (high)
-#define XGXS_ADDRESS_SPEED 0x0004 // XS Speed ability
+#define XGXS_ADDRESS_SPEED 0x0004 // XS Speed ability
#define XGXS_ADDRESS_DEV_LOW 0x0005 // XS Devices in package
#define XGXS_ADDRESS_DEV_HIGH 0x0006 // XS Devices in package
#define XGXS_ADDRESS_STATUS2 0x0008 // XS Status 2
@@ -410,27 +410,27 @@ typedef struct _SXG_HW_REGS {
#define XGXS_ADDRESS_RESET_HI2 0x8003 // Vendor-Specific Reset Hi 2
// XS Control 1 register bit definitions
-#define XGXS_CONTROL1_RESET 0x8000 // Reset - self clearing
+#define XGXS_CONTROL1_RESET 0x8000 // Reset - self clearing
#define XGXS_CONTROL1_LOOPBACK 0x4000 // Enable loopback
#define XGXS_CONTROL1_SPEED1 0x2000 // 0 = unspecified, 1 = 10Gb+
#define XGXS_CONTROL1_LOWPOWER 0x0400 // 1 = Low power mode
#define XGXS_CONTROL1_SPEED2 0x0040 // Same as SPEED1 (?)
-#define XGXS_CONTROL1_SPEED 0x003C // Everything reserved except zero (?)
+#define XGXS_CONTROL1_SPEED 0x003C // Everything reserved except zero (?)
// XS Status 1 register bit definitions
-#define XGXS_STATUS1_FAULT 0x0080 // Fault detected
-#define XGXS_STATUS1_LINK 0x0004 // 1 = Link up
+#define XGXS_STATUS1_FAULT 0x0080 // Fault detected
+#define XGXS_STATUS1_LINK 0x0004 // 1 = Link up
#define XGXS_STATUS1_LOWPOWER 0x0002 // 1 = Low power supported
// XS Speed register bit definitions
-#define XGXS_SPEED_10G 0x0001 // 1 = 10G capable
+#define XGXS_SPEED_10G 0x0001 // 1 = 10G capable
// XS Devices register bit definitions
-#define XGXS_DEVICES_DTE 0x0020 // DTE XS Present
-#define XGXS_DEVICES_PHY 0x0010 // PHY XS Present
-#define XGXS_DEVICES_PCS 0x0008 // PCS Present
-#define XGXS_DEVICES_WIS 0x0004 // WIS Present
-#define XGXS_DEVICES_PMD 0x0002 // PMD/PMA Present
+#define XGXS_DEVICES_DTE 0x0020 // DTE XS Present
+#define XGXS_DEVICES_PHY 0x0010 // PHY XS Present
+#define XGXS_DEVICES_PCS 0x0008 // PCS Present
+#define XGXS_DEVICES_WIS 0x0004 // WIS Present
+#define XGXS_DEVICES_PMD 0x0002 // PMD/PMA Present
#define XGXS_DEVICES_CLAUSE22 0x0001 // Clause 22 registers present
// XS Devices High register bit definitions
@@ -444,18 +444,18 @@ typedef struct _SXG_HW_REGS {
#define XGXS_STATUS2_RCV_FAULT 0x0400 // Receive fault
// XS Package ID High register bit definitions
-#define XGXS_PKGID_HIGH_ORG 0xFC00 // Organizationally Unique
-#define XGXS_PKGID_HIGH_MFG 0x03F0 // Manufacturer Model
-#define XGXS_PKGID_HIGH_REV 0x000F // Revision Number
+#define XGXS_PKGID_HIGH_ORG 0xFC00 // Organizationally Unique
+#define XGXS_PKGID_HIGH_MFG 0x03F0 // Manufacturer Model
+#define XGXS_PKGID_HIGH_REV 0x000F // Revision Number
// XS Lane Status register bit definitions
-#define XGXS_LANE_PHY 0x1000 // PHY/DTE lane alignment status
-#define XGXS_LANE_PATTERN 0x0800 // Pattern testing ability
-#define XGXS_LANE_LOOPBACK 0x0400 // PHY loopback ability
-#define XGXS_LANE_SYNC3 0x0008 // Lane 3 sync
-#define XGXS_LANE_SYNC2 0x0004 // Lane 2 sync
-#define XGXS_LANE_SYNC1 0x0002 // Lane 1 sync
-#define XGXS_LANE_SYNC0 0x0001 // Lane 0 sync
+#define XGXS_LANE_PHY 0x1000 // PHY/DTE lane alignment status
+#define XGXS_LANE_PATTERN 0x0800 // Pattern testing ability
+#define XGXS_LANE_LOOPBACK 0x0400 // PHY loopback ability
+#define XGXS_LANE_SYNC3 0x0008 // Lane 3 sync
+#define XGXS_LANE_SYNC2 0x0004 // Lane 2 sync
+#define XGXS_LANE_SYNC1 0x0002 // Lane 1 sync
+#define XGXS_LANE_SYNC0 0x0001 // Lane 0 sync
// XS Test Control register bit definitions
#define XGXS_TEST_PATTERN_ENABLE 0x0004 // Test pattern enabled
@@ -473,10 +473,10 @@ typedef struct _SXG_HW_REGS {
// LASI (Link Alarm Status Interrupt) Registers (located in MIIM_DEV_PHY_PMA device)
#define LASI_RX_ALARM_CONTROL 0x9000 // LASI RX_ALARM Control
#define LASI_TX_ALARM_CONTROL 0x9001 // LASI TX_ALARM Control
-#define LASI_CONTROL 0x9002 // LASI Control
+#define LASI_CONTROL 0x9002 // LASI Control
#define LASI_RX_ALARM_STATUS 0x9003 // LASI RX_ALARM Status
#define LASI_TX_ALARM_STATUS 0x9004 // LASI TX_ALARM Status
-#define LASI_STATUS 0x9005 // LASI Status
+#define LASI_STATUS 0x9005 // LASI Status
// LASI_CONTROL bit definitions
#define LASI_CTL_RX_ALARM_ENABLE 0x0004 // Enable RX_ALARM interrupts
@@ -489,34 +489,34 @@ typedef struct _SXG_HW_REGS {
#define LASI_STATUS_LS_ALARM 0x0001 // Link Status
// PHY registers - PMA/PMD (device 1)
-#define PHY_PMA_CONTROL1 0x0000 // PMA/PMD Control 1
-#define PHY_PMA_STATUS1 0x0001 // PMA/PMD Status 1
-#define PHY_PMA_RCV_DET 0x000A // PMA/PMD Receive Signal Detect
+#define PHY_PMA_CONTROL1 0x0000 // PMA/PMD Control 1
+#define PHY_PMA_STATUS1 0x0001 // PMA/PMD Status 1
+#define PHY_PMA_RCV_DET 0x000A // PMA/PMD Receive Signal Detect
// other PMA/PMD registers exist and can be defined as needed
// PHY registers - PCS (device 3)
-#define PHY_PCS_CONTROL1 0x0000 // PCS Control 1
-#define PHY_PCS_STATUS1 0x0001 // PCS Status 1
-#define PHY_PCS_10G_STATUS1 0x0020 // PCS 10GBASE-R Status 1
+#define PHY_PCS_CONTROL1 0x0000 // PCS Control 1
+#define PHY_PCS_STATUS1 0x0001 // PCS Status 1
+#define PHY_PCS_10G_STATUS1 0x0020 // PCS 10GBASE-R Status 1
// other PCS registers exist and can be defined as needed
// PHY registers - XS (device 4)
-#define PHY_XS_CONTROL1 0x0000 // XS Control 1
-#define PHY_XS_STATUS1 0x0001 // XS Status 1
-#define PHY_XS_LANE_STATUS 0x0018 // XS Lane Status
+#define PHY_XS_CONTROL1 0x0000 // XS Control 1
+#define PHY_XS_STATUS1 0x0001 // XS Status 1
+#define PHY_XS_LANE_STATUS 0x0018 // XS Lane Status
// other XS registers exist and can be defined as needed
// PHY_PMA_CONTROL1 register bit definitions
-#define PMA_CONTROL1_RESET 0x8000 // PMA/PMD reset
+#define PMA_CONTROL1_RESET 0x8000 // PMA/PMD reset
// PHY_PMA_RCV_DET register bit definitions
-#define PMA_RCV_DETECT 0x0001 // PMA/PMD receive signal detect
+#define PMA_RCV_DETECT 0x0001 // PMA/PMD receive signal detect
// PHY_PCS_10G_STATUS1 register bit definitions
-#define PCS_10B_BLOCK_LOCK 0x0001 // PCS 10GBASE-R locked to receive blocks
+#define PCS_10B_BLOCK_LOCK 0x0001 // PCS 10GBASE-R locked to receive blocks
// PHY_XS_LANE_STATUS register bit definitions
-#define XS_LANE_ALIGN 0x1000 // XS transmit lanes aligned
+#define XS_LANE_ALIGN 0x1000 // XS transmit lanes aligned
// PHY Microcode download data structure
typedef struct _PHY_UCODE {
@@ -558,8 +558,8 @@ typedef struct _XMT_DESC {
// command codes
#define XMT_DESC_CMD_RAW_SEND 0 // raw send descriptor
#define XMT_DESC_CMD_CSUM_INSERT 1 // checksum insert descriptor
-#define XMT_DESC_CMD_FORMAT 2 // format descriptor
-#define XMT_DESC_CMD_PRIME 3 // prime descriptor
+#define XMT_DESC_CMD_FORMAT 2 // format descriptor
+#define XMT_DESC_CMD_PRIME 3 // prime descriptor
#define XMT_DESC_CMD_CODE_SHFT 6 // comand code shift (shift to bits [31:30] in word 0)
// shifted command codes
#define XMT_RAW_SEND (XMT_DESC_CMD_RAW_SEND << XMT_DESC_CMD_CODE_SHFT)
@@ -569,22 +569,22 @@ typedef struct _XMT_DESC {
// XMT_DESC Control Byte (XmtCtl) definitions
// NOTE: These bits do not work on Sahara (Rev A)!
-#define XMT_CTL_PAUSE_FRAME 0x80 // current frame is a pause control frame (for statistics)
+#define XMT_CTL_PAUSE_FRAME 0x80 // current frame is a pause control frame (for statistics)
#define XMT_CTL_CONTROL_FRAME 0x40 // current frame is a control frame (for statistics)
#define XMT_CTL_PER_PKT_QUAL 0x20 // per packet qualifier
#define XMT_CTL_PAD_MODE_NONE 0x00 // do not pad frame
-#define XMT_CTL_PAD_MODE_64 0x08 // pad frame to 64 bytes
+#define XMT_CTL_PAD_MODE_64 0x08 // pad frame to 64 bytes
#define XMT_CTL_PAD_MODE_VLAN_68 0x10 // pad frame to 64 bytes, and VLAN frames to 68 bytes
-#define XMT_CTL_PAD_MODE_68 0x18 // pad frame to 68 bytes
-#define XMT_CTL_GEN_FCS 0x04 // generate FCS (CRC) for this frame
-#define XMT_CTL_DELAY_FCS_0 0x00 // do not delay FCS calcution
-#define XMT_CTL_DELAY_FCS_1 0x01 // delay FCS calculation by 1 (4-byte) word
-#define XMT_CTL_DELAY_FCS_2 0x02 // delay FCS calculation by 2 (4-byte) words
-#define XMT_CTL_DELAY_FCS_3 0x03 // delay FCS calculation by 3 (4-byte) words
+#define XMT_CTL_PAD_MODE_68 0x18 // pad frame to 68 bytes
+#define XMT_CTL_GEN_FCS 0x04 // generate FCS (CRC) for this frame
+#define XMT_CTL_DELAY_FCS_0 0x00 // do not delay FCS calcution
+#define XMT_CTL_DELAY_FCS_1 0x01 // delay FCS calculation by 1 (4-byte) word
+#define XMT_CTL_DELAY_FCS_2 0x02 // delay FCS calculation by 2 (4-byte) words
+#define XMT_CTL_DELAY_FCS_3 0x03 // delay FCS calculation by 3 (4-byte) words
// XMT_DESC XmtBufId definition
-#define XMT_BUF_ID_SHFT 8 // The Xmt buffer ID is formed by dividing
- // the buffer (DRAM) address by 256 (or << 8)
+#define XMT_BUF_ID_SHFT 8 // The Xmt buffer ID is formed by dividing
+ // the buffer (DRAM) address by 256 (or << 8)
/*****************************************************************************
* Receiver Sequencer Definitions
@@ -594,8 +594,8 @@ typedef struct _XMT_DESC {
#define RCV_EVTQ_RBFID_MASK 0x0000FFFF // bit mask for the Receive Buffer ID
// Receive Buffer ID definition
-#define RCV_BUF_ID_SHFT 5 // The Rcv buffer ID is formed by dividing
- // the buffer (DRAM) address by 32 (or << 5)
+#define RCV_BUF_ID_SHFT 5 // The Rcv buffer ID is formed by dividing
+ // the buffer (DRAM) address by 32 (or << 5)
// Format of the 18 byte Receive Buffer returned by the
// Receive Sequencer for received packets
@@ -623,48 +623,48 @@ typedef struct _RCV_BUF_HDR {
* Queue definitions
*****************************************************************************/
-// Ingress (read only) queue numbers
-#define PXY_BUF_Q 0 // Proxy Buffer Queue
-#define HST_EVT_Q 1 // Host Event Queue
-#define XMT_BUF_Q 2 // Transmit Buffer Queue
-#define SKT_EVL_Q 3 // RcvSqr Socket Event Low Priority Queue
-#define RCV_EVL_Q 4 // RcvSqr Rcv Event Low Priority Queue
-#define SKT_EVH_Q 5 // RcvSqr Socket Event High Priority Queue
-#define RCV_EVH_Q 6 // RcvSqr Rcv Event High Priority Queue
-#define DMA_RSP_Q 7 // Dma Response Queue - one per CPU context
-// Local (read/write) queue numbers
-#define LOCAL_A_Q 8 // Spare local Queue
-#define LOCAL_B_Q 9 // Spare local Queue
-#define LOCAL_C_Q 10 // Spare local Queue
-#define FSM_EVT_Q 11 // Finite-State-Machine Event Queue
-#define SBF_PAL_Q 12 // System Buffer Physical Address (low) Queue
-#define SBF_PAH_Q 13 // System Buffer Physical Address (high) Queue
-#define SBF_VAL_Q 14 // System Buffer Virtual Address (low) Queue
-#define SBF_VAH_Q 15 // System Buffer Virtual Address (high) Queue
-// Egress (write only) queue numbers
-#define H2G_CMD_Q 16 // Host to GlbRam DMA Command Queue
-#define H2D_CMD_Q 17 // Host to DRAM DMA Command Queue
-#define G2H_CMD_Q 18 // GlbRam to Host DMA Command Queue
-#define G2D_CMD_Q 19 // GlbRam to DRAM DMA Command Queue
-#define D2H_CMD_Q 20 // DRAM to Host DMA Command Queue
-#define D2G_CMD_Q 21 // DRAM to GlbRam DMA Command Queue
-#define D2D_CMD_Q 22 // DRAM to DRAM DMA Command Queue
-#define PXL_CMD_Q 23 // Low Priority Proxy Command Queue
-#define PXH_CMD_Q 24 // High Priority Proxy Command Queue
-#define RSQ_CMD_Q 25 // Receive Sequencer Command Queue
-#define RCV_BUF_Q 26 // Receive Buffer Queue
-
-// Bit definitions for the Proxy Command queues (PXL_CMD_Q and PXH_CMD_Q)
-#define PXY_COPY_EN 0x00200000 // enable copy of xmt descriptor to xmt command queue
-#define PXY_SIZE_16 0x00000000 // copy 16 bytes
-#define PXY_SIZE_32 0x00100000 // copy 32 bytes
+/* Ingress (read only) queue numbers */
+#define PXY_BUF_Q 0 /* Proxy Buffer Queue */
+#define HST_EVT_Q 1 /* Host Event Queue */
+#define XMT_BUF_Q 2 /* Transmit Buffer Queue */
+#define SKT_EVL_Q 3 /* RcvSqr Socket Event Low Priority Queue */
+#define RCV_EVL_Q 4 /* RcvSqr Rcv Event Low Priority Queue */
+#define SKT_EVH_Q 5 /* RcvSqr Socket Event High Priority Queue */
+#define RCV_EVH_Q 6 /* RcvSqr Rcv Event High Priority Queue */
+#define DMA_RSP_Q 7 /* Dma Response Queue - one per CPU context */
+/* Local (read/write) queue numbers */
+#define LOCAL_A_Q 8 /* Spare local Queue */
+#define LOCAL_B_Q 9 /* Spare local Queue */
+#define LOCAL_C_Q 10 /* Spare local Queue */
+#define FSM_EVT_Q 11 /* Finite-State-Machine Event Queue */
+#define SBF_PAL_Q 12 /* System Buffer Physical Address (low) Queue */
+#define SBF_PAH_Q 13 /* System Buffer Physical Address (high) Queue */
+#define SBF_VAL_Q 14 /* System Buffer Virtual Address (low) Queue */
+#define SBF_VAH_Q 15 /* System Buffer Virtual Address (high) Queue */
+/* Egress (write only) queue numbers */
+#define H2G_CMD_Q 16 /* Host to GlbRam DMA Command Queue */
+#define H2D_CMD_Q 17 /* Host to DRAM DMA Command Queue */
+#define G2H_CMD_Q 18 /* GlbRam to Host DMA Command Queue */
+#define G2D_CMD_Q 19 /* GlbRam to DRAM DMA Command Queue */
+#define D2H_CMD_Q 20 /* DRAM to Host DMA Command Queue */
+#define D2G_CMD_Q 21 /* DRAM to GlbRam DMA Command Queue */
+#define D2D_CMD_Q 22 /* DRAM to DRAM DMA Command Queue */
+#define PXL_CMD_Q 23 /* Low Priority Proxy Command Queue */
+#define PXH_CMD_Q 24 /* High Priority Proxy Command Queue */
+#define RSQ_CMD_Q 25 /* Receive Sequencer Command Queue */
+#define RCV_BUF_Q 26 /* Receive Buffer Queue */
+
+/* Bit definitions for the Proxy Command queues (PXL_CMD_Q and PXH_CMD_Q) */
+#define PXY_COPY_EN 0x00200000 /* enable copy of xmt descriptor to xmt command queue */
+#define PXY_SIZE_16 0x00000000 /* copy 16 bytes */
+#define PXY_SIZE_32 0x00100000 /* copy 32 bytes */
/*****************************************************************************
* SXG EEPROM/Flash Configuration Definitions
*****************************************************************************/
#pragma pack(push, 1)
-//
+/* */
typedef struct _HW_CFG_DATA {
ushort Addr;
union {
@@ -673,22 +673,22 @@ typedef struct _HW_CFG_DATA {
};
} HW_CFG_DATA, *PHW_CFG_DATA;
-//
+/* */
#define NUM_HW_CFG_ENTRIES ((128/sizeof(HW_CFG_DATA)) - 4)
-// MAC address
+/* MAC address */
typedef struct _SXG_CONFIG_MAC {
- unsigned char MacAddr[6]; // MAC Address
+ unsigned char MacAddr[6]; /* MAC Address */
} SXG_CONFIG_MAC, *PSXG_CONFIG_MAC;
-//
+/* */
typedef struct _ATK_FRU {
unsigned char PartNum[6];
unsigned char Revision[2];
unsigned char Serial[14];
} ATK_FRU, *PATK_FRU;
-// OEM FRU Format types
+/* OEM FRU Format types */
#define ATK_FRU_FORMAT 0x0000
#define CPQ_FRU_FORMAT 0x0001
#define DELL_FRU_FORMAT 0x0002
@@ -697,24 +697,24 @@ typedef struct _ATK_FRU {
#define EMC_FRU_FORMAT 0x0005
#define NO_FRU_FORMAT 0xFFFF
-// EEPROM/Flash Format
+/* EEPROM/Flash Format */
typedef struct _SXG_CONFIG {
- //
- // Section 1 (128 bytes)
- //
- ushort MagicWord; // EEPROM/FLASH Magic code 'A5A5'
- ushort SpiClks; // SPI bus clock dividers
+ /* */
+ /* Section 1 (128 bytes) */
+ /* */
+ ushort MagicWord; /* EEPROM/FLASH Magic code 'A5A5' */
+ ushort SpiClks; /* SPI bus clock dividers */
HW_CFG_DATA HwCfg[NUM_HW_CFG_ENTRIES];
- //
- //
- //
- ushort Version; // EEPROM format version
- SXG_CONFIG_MAC MacAddr[4]; // space for 4 MAC addresses
- ATK_FRU AtkFru; // FRU information
- ushort OemFruFormat; // OEM FRU format type
- unsigned char OemFru[76]; // OEM FRU information (optional)
- ushort Checksum; // Checksum of section 2
- // CS info XXXTODO
+ /* */
+ /* */
+ /* */
+ ushort Version; /* EEPROM format version */
+ SXG_CONFIG_MAC MacAddr[4]; /* space for 4 MAC addresses */
+ ATK_FRU AtkFru; /* FRU information */
+ ushort OemFruFormat; /* OEM FRU format type */
+ unsigned char OemFru[76]; /* OEM FRU information (optional) */
+ ushort Checksum; /* Checksum of section 2 */
+ /* CS info XXXTODO */
} SXG_CONFIG, *PSXG_CONFIG;
#pragma pack(pop)
@@ -723,12 +723,12 @@ typedef struct _SXG_CONFIG {
*****************************************************************************/
// Sahara (ASIC level) defines
-#define SAHARA_GRAM_SIZE 0x020000 // GRAM size - 128 KB
-#define SAHARA_DRAM_SIZE 0x200000 // DRAM size - 2 MB
-#define SAHARA_QRAM_SIZE 0x004000 // QRAM size - 16K entries (64 KB)
-#define SAHARA_WCS_SIZE 0x002000 // WCS - 8K instructions (x 108 bits)
+#define SAHARA_GRAM_SIZE 0x020000 // GRAM size - 128 KB
+#define SAHARA_DRAM_SIZE 0x200000 // DRAM size - 2 MB
+#define SAHARA_QRAM_SIZE 0x004000 // QRAM size - 16K entries (64 KB)
+#define SAHARA_WCS_SIZE 0x002000 // WCS - 8K instructions (x 108 bits)
// Arabia (board level) defines
-#define FLASH_SIZE 0x080000 // 512 KB (4 Mb)
-#define EEPROM_SIZE_XFMR 512 // true EEPROM size (bytes), including xfmr area
-#define EEPROM_SIZE_NO_XFMR 256 // EEPROM size excluding xfmr area
+#define FLASH_SIZE 0x080000 // 512 KB (4 Mb)
+#define EEPROM_SIZE_XFMR 512 // true EEPROM size (bytes), including xfmr area
+#define EEPROM_SIZE_NO_XFMR 256 // EEPROM size excluding xfmr area
diff --git a/drivers/staging/sxg/sxgphycode.h b/drivers/staging/sxg/sxgphycode.h
index 26b36c81eb1..8dbaeda7eca 100644
--- a/drivers/staging/sxg/sxgphycode.h
+++ b/drivers/staging/sxg/sxgphycode.h
@@ -34,7 +34,7 @@ static PHY_UCODE PhyUcode[] = {
*/
/* Addr, Data */
{0xc017, 0xfeb0}, /* flip RX_LOS polarity (mandatory */
- /* patch for SFP+ applications) */
+ /* patch for SFP+ applications) */
{0xC001, 0x0428}, /* flip RX serial polarity */
{0xc013, 0xf341}, /* invert lxmit clock (mandatory patch) */
@@ -43,7 +43,7 @@ static PHY_UCODE PhyUcode[] = {
{0xc210, 0x8000}, /* reset datapath (mandatory patch) */
{0xc210, 0x0000}, /* reset datapath (mandatory patch) */
{0x0000, 0x0032}, /* wait for 50ms for datapath reset to */
- /* complete. (mandatory patch) */
+ /* complete. (mandatory patch) */
/* Configure the LED's */
{0xc214, 0x0099}, /* configure the LED drivers */
@@ -52,15 +52,15 @@ static PHY_UCODE PhyUcode[] = {
/* Transceiver-specific MDIO Patches: */
{0xc010, 0x448a}, /* (bit 14) mask out high BER input from the */
- /* LOS signal in 1.000A */
- /* (mandatory patch for SR code)*/
+ /* LOS signal in 1.000A */
+ /* (mandatory patch for SR code) */
{0xc003, 0x0181}, /* (bit 7) enable the CDR inc setting in */
- /* 1.C005 (mandatory patch for SR code) */
+ /* 1.C005 (mandatory patch for SR code) */
/* Transceiver-specific Microcontroller Initialization: */
{0xc04a, 0x5200}, /* activate microcontroller and pause */
{0x0000, 0x0032}, /* wait 50ms for microcontroller before */
- /* writing in code. */
+ /* writing in code. */
/* code block starts here: */
{0xcc00, 0x2009},
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index e64918f42ff..72e209276ea 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -221,7 +221,7 @@ static void usbip_dump_request_type(__u8 rt)
static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
{
if (!cmd) {
- printk(" %s : null pointer\n", __FUNCTION__);
+ printk(" %s : null pointer\n", __func__);
return;
}
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index 933ccaf50af..58e3995d0e2 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -202,7 +202,7 @@ static void vhci_rx_pdu(struct usbip_device *ud)
ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
if (ret != sizeof(pdu)) {
uerr("receiving pdu failed! size is %d, should be %d\n",
- ret, sizeof(pdu));
+ ret, (unsigned int)sizeof(pdu));
usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
return;
}
diff --git a/drivers/staging/winbond/Kconfig b/drivers/staging/winbond/Kconfig
index 10d72bec88a..425219ed7ab 100644
--- a/drivers/staging/winbond/Kconfig
+++ b/drivers/staging/winbond/Kconfig
@@ -1,6 +1,6 @@
config W35UND
tristate "Winbond driver"
- depends on MAC80211 && WLAN_80211 && EXPERIMENTAL && !4KSTACKS
+ depends on MAC80211 && WLAN_80211 && USB && EXPERIMENTAL && !4KSTACKS
default n
---help---
This is highly experimental driver for winbond wifi card on some Kohjinsha notebooks
diff --git a/drivers/staging/winbond/README b/drivers/staging/winbond/README
index 707b6b354dc..cb944e4bf17 100644
--- a/drivers/staging/winbond/README
+++ b/drivers/staging/winbond/README
@@ -5,6 +5,7 @@ TODO:
- remove typedefs
- remove unused ioctls
- use cfg80211 for regulatory stuff
+ - fix 4k stack problems
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
Pavel Machek <pavel@suse.cz>
diff --git a/drivers/staging/winbond/bss_f.h b/drivers/staging/winbond/bss_f.h
index c957bc94f08..01318315399 100644
--- a/drivers/staging/winbond/bss_f.h
+++ b/drivers/staging/winbond/bss_f.h
@@ -24,7 +24,7 @@ void DesiredRate2InfoElement(PWB32_ADAPTER Adapter, u8 *addr, u16 *iFildOffset,
u8 *pBasicRateSet, u8 BasicRateCount,
u8 *pOperationRateSet, u8 OperationRateCount);
void BSSAddIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData);
-unsigned char boCmpMacAddr( PUCHAR, PUCHAR );
+unsigned char boCmpMacAddr( u8 *, u8 *);
unsigned char boCmpSSID(struct SSID_Element *psSSID1, struct SSID_Element *psSSID2);
u16 wBSSfindSSID(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid);
u16 wRoamingQuery(PWB32_ADAPTER Adapter);
@@ -42,11 +42,11 @@ void RateReSortForSRate(PWB32_ADAPTER Adapter, u8 *RateArray, u8 num);
void Assemble_IE(PWB32_ADAPTER Adapter, u16 wBssIdx);
void SetMaxTxRate(PWB32_ADAPTER Adapter);
-void CreateWpaIE(PWB32_ADAPTER Adapter, u16* iFildOffset, PUCHAR msg, struct Management_Frame* msgHeader,
+void CreateWpaIE(PWB32_ADAPTER Adapter, u16* iFildOffset, u8 *msg, struct Management_Frame* msgHeader,
struct Association_Request_Frame_Body* msgBody, u16 iMSindex); //added by WS 05/14/05
#ifdef _WPA2_
-void CreateRsnIE(PWB32_ADAPTER Adapter, u16* iFildOffset, PUCHAR msg, struct Management_Frame* msgHeader,
+void CreateRsnIE(PWB32_ADAPTER Adapter, u16* iFildOffset, u8 *msg, struct Management_Frame* msgHeader,
struct Association_Request_Frame_Body* msgBody, u16 iMSindex);//added by WS 05/14/05
u16 SearchPmkid(PWB32_ADAPTER Adapter, struct Management_Frame* msgHeader,
diff --git a/drivers/staging/winbond/ds_tkip.h b/drivers/staging/winbond/ds_tkip.h
index 29e5055b45a..6841d66e7e8 100644
--- a/drivers/staging/winbond/ds_tkip.h
+++ b/drivers/staging/winbond/ds_tkip.h
@@ -25,9 +25,9 @@ typedef struct tkip
s32 bytes_in_M; // # bytes in M
} tkip_t;
-//void _append_data( PUCHAR pData, u16 size, tkip_t *p );
-void Mds_MicGet( void* Adapter, void* pRxLayer1, PUCHAR pKey, PUCHAR pMic );
-void Mds_MicFill( void* Adapter, void* pDes, PUCHAR XmitBufAddress );
+//void _append_data( u8 *pData, u16 size, tkip_t *p );
+void Mds_MicGet( void* Adapter, void* pRxLayer1, u8 *pKey, u8 *pMic );
+void Mds_MicFill( void* Adapter, void* pDes, u8 *XmitBufAddress );
diff --git a/drivers/staging/winbond/linux/common.h b/drivers/staging/winbond/linux/common.h
index 6b00bad74f7..712a86cfa68 100644
--- a/drivers/staging/winbond/linux/common.h
+++ b/drivers/staging/winbond/linux/common.h
@@ -39,14 +39,6 @@
// Common type definition
//===============================================================
-typedef u8* PUCHAR;
-typedef s8* PCHAR;
-typedef u8* PBOOLEAN;
-typedef u16* PUSHORT;
-typedef u32* PULONG;
-typedef s16* PSHORT;
-
-
//===========================================
#define IGNORE 2
#define SUCCESS 1
@@ -110,16 +102,9 @@ typedef struct urb * PURB;
#define OS_ATOMIC_READ( _A, _V ) _V
#define OS_ATOMIC_INC( _A, _V ) EncapAtomicInc( _A, (void*)_V )
#define OS_ATOMIC_DEC( _A, _V ) EncapAtomicDec( _A, (void*)_V )
-#define OS_MEMORY_CLEAR( _A, _S ) memset( (PUCHAR)_A,0,_S)
+#define OS_MEMORY_CLEAR( _A, _S ) memset( (u8 *)_A,0,_S)
#define OS_MEMORY_COMPARE( _A, _B, _S ) (memcmp(_A,_B,_S)? 0 : 1) // Definition is reverse with Ndis 1: the same 0: different
-
-#define OS_SPIN_LOCK spinlock_t
-#define OS_SPIN_LOCK_ALLOCATE( _S ) spin_lock_init( _S );
-#define OS_SPIN_LOCK_FREE( _S )
-#define OS_SPIN_LOCK_ACQUIRED( _S ) spin_lock_irq( _S )
-#define OS_SPIN_LOCK_RELEASED( _S ) spin_unlock_irq( _S );
-
#define OS_TIMER struct timer_list
#define OS_TIMER_INITIAL( _T, _F, _P ) \
{ \
diff --git a/drivers/staging/winbond/linux/wb35reg.c b/drivers/staging/winbond/linux/wb35reg.c
index 2c0b454e8ca..ebb6db5438a 100644
--- a/drivers/staging/winbond/linux/wb35reg.c
+++ b/drivers/staging/winbond/linux/wb35reg.c
@@ -10,7 +10,7 @@ extern void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency);
// Flag : AUTO_INCREMENT - RegisterNo will auto increment 4
// NO_INCREMENT - Function will write data into the same register
unsigned char
-Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag)
+Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PURB pUrb = NULL;
@@ -30,13 +30,13 @@ Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8
if( pUrb && pRegQueue ) {
pRegQueue->DIRECT = 2;// burst write register
pRegQueue->INDEX = RegisterNo;
- pRegQueue->pBuffer = (PULONG)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ pRegQueue->pBuffer = (u32 *)((u8 *)pRegQueue + sizeof(REG_QUEUE));
memcpy( pRegQueue->pBuffer, pRegisterData, DataSize );
//the function for reversing register data from little endian to big endian
for( i=0; i<NumberOfData ; i++ )
pRegQueue->pBuffer[i] = cpu_to_le32( pRegQueue->pBuffer[i] );
- dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE) + DataSize);
+ dr = (struct usb_ctrlrequest *)((u8 *)pRegQueue + sizeof(REG_QUEUE) + DataSize);
dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
dr->bRequest = 0x04; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16( Flag ); // 0: Register number auto-increment, 1: No auto increment
@@ -46,14 +46,14 @@ Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
- OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq( &pWb35Reg->EP0VM_spin_lock );
if (pWb35Reg->pRegFirst == NULL)
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start(pHwData);
@@ -181,7 +181,7 @@ Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
pRegQueue->INDEX = RegisterNo;
pRegQueue->VALUE = cpu_to_le32(RegisterValue);
pRegQueue->RESERVED_VALID = FALSE;
- dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ dr = (struct usb_ctrlrequest *)((u8 *)pRegQueue + sizeof(REG_QUEUE));
dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16(0x0);
@@ -193,14 +193,14 @@ Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
- OS_SPIN_LOCK_ACQUIRED(&pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq(&pWb35Reg->EP0VM_spin_lock );
if (pWb35Reg->pRegFirst == NULL)
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start(pHwData);
@@ -220,7 +220,7 @@ Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
// FALSE : register not support
unsigned char
Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue,
- PCHAR pValue, s8 Len)
+ s8 *pValue, s8 Len)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
struct usb_ctrlrequest *dr;
@@ -243,7 +243,7 @@ Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 Register
//NOTE : Users must guarantee the size of value will not exceed the buffer size.
memcpy(pRegQueue->RESERVED, pValue, Len);
pRegQueue->RESERVED_VALID = TRUE;
- dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ dr = (struct usb_ctrlrequest *)((u8 *)pRegQueue + sizeof(REG_QUEUE));
dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16(0x0);
@@ -254,14 +254,14 @@ Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 Register
pRegQueue->Next = NULL;
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
- OS_SPIN_LOCK_ACQUIRED (&pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq (&pWb35Reg->EP0VM_spin_lock );
if( pWb35Reg->pRegFirst == NULL )
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
- OS_SPIN_LOCK_RELEASED ( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq ( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start(pHwData);
@@ -278,10 +278,10 @@ Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 Register
// FALSE : register not support
// pRegisterValue : It must be a resident buffer due to asynchronous read register.
unsigned char
-Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
+Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
- PULONG pltmp = pRegisterValue;
+ u32 * pltmp = pRegisterValue;
int ret = -1;
// Module shutdown
@@ -327,7 +327,7 @@ Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue
// FALSE : register not support
// pRegisterValue : It must be a resident buffer due to asynchronous read register.
unsigned char
-Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
+Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
struct usb_ctrlrequest * dr;
@@ -348,7 +348,7 @@ Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
pRegQueue->DIRECT = 0;// read register
pRegQueue->INDEX = RegisterNo;
pRegQueue->pBuffer = pRegisterValue;
- dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ dr = (struct usb_ctrlrequest *)((u8 *)pRegQueue + sizeof(REG_QUEUE));
dr->bRequestType = USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN;
dr->bRequest = 0x01; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16(0x0);
@@ -359,14 +359,14 @@ Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
pRegQueue->Next = NULL;
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
- OS_SPIN_LOCK_ACQUIRED ( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq ( &pWb35Reg->EP0VM_spin_lock );
if( pWb35Reg->pRegFirst == NULL )
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start( pHwData );
@@ -399,7 +399,7 @@ Wb35Reg_EP0VM(phw_data_t pHwData )
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PURB pUrb;
struct usb_ctrlrequest *dr;
- PULONG pBuffer;
+ u32 * pBuffer;
int ret = -1;
PREG_QUEUE pRegQueue;
@@ -411,9 +411,9 @@ Wb35Reg_EP0VM(phw_data_t pHwData )
goto cleanup;
// Get the register data and send to USB through Irp
- OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
if (!pRegQueue)
goto cleanup;
@@ -429,7 +429,7 @@ Wb35Reg_EP0VM(phw_data_t pHwData )
usb_fill_control_urb( pUrb, pHwData->WbUsb.udev,
REG_DIRECTION(pHwData->WbUsb.udev,pRegQueue),
- (PUCHAR)dr,pBuffer,cpu_to_le16(dr->wLength),
+ (u8 *)dr,pBuffer,cpu_to_le16(dr->wLength),
Wb35Reg_EP0VM_complete, (void*)pHwData);
pWb35Reg->EP0vm_state = VM_RUNNING;
@@ -468,12 +468,12 @@ Wb35Reg_EP0VM_complete(PURB pUrb)
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
} else {
// Complete to send, remove the URB from the first
- OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
if (pRegQueue == pWb35Reg->pRegLast)
pWb35Reg->pRegLast = NULL;
pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
if (pWb35Reg->EP0VM_status) {
#ifdef _PE_REG_DUMP_
@@ -513,7 +513,7 @@ Wb35Reg_destroy(phw_data_t pHwData)
OS_SLEEP(10000); // Delay for waiting function enter 940623.1.b
// Release all the data in RegQueue
- OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
while (pRegQueue) {
if (pRegQueue == pWb35Reg->pRegLast)
@@ -521,7 +521,7 @@ Wb35Reg_destroy(phw_data_t pHwData)
pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
pUrb = pRegQueue->pUrb;
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
if (pUrb) {
usb_free_urb(pUrb);
kfree(pRegQueue);
@@ -530,14 +530,11 @@ Wb35Reg_destroy(phw_data_t pHwData)
WBDEBUG(("EP0 queue release error\n"));
#endif
}
- OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_irq( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
}
- OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
-
- // Free resource
- OS_SPIN_LOCK_FREE( &pWb35Reg->EP0VM_spin_lock );
+ spin_unlock_irq( &pWb35Reg->EP0VM_spin_lock );
}
//====================================================================================
@@ -550,7 +547,7 @@ unsigned char Wb35Reg_initial(phw_data_t pHwData)
u32 SoftwareSet, VCO_trim, TxVga, Region_ScanInterval;
// Spin lock is acquired for read and write IRP command
- OS_SPIN_LOCK_ALLOCATE( &pWb35Reg->EP0VM_spin_lock );
+ spin_lock_init( &pWb35Reg->EP0VM_spin_lock );
// Getting RF module type from EEPROM ------------------------------------
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x080d0000 ); // Start EEPROM access + Read + address(0x0d)
@@ -655,7 +652,7 @@ unsigned char Wb35Reg_initial(phw_data_t pHwData)
// version in _GENREQ.ASM of the DWB NE1000/2000 driver.
//==================================================================================
u32
-CardComputeCrc(PUCHAR Buffer, u32 Length)
+CardComputeCrc(u8 * Buffer, u32 Length)
{
u32 Crc, Carry;
u32 i, j;
diff --git a/drivers/staging/winbond/linux/wb35reg_f.h b/drivers/staging/winbond/linux/wb35reg_f.h
index 38e2906b51a..3006cfe99cc 100644
--- a/drivers/staging/winbond/linux/wb35reg_f.h
+++ b/drivers/staging/winbond/linux/wb35reg_f.h
@@ -29,16 +29,16 @@ void EEPROMTxVgaAdjust( phw_data_t pHwData ); // 20060619.5 Add
void Wb35Reg_destroy( phw_data_t pHwData );
-unsigned char Wb35Reg_Read( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue );
-unsigned char Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue );
+unsigned char Wb35Reg_Read( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue );
+unsigned char Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue );
unsigned char Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
unsigned char Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
unsigned char Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData,
u16 RegisterNo,
u32 RegisterValue,
- PCHAR pValue,
- s8 Len);
-unsigned char Wb35Reg_BurstWrite( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag );
+ s8 *pValue,
+ s8 Len);
+unsigned char Wb35Reg_BurstWrite( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag );
void Wb35Reg_EP0VM( phw_data_t pHwData );
void Wb35Reg_EP0VM_start( phw_data_t pHwData );
@@ -47,7 +47,7 @@ void Wb35Reg_EP0VM_complete( PURB pUrb );
u32 BitReverse( u32 dwData, u32 DataLength);
void CardGetMulticastBit( u8 Address[MAC_ADDR_LENGTH], u8 *Byte, u8 *Value );
-u32 CardComputeCrc( PUCHAR Buffer, u32 Length );
+u32 CardComputeCrc( u8 * Buffer, u32 Length );
void Wb35Reg_phy_calibration( phw_data_t pHwData );
void Wb35Reg_Update( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
diff --git a/drivers/staging/winbond/linux/wb35reg_s.h b/drivers/staging/winbond/linux/wb35reg_s.h
index a7595b1e733..8b35b93f7f0 100644
--- a/drivers/staging/winbond/linux/wb35reg_s.h
+++ b/drivers/staging/winbond/linux/wb35reg_s.h
@@ -75,7 +75,7 @@ typedef struct _REG_QUEUE
union
{
u32 VALUE;
- PULONG pBuffer;
+ u32 * pBuffer;
};
u8 RESERVED[4];// space reserved for communication
@@ -143,7 +143,7 @@ typedef struct _WB35REG
//-------------------
// VM
//-------------------
- OS_SPIN_LOCK EP0VM_spin_lock; // 4B
+ spinlock_t EP0VM_spin_lock; // 4B
u32 EP0VM_status;//$$
PREG_QUEUE pRegFirst;
PREG_QUEUE pRegLast;
diff --git a/drivers/staging/winbond/linux/wb35rx.c b/drivers/staging/winbond/linux/wb35rx.c
index 26157eb3d5a..b4b9f5f371d 100644
--- a/drivers/staging/winbond/linux/wb35rx.c
+++ b/drivers/staging/winbond/linux/wb35rx.c
@@ -27,7 +27,7 @@ void Wb35Rx_start(phw_data_t pHwData)
void Wb35Rx( phw_data_t pHwData )
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
- PUCHAR pRxBufferAddress;
+ u8 * pRxBufferAddress;
PURB pUrb = (PURB)pWb35Rx->RxUrb;
int retv;
u32 RxBufferId;
@@ -35,51 +35,50 @@ void Wb35Rx( phw_data_t pHwData )
//
// Issuing URB
//
- do {
- if (pHwData->SurpriseRemove || pHwData->HwStop)
- break;
+ if (pHwData->SurpriseRemove || pHwData->HwStop)
+ goto error;
- if (pWb35Rx->rx_halt)
- break;
+ if (pWb35Rx->rx_halt)
+ goto error;
- // Get RxBuffer's ID
- RxBufferId = pWb35Rx->RxBufferId;
- if (!pWb35Rx->RxOwner[RxBufferId]) {
- // It's impossible to run here.
- #ifdef _PE_RX_DUMP_
- WBDEBUG(("Rx driver fifo unavailable\n"));
- #endif
- break;
- }
+ // Get RxBuffer's ID
+ RxBufferId = pWb35Rx->RxBufferId;
+ if (!pWb35Rx->RxOwner[RxBufferId]) {
+ // It's impossible to run here.
+ #ifdef _PE_RX_DUMP_
+ WBDEBUG(("Rx driver fifo unavailable\n"));
+ #endif
+ goto error;
+ }
- // Update buffer point, then start to bulkin the data from USB
- pWb35Rx->RxBufferId++;
- pWb35Rx->RxBufferId %= MAX_USB_RX_BUFFER_NUMBER;
+ // Update buffer point, then start to bulkin the data from USB
+ pWb35Rx->RxBufferId++;
+ pWb35Rx->RxBufferId %= MAX_USB_RX_BUFFER_NUMBER;
- pWb35Rx->CurrentRxBufferId = RxBufferId;
+ pWb35Rx->CurrentRxBufferId = RxBufferId;
- if (1 != OS_MEMORY_ALLOC((void* *)&pWb35Rx->pDRx, MAX_USB_RX_BUFFER)) {
- printk("w35und: Rx memory alloc failed\n");
- break;
- }
- pRxBufferAddress = pWb35Rx->pDRx;
+ if (1 != OS_MEMORY_ALLOC((void* *)&pWb35Rx->pDRx, MAX_USB_RX_BUFFER)) {
+ printk("w35und: Rx memory alloc failed\n");
+ goto error;
+ }
+ pRxBufferAddress = pWb35Rx->pDRx;
- usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
- usb_rcvbulkpipe(pHwData->WbUsb.udev, 3),
- pRxBufferAddress, MAX_USB_RX_BUFFER,
- Wb35Rx_Complete, pHwData);
+ usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
+ usb_rcvbulkpipe(pHwData->WbUsb.udev, 3),
+ pRxBufferAddress, MAX_USB_RX_BUFFER,
+ Wb35Rx_Complete, pHwData);
- pWb35Rx->EP3vm_state = VM_RUNNING;
+ pWb35Rx->EP3vm_state = VM_RUNNING;
- retv = wb_usb_submit_urb(pUrb);
+ retv = wb_usb_submit_urb(pUrb);
- if (retv != 0) {
- printk("Rx URB sending error\n");
- break;
- }
- return;
- } while(FALSE);
+ if (retv != 0) {
+ printk("Rx URB sending error\n");
+ goto error;
+ }
+ return;
+error:
// VM stop
pWb35Rx->EP3vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
@@ -89,7 +88,7 @@ void Wb35Rx_Complete(PURB pUrb)
{
phw_data_t pHwData = pUrb->context;
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
- PUCHAR pRxBufferAddress;
+ u8 * pRxBufferAddress;
u32 SizeCheck;
u16 BulkLength;
u32 RxBufferId;
@@ -99,65 +98,63 @@ void Wb35Rx_Complete(PURB pUrb)
pWb35Rx->EP3vm_state = VM_COMPLETED;
pWb35Rx->EP3VM_status = pUrb->status;//Store the last result of Irp
- do {
- RxBufferId = pWb35Rx->CurrentRxBufferId;
+ RxBufferId = pWb35Rx->CurrentRxBufferId;
- pRxBufferAddress = pWb35Rx->pDRx;
- BulkLength = (u16)pUrb->actual_length;
+ pRxBufferAddress = pWb35Rx->pDRx;
+ BulkLength = (u16)pUrb->actual_length;
- // The IRP is completed
- pWb35Rx->EP3vm_state = VM_COMPLETED;
+ // The IRP is completed
+ pWb35Rx->EP3vm_state = VM_COMPLETED;
- if (pHwData->SurpriseRemove || pHwData->HwStop) // Must be here, or RxBufferId is invalid
- break;
+ if (pHwData->SurpriseRemove || pHwData->HwStop) // Must be here, or RxBufferId is invalid
+ goto error;
- if (pWb35Rx->rx_halt)
- break;
+ if (pWb35Rx->rx_halt)
+ goto error;
- // Start to process the data only in successful condition
- pWb35Rx->RxOwner[ RxBufferId ] = 0; // Set the owner to driver
- R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
+ // Start to process the data only in successful condition
+ pWb35Rx->RxOwner[ RxBufferId ] = 0; // Set the owner to driver
+ R00.value = le32_to_cpu(*(u32 *)pRxBufferAddress);
- // The URB is completed, check the result
- if (pWb35Rx->EP3VM_status != 0) {
- #ifdef _PE_USB_STATE_DUMP_
- WBDEBUG(("EP3 IoCompleteRoutine return error\n"));
- DebugUsbdStatusInformation( pWb35Rx->EP3VM_status );
- #endif
- pWb35Rx->EP3vm_state = VM_STOP;
- break;
- }
+ // The URB is completed, check the result
+ if (pWb35Rx->EP3VM_status != 0) {
+ #ifdef _PE_USB_STATE_DUMP_
+ WBDEBUG(("EP3 IoCompleteRoutine return error\n"));
+ DebugUsbdStatusInformation( pWb35Rx->EP3VM_status );
+ #endif
+ pWb35Rx->EP3vm_state = VM_STOP;
+ goto error;
+ }
- // 20060220 For recovering. check if operating in single USB mode
- if (!HAL_USB_MODE_BURST(pHwData)) {
- SizeCheck = R00.R00_receive_byte_count; //20060926 anson's endian
- if ((SizeCheck & 0x03) > 0)
- SizeCheck -= 4;
- SizeCheck = (SizeCheck + 3) & ~0x03;
- SizeCheck += 12; // 8 + 4 badbeef
- if ((BulkLength > 1600) ||
- (SizeCheck > 1600) ||
- (BulkLength != SizeCheck) ||
- (BulkLength == 0)) { // Add for fail Urb
- pWb35Rx->EP3vm_state = VM_STOP;
- pWb35Rx->Ep3ErrorCount2++;
- }
+ // 20060220 For recovering. check if operating in single USB mode
+ if (!HAL_USB_MODE_BURST(pHwData)) {
+ SizeCheck = R00.R00_receive_byte_count; //20060926 anson's endian
+ if ((SizeCheck & 0x03) > 0)
+ SizeCheck -= 4;
+ SizeCheck = (SizeCheck + 3) & ~0x03;
+ SizeCheck += 12; // 8 + 4 badbeef
+ if ((BulkLength > 1600) ||
+ (SizeCheck > 1600) ||
+ (BulkLength != SizeCheck) ||
+ (BulkLength == 0)) { // Add for fail Urb
+ pWb35Rx->EP3vm_state = VM_STOP;
+ pWb35Rx->Ep3ErrorCount2++;
}
+ }
- // Indicating the receiving data
- pWb35Rx->ByteReceived += BulkLength;
- pWb35Rx->RxBufferSize[ RxBufferId ] = BulkLength;
-
- if (!pWb35Rx->RxOwner[ RxBufferId ])
- Wb35Rx_indicate(pHwData);
+ // Indicating the receiving data
+ pWb35Rx->ByteReceived += BulkLength;
+ pWb35Rx->RxBufferSize[ RxBufferId ] = BulkLength;
- kfree(pWb35Rx->pDRx);
- // Do the next receive
- Wb35Rx(pHwData);
- return;
+ if (!pWb35Rx->RxOwner[ RxBufferId ])
+ Wb35Rx_indicate(pHwData);
- } while(FALSE);
+ kfree(pWb35Rx->pDRx);
+ // Do the next receive
+ Wb35Rx(pHwData);
+ return;
+error:
pWb35Rx->RxOwner[ RxBufferId ] = 1; // Set the owner to hardware
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
pWb35Rx->EP3vm_state = VM_STOP;
@@ -223,7 +220,7 @@ void Wb35Rx_reset_descriptor( phw_data_t pHwData )
void Wb35Rx_adjust(PDESCRIPTOR pRxDes)
{
- PULONG pRxBufferAddress;
+ u32 * pRxBufferAddress;
u32 DecryptionMethod;
u32 i;
u16 BufferSize;
@@ -264,7 +261,7 @@ u16 Wb35Rx_indicate(phw_data_t pHwData)
{
DESCRIPTOR RxDes;
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
- PUCHAR pRxBufferAddress;
+ u8 * pRxBufferAddress;
u16 PacketSize;
u16 stmp, BufferSize, stmp2 = 0;
u32 RxBufferId;
@@ -283,13 +280,13 @@ u16 Wb35Rx_indicate(phw_data_t pHwData)
// Parse the bulkin buffer
while (BufferSize >= 4) {
- if ((cpu_to_le32(*(PULONG)pRxBufferAddress) & 0x0fffffff) == RX_END_TAG) //Is ending? 921002.9.a
+ if ((cpu_to_le32(*(u32 *)pRxBufferAddress) & 0x0fffffff) == RX_END_TAG) //Is ending? 921002.9.a
break;
// Get the R00 R01 first
- RxDes.R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
+ RxDes.R00.value = le32_to_cpu(*(u32 *)pRxBufferAddress);
PacketSize = (u16)RxDes.R00.R00_receive_byte_count;
- RxDes.R01.value = le32_to_cpu(*((PULONG)(pRxBufferAddress+4)));
+ RxDes.R01.value = le32_to_cpu(*((u32 *)(pRxBufferAddress+4)));
// For new DMA 4k
if ((PacketSize & 0x03) > 0)
PacketSize -= 4;
diff --git a/drivers/staging/winbond/linux/wb35rx_s.h b/drivers/staging/winbond/linux/wb35rx_s.h
index 53b831fdeb7..b90c269e6ad 100644
--- a/drivers/staging/winbond/linux/wb35rx_s.h
+++ b/drivers/staging/winbond/linux/wb35rx_s.h
@@ -41,7 +41,7 @@ typedef struct _WB35RX
u32 Ep3ErrorCount2; // 20060625.1 Usbd for Rx DMA error count
int EP3VM_status;
- PUCHAR pDRx;
+ u8 * pDRx;
} WB35RX, *PWB35RX;
diff --git a/drivers/staging/winbond/linux/wb35tx.c b/drivers/staging/winbond/linux/wb35tx.c
index cf19c3bc524..ba9d51244e2 100644
--- a/drivers/staging/winbond/linux/wb35tx.c
+++ b/drivers/staging/winbond/linux/wb35tx.c
@@ -12,7 +12,7 @@
unsigned char
-Wb35Tx_get_tx_buffer(phw_data_t pHwData, PUCHAR *pBuffer )
+Wb35Tx_get_tx_buffer(phw_data_t pHwData, u8 **pBuffer)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
@@ -37,7 +37,7 @@ void Wb35Tx(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
PADAPTER Adapter = pHwData->Adapter;
- PUCHAR pTxBufferAddress;
+ u8 *pTxBufferAddress;
PMDS pMds = &Adapter->Mds;
struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb;
int retv;
@@ -100,25 +100,24 @@ void Wb35Tx_complete(struct urb * pUrb)
pWb35Tx->TxSendIndex++;
pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
- do {
- if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
- break;
+ if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
+ goto error;
- if (pWb35Tx->tx_halt)
- break;
+ if (pWb35Tx->tx_halt)
+ goto error;
- // The URB is completed, check the result
- if (pWb35Tx->EP4VM_status != 0) {
- printk("URB submission failed\n");
- pWb35Tx->EP4vm_state = VM_STOP;
- break; // Exit while(FALSE);
- }
+ // The URB is completed, check the result
+ if (pWb35Tx->EP4VM_status != 0) {
+ printk("URB submission failed\n");
+ pWb35Tx->EP4vm_state = VM_STOP;
+ goto error;
+ }
- Mds_Tx(Adapter);
- Wb35Tx(pHwData);
- return;
- } while(FALSE);
+ Mds_Tx(Adapter);
+ Wb35Tx(pHwData);
+ return;
+error:
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
pWb35Tx->EP4vm_state = VM_STOP;
}
@@ -225,36 +224,33 @@ void Wb35Tx_EP2VM(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb;
- PULONG pltmp = (PULONG)pWb35Tx->EP2_buf;
+ u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
int retv;
- do {
- if (pHwData->SurpriseRemove || pHwData->HwStop)
- break;
-
- if (pWb35Tx->tx_halt)
- break;
-
- //
- // Issuing URB
- //
- usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
- pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, pHwData, 32);
+ if (pHwData->SurpriseRemove || pHwData->HwStop)
+ goto error;
- pWb35Tx->EP2vm_state = VM_RUNNING;
- retv = wb_usb_submit_urb( pUrb );
+ if (pWb35Tx->tx_halt)
+ goto error;
- if(retv < 0) {
- #ifdef _PE_TX_DUMP_
- WBDEBUG(("EP2 Tx Irp sending error\n"));
- #endif
- break;
- }
+ //
+ // Issuing URB
+ //
+ usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
+ pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, pHwData, 32);
- return;
+ pWb35Tx->EP2vm_state = VM_RUNNING;
+ retv = wb_usb_submit_urb( pUrb );
- } while(FALSE);
+ if (retv < 0) {
+ #ifdef _PE_TX_DUMP_
+ WBDEBUG(("EP2 Tx Irp sending error\n"));
+ #endif
+ goto error;
+ }
+ return;
+error:
pWb35Tx->EP2vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
}
@@ -266,7 +262,7 @@ void Wb35Tx_EP2VM_complete(struct urb * pUrb)
T02_DESCRIPTOR T02, TSTATUS;
PADAPTER Adapter = (PADAPTER)pHwData->Adapter;
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
- PULONG pltmp = (PULONG)pWb35Tx->EP2_buf;
+ u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
u32 i;
u16 InterruptInLength;
@@ -275,38 +271,36 @@ void Wb35Tx_EP2VM_complete(struct urb * pUrb)
pWb35Tx->EP2vm_state = VM_COMPLETED;
pWb35Tx->EP2VM_status = pUrb->status;
- do {
- // For Linux 2.4. Interrupt will always trigger
- if( pHwData->SurpriseRemove || pHwData->HwStop ) // Let WbWlanHalt to handle surprise remove
- break;
-
- if( pWb35Tx->tx_halt )
- break;
-
- //The Urb is completed, check the result
- if (pWb35Tx->EP2VM_status != 0) {
- WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
- pWb35Tx->EP2vm_state= VM_STOP;
- break; // Exit while(FALSE);
- }
-
- // Update the Tx result
- InterruptInLength = pUrb->actual_length;
- // Modify for minimum memory access and DWORD alignment.
- T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
- InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
- InterruptInLength >>= 2; // InterruptInLength/4
- for (i=1; i<=InterruptInLength; i++) {
- T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
-
- TSTATUS.value = T02.value; //20061009 anson's endian
- Mds_SendComplete( Adapter, &TSTATUS );
- T02.value = cpu_to_le32(pltmp[i]) >> 8;
- }
-
- return;
- } while(FALSE);
+ // For Linux 2.4. Interrupt will always trigger
+ if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
+ goto error;
+
+ if (pWb35Tx->tx_halt)
+ goto error;
+
+ //The Urb is completed, check the result
+ if (pWb35Tx->EP2VM_status != 0) {
+ WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
+ pWb35Tx->EP2vm_state= VM_STOP;
+ goto error;
+ }
+ // Update the Tx result
+ InterruptInLength = pUrb->actual_length;
+ // Modify for minimum memory access and DWORD alignment.
+ T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
+ InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
+ InterruptInLength >>= 2; // InterruptInLength/4
+ for (i = 1; i <= InterruptInLength; i++) {
+ T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
+
+ TSTATUS.value = T02.value; //20061009 anson's endian
+ Mds_SendComplete( Adapter, &TSTATUS );
+ T02.value = cpu_to_le32(pltmp[i]) >> 8;
+ }
+
+ return;
+error:
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
pWb35Tx->EP2vm_state = VM_STOP;
}
diff --git a/drivers/staging/winbond/linux/wb35tx_f.h b/drivers/staging/winbond/linux/wb35tx_f.h
index 7705a8454dc..107b1291813 100644
--- a/drivers/staging/winbond/linux/wb35tx_f.h
+++ b/drivers/staging/winbond/linux/wb35tx_f.h
@@ -3,7 +3,7 @@
//====================================
unsigned char Wb35Tx_initial( phw_data_t pHwData );
void Wb35Tx_destroy( phw_data_t pHwData );
-unsigned char Wb35Tx_get_tx_buffer( phw_data_t pHwData, PUCHAR *pBuffer );
+unsigned char Wb35Tx_get_tx_buffer( phw_data_t pHwData, u8 **pBuffer );
void Wb35Tx_EP2VM( phw_data_t pHwData );
void Wb35Tx_EP2VM_start( phw_data_t pHwData );
diff --git a/drivers/staging/winbond/linux/wbusb.c b/drivers/staging/winbond/linux/wbusb.c
index cbad5fb0595..f4a7875f238 100644
--- a/drivers/staging/winbond/linux/wbusb.c
+++ b/drivers/staging/winbond/linux/wbusb.c
@@ -6,42 +6,29 @@
#include "sysdef.h"
#include <net/mac80211.h>
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
-
-//============================================================
-// vendor ID and product ID can into here for others
-//============================================================
-static struct usb_device_id Id_Table[] =
-{
- {USB_DEVICE( 0x0416, 0x0035 )},
- {USB_DEVICE( 0x18E8, 0x6201 )},
- {USB_DEVICE( 0x18E8, 0x6206 )},
- {USB_DEVICE( 0x18E8, 0x6217 )},
- {USB_DEVICE( 0x18E8, 0x6230 )},
- {USB_DEVICE( 0x18E8, 0x6233 )},
- {USB_DEVICE( 0x1131, 0x2035 )},
- { }
+static struct usb_device_id wb35_table[] __devinitdata = {
+ {USB_DEVICE(0x0416, 0x0035)},
+ {USB_DEVICE(0x18E8, 0x6201)},
+ {USB_DEVICE(0x18E8, 0x6206)},
+ {USB_DEVICE(0x18E8, 0x6217)},
+ {USB_DEVICE(0x18E8, 0x6230)},
+ {USB_DEVICE(0x18E8, 0x6233)},
+ {USB_DEVICE(0x1131, 0x2035)},
+ { 0, }
};
-MODULE_DEVICE_TABLE(usb, Id_Table);
+MODULE_DEVICE_TABLE(usb, wb35_table);
-static struct usb_driver wb35_driver = {
- .name = "w35und",
- .probe = wb35_probe,
- .disconnect = wb35_disconnect,
- .id_table = Id_Table,
-};
-
-static const struct ieee80211_rate wbsoft_rates[] = {
+static struct ieee80211_rate wbsoft_rates[] = {
{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
};
-static const struct ieee80211_channel wbsoft_channels[] = {
+static struct ieee80211_channel wbsoft_channels[] = {
{ .center_freq = 2412},
};
@@ -62,9 +49,22 @@ static void wbsoft_remove_interface(struct ieee80211_hw *dev,
printk("wbsoft_remove interface called\n");
}
-static int wbsoft_nop(void)
+static void wbsoft_stop(struct ieee80211_hw *hw)
+{
+ printk(KERN_INFO "%s called\n", __func__);
+}
+
+static int wbsoft_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
- printk("wbsoft_nop called\n");
+ printk(KERN_INFO "%s called\n", __func__);
+ return 0;
+}
+
+static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ printk(KERN_INFO "%s called\n", __func__);
return 0;
}
@@ -105,8 +105,7 @@ static void wbsoft_configure_filter(struct ieee80211_hw *dev,
*total_flags = new_flags;
}
-static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
+static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
char *buffer = kmalloc(skb->len, GFP_ATOMIC);
printk("Sending frame %d bytes\n", skb->len);
@@ -136,7 +135,7 @@ static int wbsoft_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
hal_set_current_channel(&my_adapter->sHwData, ch);
hal_set_beacon_period(&my_adapter->sHwData, conf->beacon_int);
// hal_set_cap_info(&my_adapter->sHwData, ?? );
-// hal_set_ssid(phw_data_t pHwData, PUCHAR pssid, u8 ssid_len); ??
+// hal_set_ssid(phw_data_t pHwData, u8 * pssid, u8 ssid_len); ??
hal_set_accept_broadcast(&my_adapter->sHwData, 1);
hal_set_accept_promiscuous(&my_adapter->sHwData, 1);
hal_set_accept_multicast(&my_adapter->sHwData, 1);
@@ -148,7 +147,7 @@ static int wbsoft_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
// hal_start_bss(&my_adapter->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE); ??
-//void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
+//void hal_set_rates(phw_data_t pHwData, u8 * pbss_rates,
// u8 length, unsigned char basic_rate_set)
return 0;
@@ -171,14 +170,14 @@ static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
static const struct ieee80211_ops wbsoft_ops = {
.tx = wbsoft_tx,
.start = wbsoft_start, /* Start can be pretty much empty as we do WbWLanInitialize() during probe? */
- .stop = wbsoft_nop,
+ .stop = wbsoft_stop,
.add_interface = wbsoft_add_interface,
.remove_interface = wbsoft_remove_interface,
.config = wbsoft_config,
.config_interface = wbsoft_config_interface,
.configure_filter = wbsoft_configure_filter,
- .get_stats = wbsoft_nop,
- .get_tx_stats = wbsoft_nop,
+ .get_stats = wbsoft_get_stats,
+ .get_tx_stats = wbsoft_get_tx_stats,
.get_tsf = wbsoft_get_tsf,
// conf_tx: hal_set_cwmin()/hal_set_cwmax;
};
@@ -187,21 +186,6 @@ struct wbsoft_priv {
};
-int __init wb35_init(void)
-{
- printk("[w35und]driver init\n");
- return usb_register(&wb35_driver);
-}
-
-void __exit wb35_exit(void)
-{
- printk("[w35und]driver exit\n");
- usb_deregister( &wb35_driver );
-}
-
-module_init(wb35_init);
-module_exit(wb35_exit);
-
// Usb kernel subsystem will call this function when a new device is plugged into.
int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table)
{
@@ -210,7 +194,7 @@ int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table)
PWBUSB pWbUsb;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
- int i, ret = -1;
+ int ret = -1;
u32 ltmp;
struct usb_device *udev = interface_to_usbdev(intf);
@@ -218,114 +202,95 @@ int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table)
printk("[w35und]wb35_probe ->\n");
- do {
- for (i=0; i<(sizeof(Id_Table)/sizeof(struct usb_device_id)); i++ ) {
- if ((udev->descriptor.idVendor == Id_Table[i].idVendor) &&
- (udev->descriptor.idProduct == Id_Table[i].idProduct)) {
- printk("[w35und]Found supported hardware\n");
- break;
- }
- }
- if ((i == (sizeof(Id_Table)/sizeof(struct usb_device_id)))) {
- #ifdef _PE_USB_INI_DUMP_
- WBDEBUG(("[w35und] This is not the one we are interested about\n"));
- #endif
- return -ENODEV;
- }
-
- // 20060630.2 Check the device if it already be opened
- ret = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
- 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
- 0x0, 0x400, &ltmp, 4, HZ*100 );
- if( ret < 0 )
- break;
+ // 20060630.2 Check the device if it already be opened
+ ret = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
+ 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+ 0x0, 0x400, &ltmp, 4, HZ*100 );
+ if (ret < 0)
+ goto error;
- ltmp = cpu_to_le32(ltmp);
- if (ltmp) // Is already initialized?
- break;
+ ltmp = cpu_to_le32(ltmp);
+ if (ltmp) // Is already initialized?
+ goto error;
+ Adapter = kzalloc(sizeof(ADAPTER), GFP_KERNEL);
- Adapter = kzalloc(sizeof(ADAPTER), GFP_KERNEL);
+ my_adapter = Adapter;
+ pWbLinux = &Adapter->WbLinux;
+ pWbUsb = &Adapter->sHwData.WbUsb;
+ pWbUsb->udev = udev;
- my_adapter = Adapter;
- pWbLinux = &Adapter->WbLinux;
- pWbUsb = &Adapter->sHwData.WbUsb;
- pWbUsb->udev = udev;
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
- interface = intf->cur_altsetting;
- endpoint = &interface->endpoint[0].desc;
-
- if (endpoint[2].wMaxPacketSize == 512) {
- printk("[w35und] Working on USB 2.0\n");
- pWbUsb->IsUsb20 = 1;
- }
-
- if (!WbWLanInitialize(Adapter)) {
- printk("[w35und]WbWLanInitialize fail\n");
- break;
- }
+ if (endpoint[2].wMaxPacketSize == 512) {
+ printk("[w35und] Working on USB 2.0\n");
+ pWbUsb->IsUsb20 = 1;
+ }
- {
- struct wbsoft_priv *priv;
- struct ieee80211_hw *dev;
- int res;
+ if (!WbWLanInitialize(Adapter)) {
+ printk("[w35und]WbWLanInitialize fail\n");
+ goto error;
+ }
- dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
+ {
+ struct wbsoft_priv *priv;
+ struct ieee80211_hw *dev;
+ static struct ieee80211_supported_band band;
+ int res;
- if (!dev) {
- printk("w35und: ieee80211 alloc failed\n" );
- BUG();
- }
+ dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
- my_dev = dev;
+ if (!dev) {
+ printk("w35und: ieee80211 alloc failed\n" );
+ BUG();
+ }
- SET_IEEE80211_DEV(dev, &udev->dev);
- {
- phw_data_t pHwData = &Adapter->sHwData;
- unsigned char dev_addr[MAX_ADDR_LEN];
- hal_get_permanent_address(pHwData, dev_addr);
- SET_IEEE80211_PERM_ADDR(dev, dev_addr);
- }
+ my_dev = dev;
+ SET_IEEE80211_DEV(dev, &udev->dev);
+ {
+ phw_data_t pHwData = &Adapter->sHwData;
+ unsigned char dev_addr[MAX_ADDR_LEN];
+ hal_get_permanent_address(pHwData, dev_addr);
+ SET_IEEE80211_PERM_ADDR(dev, dev_addr);
+ }
- dev->extra_tx_headroom = 12; /* FIXME */
- dev->flags = 0;
- dev->channel_change_time = 1000;
-// dev->max_rssi = 100;
+ dev->extra_tx_headroom = 12; /* FIXME */
+ dev->flags = 0;
- dev->queues = 1;
+ dev->channel_change_time = 1000;
+// dev->max_rssi = 100;
- static struct ieee80211_supported_band band;
+ dev->queues = 1;
- band.channels = wbsoft_channels;
- band.n_channels = ARRAY_SIZE(wbsoft_channels);
- band.bitrates = wbsoft_rates;
- band.n_bitrates = ARRAY_SIZE(wbsoft_rates);
+ band.channels = wbsoft_channels;
+ band.n_channels = ARRAY_SIZE(wbsoft_channels);
+ band.bitrates = wbsoft_rates;
+ band.n_bitrates = ARRAY_SIZE(wbsoft_rates);
- dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band;
+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band;
#if 0
- wbsoft_modes[0].num_channels = 1;
- wbsoft_modes[0].channels = wbsoft_channels;
- wbsoft_modes[0].mode = MODE_IEEE80211B;
- wbsoft_modes[0].num_rates = ARRAY_SIZE(wbsoft_rates);
- wbsoft_modes[0].rates = wbsoft_rates;
-
- res = ieee80211_register_hwmode(dev, &wbsoft_modes[0]);
- BUG_ON(res);
+ wbsoft_modes[0].num_channels = 1;
+ wbsoft_modes[0].channels = wbsoft_channels;
+ wbsoft_modes[0].mode = MODE_IEEE80211B;
+ wbsoft_modes[0].num_rates = ARRAY_SIZE(wbsoft_rates);
+ wbsoft_modes[0].rates = wbsoft_rates;
+
+ res = ieee80211_register_hwmode(dev, &wbsoft_modes[0]);
+ BUG_ON(res);
#endif
- res = ieee80211_register_hw(dev);
- BUG_ON(res);
- }
-
- usb_set_intfdata( intf, Adapter );
-
- printk("[w35und] _probe OK\n");
- return 0;
+ res = ieee80211_register_hw(dev);
+ BUG_ON(res);
+ }
- } while(FALSE);
+ usb_set_intfdata( intf, Adapter );
+ printk("[w35und] _probe OK\n");
+ return 0;
+error:
return -ENOMEM;
}
@@ -401,4 +366,22 @@ void wb35_disconnect(struct usb_interface *intf)
}
+static struct usb_driver wb35_driver = {
+ .name = "w35und",
+ .id_table = wb35_table,
+ .probe = wb35_probe,
+ .disconnect = wb35_disconnect,
+};
+static int __init wb35_init(void)
+{
+ return usb_register(&wb35_driver);
+}
+
+static void __exit wb35_exit(void)
+{
+ usb_deregister(&wb35_driver);
+}
+
+module_init(wb35_init);
+module_exit(wb35_exit);
diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c
index 8ce6389c413..f1de813f9c7 100644
--- a/drivers/staging/winbond/mds.c
+++ b/drivers/staging/winbond/mds.c
@@ -40,7 +40,7 @@ Mds_Tx(PADAPTER Adapter)
PMDS pMds = &Adapter->Mds;
DESCRIPTOR TxDes;
PDESCRIPTOR pTxDes = &TxDes;
- PUCHAR XmitBufAddress;
+ u8 *XmitBufAddress;
u16 XmitBufSize, PacketSize, stmp, CurrentSize, FragmentThreshold;
u8 FillIndex, TxDesIndex, FragmentCount, FillCount;
unsigned char BufferFilled = FALSE, MICAdd = 0;
@@ -90,7 +90,7 @@ Mds_Tx(PADAPTER Adapter)
BufferFilled = TRUE;
/* Leaves first u8 intact */
- memset((PUCHAR)pTxDes + 1, 0, sizeof(DESCRIPTOR) - 1);
+ memset((u8 *)pTxDes + 1, 0, sizeof(DESCRIPTOR) - 1);
TxDesIndex = pMds->TxDesIndex;//Get the current ID
pTxDes->Descriptor_ID = TxDesIndex;
@@ -229,10 +229,10 @@ Mds_SendComplete(PADAPTER Adapter, PT02_DESCRIPTOR pT02)
}
void
-Mds_HeaderCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
+Mds_HeaderCopy(PADAPTER Adapter, PDESCRIPTOR pDes, u8 *TargetBuffer)
{
PMDS pMds = &Adapter->Mds;
- PUCHAR src_buffer = pDes->buffer_address[0];//931130.5.g
+ u8 *src_buffer = pDes->buffer_address[0];//931130.5.g
PT00_DESCRIPTOR pT00;
PT01_DESCRIPTOR pT01;
u16 stmp;
@@ -276,7 +276,7 @@ Mds_HeaderCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
//
// Set tx rate
//
- stmp = *(PUSHORT)(TargetBuffer+30); // 2n alignment address
+ stmp = *(u16 *)(TargetBuffer+30); // 2n alignment address
//Use basic rate
ctmp1 = ctmpf = CURRENT_TX_RATE_FOR_MNG;
@@ -326,11 +326,13 @@ Mds_HeaderCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
// The function return the 4n size of usb pk
u16
-Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
+Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, u8 *TargetBuffer)
{
PT00_DESCRIPTOR pT00;
PMDS pMds = &Adapter->Mds;
- PUCHAR buffer, src_buffer, pctmp;
+ u8 *buffer;
+ u8 *src_buffer;
+ u8 *pctmp;
u16 Size = 0;
u16 SizeLeft, CopySize, CopyLeft, stmp;
u8 buf_index, FragmentCount = 0;
@@ -354,7 +356,7 @@ Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
SizeLeft -= CopySize;
// 1 Byte operation
- pctmp = (PUCHAR)( buffer + 8 + DOT_11_SEQUENCE_OFFSET );
+ pctmp = (u8 *)( buffer + 8 + DOT_11_SEQUENCE_OFFSET );
*pctmp &= 0xf0;
*pctmp |= FragmentCount;//931130.5.m
if( !FragmentCount )
@@ -379,7 +381,7 @@ Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
buf_index++;
buf_index %= MAX_DESCRIPTOR_BUFFER_INDEX;
} else {
- PUCHAR pctmp = pDes->buffer_address[buf_index];
+ u8 *pctmp = pDes->buffer_address[buf_index];
pctmp += CopySize;
pDes->buffer_address[buf_index] = pctmp;
pDes->buffer_size[buf_index] -= CopySize;
@@ -419,7 +421,7 @@ Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
pT00->T00_last_mpdu = 1;
pT00->T00_IsLastMpdu = 1;
- buffer = (PUCHAR)pT00 + 8; // +8 for USB hdr
+ buffer = (u8 *)pT00 + 8; // +8 for USB hdr
buffer[1] &= ~0x04; // Clear more frag bit of 802.11 frame control
pDes->FragmentCount = FragmentCount; // Update the correct fragment number
return Size;
@@ -427,7 +429,7 @@ Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
void
-Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR buffer )
+Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, u8 *buffer )
{
PT00_DESCRIPTOR pT00;
PT01_DESCRIPTOR pT01;
@@ -435,7 +437,7 @@ Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR buffer )
u8 Rate, i;
unsigned char CTS_on = FALSE, RTS_on = FALSE;
PT00_DESCRIPTOR pNextT00;
- u16 BodyLen;
+ u16 BodyLen = 0;
unsigned char boGroupAddr = FALSE;
@@ -574,7 +576,7 @@ Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR buffer )
DEFAULT_SIFSTIME*3 );
}
- ((PUSHORT)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
+ ((u16 *)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
//----20061009 add by anson's endian
pNextT00->value = cpu_to_le32(pNextT00->value);
@@ -615,7 +617,7 @@ Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR buffer )
}
}
- ((PUSHORT)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
+ ((u16 *)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
pT00->value = cpu_to_le32(pT00->value);
pT01->value = cpu_to_le32(pT01->value);
//--end 20061009 add
diff --git a/drivers/staging/winbond/mds_f.h b/drivers/staging/winbond/mds_f.h
index 651188be106..7a682d4cfbd 100644
--- a/drivers/staging/winbond/mds_f.h
+++ b/drivers/staging/winbond/mds_f.h
@@ -1,9 +1,9 @@
unsigned char Mds_initial( PADAPTER Adapter );
void Mds_Destroy( PADAPTER Adapter );
void Mds_Tx( PADAPTER Adapter );
-void Mds_HeaderCopy( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
-u16 Mds_BodyCopy( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
-void Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
+void Mds_HeaderCopy( PADAPTER Adapter, PDESCRIPTOR pDes, u8 *TargetBuffer );
+u16 Mds_BodyCopy( PADAPTER Adapter, PDESCRIPTOR pDes, u8 *TargetBuffer );
+void Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, u8 *TargetBuffer );
void Mds_SendComplete( PADAPTER Adapter, PT02_DESCRIPTOR pT02 );
void Mds_MpduProcess( PADAPTER Adapter, PDESCRIPTOR pRxDes );
void Mds_reset_descriptor( PADAPTER Adapter );
diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h
index 4738279d5f3..9df2e0936bf 100644
--- a/drivers/staging/winbond/mds_s.h
+++ b/drivers/staging/winbond/mds_s.h
@@ -86,7 +86,7 @@ typedef struct _MDS
{
// For Tx usage
u8 TxOwner[ ((MAX_USB_TX_BUFFER_NUMBER + 3) & ~0x03) ];
- PUCHAR pTxBuffer;
+ u8 *pTxBuffer;
u16 TxBufferSize[ ((MAX_USB_TX_BUFFER_NUMBER + 1) & ~0x01) ];
u8 TxDesFrom[ ((MAX_USB_TX_DESCRIPTOR + 3) & ~0x03) ];//931130.4.u // 1: MLME 2: NDIS control 3: NDIS data
u8 TxCountInBuffer[ ((MAX_USB_TX_DESCRIPTOR + 3) & ~0x03) ]; // 20060928
@@ -103,7 +103,7 @@ typedef struct _MDS
u16 TxResult[ ((MAX_USB_TX_DESCRIPTOR + 1) & ~0x01) ];//Collect the sending result of Mpdu
u8 MicRedundant[8]; // For tmp use
- PUCHAR MicWriteAddress[2]; //The start address to fill the Mic, use 2 point due to Mic maybe fragment
+ u8 *MicWriteAddress[2]; //The start address to fill the Mic, use 2 point due to Mic maybe fragment
u16 MicWriteSize[2]; //931130.4.x
@@ -144,7 +144,7 @@ typedef struct _MDS
typedef struct _RxBuffer
{
- PUCHAR pBufferAddress; // Pointer the received data buffer.
+ u8 * pBufferAddress; // Pointer the received data buffer.
u16 BufferSize;
u8 RESERVED;
u8 BufferIndex;// Only 1 byte
@@ -176,7 +176,7 @@ typedef struct _RXLAYER1
/////////////////////////////////////////////////////////////////////////////////////////////
// For brand-new Rx system
u8 ReservedBuffer[ 2400 ];//If Buffer ID is reserved one, it must copy the data into this area
- PUCHAR ReservedBufferPoint;// Point to the next availabe address of reserved buffer
+ u8 *ReservedBufferPoint;// Point to the next availabe address of reserved buffer
}RXLAYER1, * PRXLAYER1;
diff --git a/drivers/staging/winbond/mlme_s.h b/drivers/staging/winbond/mlme_s.h
index 58094f61c03..039fd408ba6 100644
--- a/drivers/staging/winbond/mlme_s.h
+++ b/drivers/staging/winbond/mlme_s.h
@@ -125,12 +125,12 @@
typedef struct _MLME_FRAME
{
//NDIS_PACKET MLME_Packet;
- PCHAR pMMPDU;
+ s8 * pMMPDU;
u16 len;
u8 DataType;
u8 IsInUsed;
- OS_SPIN_LOCK MLMESpinLock;
+ spinlock_t MLMESpinLock;
u8 TxMMPDU[MAX_NUM_TX_MMPDU][MAX_MMPDU_SIZE];
u8 TxMMPDUInUse[ (MAX_NUM_TX_MMPDU+3) & ~0x03 ];
diff --git a/drivers/staging/winbond/mlmetxrx.c b/drivers/staging/winbond/mlmetxrx.c
index 46b091e9679..e8533b8d197 100644
--- a/drivers/staging/winbond/mlmetxrx.c
+++ b/drivers/staging/winbond/mlmetxrx.c
@@ -113,13 +113,13 @@ MLME_GetNextPacket(PADAPTER Adapter, PDESCRIPTOR pDes)
pDes->Type = Adapter->sMlmeFrame.DataType;
}
-void MLMEfreeMMPDUBuffer(PWB32_ADAPTER Adapter, PCHAR pData)
+void MLMEfreeMMPDUBuffer(PWB32_ADAPTER Adapter, s8 *pData)
{
int i;
// Reclaim the data buffer
for (i = 0; i < MAX_NUM_TX_MMPDU; i++) {
- if (pData == (PCHAR)&(Adapter->sMlmeFrame.TxMMPDU[i]))
+ if (pData == (s8 *)&(Adapter->sMlmeFrame.TxMMPDU[i]))
break;
}
if (Adapter->sMlmeFrame.TxMMPDUInUse[i])
diff --git a/drivers/staging/winbond/mlmetxrx_f.h b/drivers/staging/winbond/mlmetxrx_f.h
index d74e225be21..24cd5f308d9 100644
--- a/drivers/staging/winbond/mlmetxrx_f.h
+++ b/drivers/staging/winbond/mlmetxrx_f.h
@@ -20,7 +20,7 @@ MLMEGetMMPDUBuffer(
PWB32_ADAPTER Adapter
);
-void MLMEfreeMMPDUBuffer( PWB32_ADAPTER Adapter, PCHAR pData);
+void MLMEfreeMMPDUBuffer( PWB32_ADAPTER Adapter, s8 * pData);
void MLME_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
u8 MLMESendFrame( PWB32_ADAPTER Adapter,
@@ -42,7 +42,7 @@ MLMERcvFrame(
void
MLMEReturnPacket(
PWB32_ADAPTER Adapter,
- PUCHAR pRxBufer
+ u8 * pRxBufer
);
#ifdef _IBSS_BEACON_SEQ_STICK_
s8 SendBCNullData(PWB32_ADAPTER Adapter, u16 wIdx);
diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c
index b475c7a7c42..57af5b83150 100644
--- a/drivers/staging/winbond/reg.c
+++ b/drivers/staging/winbond/reg.c
@@ -922,16 +922,16 @@ Uxx_ReadEthernetAddress( phw_data_t pHwData )
// Only unplug and plug again can make hardware read EEPROM again. 20060727
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08000000 ); // Start EEPROM access + Read + address(0x0d)
Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
- *(PUSHORT)pHwData->PermanentMacAddress = cpu_to_le16((u16)ltmp); //20060926 anson's endian
+ *(u16 *)pHwData->PermanentMacAddress = cpu_to_le16((u16)ltmp); //20060926 anson's endian
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08010000 ); // Start EEPROM access + Read + address(0x0d)
Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
- *(PUSHORT)(pHwData->PermanentMacAddress + 2) = cpu_to_le16((u16)ltmp); //20060926 anson's endian
+ *(u16 *)(pHwData->PermanentMacAddress + 2) = cpu_to_le16((u16)ltmp); //20060926 anson's endian
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08020000 ); // Start EEPROM access + Read + address(0x0d)
Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
- *(PUSHORT)(pHwData->PermanentMacAddress + 4) = cpu_to_le16((u16)ltmp); //20060926 anson's endian
- *(PUSHORT)(pHwData->PermanentMacAddress + 6) = 0;
- Wb35Reg_WriteSync( pHwData, 0x03e8, cpu_to_le32(*(PULONG)pHwData->PermanentMacAddress) ); //20060926 anson's endian
- Wb35Reg_WriteSync( pHwData, 0x03ec, cpu_to_le32(*(PULONG)(pHwData->PermanentMacAddress+4)) ); //20060926 anson's endian
+ *(u16 *)(pHwData->PermanentMacAddress + 4) = cpu_to_le16((u16)ltmp); //20060926 anson's endian
+ *(u16 *)(pHwData->PermanentMacAddress + 6) = 0;
+ Wb35Reg_WriteSync( pHwData, 0x03e8, cpu_to_le32(*(u32 *)pHwData->PermanentMacAddress) ); //20060926 anson's endian
+ Wb35Reg_WriteSync( pHwData, 0x03ec, cpu_to_le32(*(u32 *)(pHwData->PermanentMacAddress+4)) ); //20060926 anson's endian
}
@@ -1038,7 +1038,7 @@ void
RFSynthesizer_initial(phw_data_t pHwData)
{
u32 altmp[32];
- PULONG pltmp = altmp;
+ u32 * pltmp = altmp;
u32 ltmp;
u8 number=0x00; // The number of register vale
u8 i;
@@ -2358,11 +2358,11 @@ void Mxx_initial( phw_data_t pHwData )
pltmp[2] = pWb35Reg->M2C_MacControl;
// M30 BSSID
- pltmp[3] = *(PULONG)pHwData->bssid;
+ pltmp[3] = *(u32 *)pHwData->bssid;
// M34
pHwData->AID = DEFAULT_AID;
- tmp = *(PUSHORT)(pHwData->bssid+4);
+ tmp = *(u16 *)(pHwData->bssid+4);
tmp |= DEFAULT_AID << 16;
pltmp[4] = tmp;
@@ -2428,7 +2428,7 @@ void GetTxVgaFromEEPROM( phw_data_t pHwData )
{
u32 i, j, ltmp;
u16 Value[MAX_TXVGA_EEPROM];
- PUCHAR pctmp;
+ u8 *pctmp;
u8 ctmp=0;
// Get the entire TxVga setting in EEPROM
@@ -2441,7 +2441,7 @@ void GetTxVgaFromEEPROM( phw_data_t pHwData )
}
// Adjust the filed which fills with reserved value.
- pctmp = (PUCHAR)Value;
+ pctmp = (u8 *)Value;
for( i=0; i<(MAX_TXVGA_EEPROM*2); i++ )
{
if( pctmp[i] != 0xff )
@@ -2480,7 +2480,7 @@ void GetTxVgaFromEEPROM( phw_data_t pHwData )
// This function will use default TxVgaSettingInEEPROM data to calculate new TxVga.
void EEPROMTxVgaAdjust( phw_data_t pHwData ) // 20060619.5 Add
{
- PUCHAR pTxVga = pHwData->TxVgaSettingInEEPROM;
+ u8 * pTxVga = pHwData->TxVgaSettingInEEPROM;
s16 i, stmp;
//-- 2.4G -- 20060704.2 Request from Tiger
diff --git a/drivers/staging/winbond/sme_api.c b/drivers/staging/winbond/sme_api.c
index 40e93b7600e..31c9673ea86 100644
--- a/drivers/staging/winbond/sme_api.c
+++ b/drivers/staging/winbond/sme_api.c
@@ -10,4 +10,5 @@
s8 sme_get_rssi(void *pcore_data, s32 *prssi)
{
BUG();
+ return 0;
}
diff --git a/drivers/staging/winbond/sme_api.h b/drivers/staging/winbond/sme_api.h
index 016b225ca4a..745eb376bc7 100644
--- a/drivers/staging/winbond/sme_api.h
+++ b/drivers/staging/winbond/sme_api.h
@@ -208,7 +208,7 @@ s8 sme_set_tx_antenna(void *pcore_data, u32 TxAntenna);
s8 sme_set_IBSS_chan(void *pcore_data, ChanInfo chan);
//20061108 WPS
-s8 sme_set_IE_append(void *pcore_data, PUCHAR buffer, u16 buf_len);
+s8 sme_set_IE_append(void *pcore_data, u8 *buffer, u16 buf_len);
diff --git a/drivers/staging/winbond/wbhal.c b/drivers/staging/winbond/wbhal.c
index daf44224755..5d68ecec34c 100644
--- a/drivers/staging/winbond/wbhal.c
+++ b/drivers/staging/winbond/wbhal.c
@@ -1,13 +1,13 @@
#include "os_common.h"
-void hal_get_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
+void hal_get_ethernet_address( phw_data_t pHwData, u8 *current_address )
{
if( pHwData->SurpriseRemove ) return;
memcpy( current_address, pHwData->CurrentMacAddress, ETH_LENGTH_OF_ADDRESS );
}
-void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
+void hal_set_ethernet_address( phw_data_t pHwData, u8 *current_address )
{
u32 ltmp[2];
@@ -15,13 +15,13 @@ void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
memcpy( pHwData->CurrentMacAddress, current_address, ETH_LENGTH_OF_ADDRESS );
- ltmp[0]= cpu_to_le32( *(PULONG)pHwData->CurrentMacAddress );
- ltmp[1]= cpu_to_le32( *(PULONG)(pHwData->CurrentMacAddress + 4) ) & 0xffff;
+ ltmp[0]= cpu_to_le32( *(u32 *)pHwData->CurrentMacAddress );
+ ltmp[1]= cpu_to_le32( *(u32 *)(pHwData->CurrentMacAddress + 4) ) & 0xffff;
Wb35Reg_BurstWrite( pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT );
}
-void hal_get_permanent_address( phw_data_t pHwData, PUCHAR pethernet_address )
+void hal_get_permanent_address( phw_data_t pHwData, u8 *pethernet_address )
{
if( pHwData->SurpriseRemove ) return;
@@ -89,7 +89,7 @@ void hal_halt(phw_data_t pHwData, void *ppa_data)
}
//---------------------------------------------------------------------------------------------------
-void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
+void hal_set_rates(phw_data_t pHwData, u8 *pbss_rates,
u8 length, unsigned char basic_rate_set)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
@@ -158,13 +158,13 @@ void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
// Fill data into support rate until buffer full
//---20060926 add by anson's endian
for (i=0; i<4; i++)
- *(PULONG)(SupportedRate+(i<<2)) = cpu_to_le32( *(PULONG)(SupportedRate+(i<<2)) );
+ *(u32 *)(SupportedRate+(i<<2)) = cpu_to_le32( *(u32 *)(SupportedRate+(i<<2)) );
//--- end 20060926 add by anson's endian
- Wb35Reg_BurstWrite( pHwData,0x087c, (PULONG)SupportedRate, 4, AUTO_INCREMENT );
- pWb35Reg->M7C_MacControl = ((PULONG)SupportedRate)[0];
- pWb35Reg->M80_MacControl = ((PULONG)SupportedRate)[1];
- pWb35Reg->M84_MacControl = ((PULONG)SupportedRate)[2];
- pWb35Reg->M88_MacControl = ((PULONG)SupportedRate)[3];
+ Wb35Reg_BurstWrite( pHwData,0x087c, (u32 *)SupportedRate, 4, AUTO_INCREMENT );
+ pWb35Reg->M7C_MacControl = ((u32 *)SupportedRate)[0];
+ pWb35Reg->M80_MacControl = ((u32 *)SupportedRate)[1];
+ pWb35Reg->M84_MacControl = ((u32 *)SupportedRate)[2];
+ pWb35Reg->M88_MacControl = ((u32 *)SupportedRate)[3];
// Fill length
tmp = Count1<<28 | Count2<<24;
@@ -206,7 +206,7 @@ void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel )
pWb35Reg->M28_MacControl &= ~0xff; // Clean channel information field
pWb35Reg->M28_MacControl |= channel.ChanNo;
Wb35Reg_WriteWithCallbackValue( pHwData, 0x0828, pWb35Reg->M28_MacControl,
- (PCHAR)&channel, sizeof(ChanInfo));
+ (s8 *)&channel, sizeof(ChanInfo));
}
//---------------------------------------------------------------------------------------------------
void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel )
@@ -277,7 +277,7 @@ void hal_set_accept_beacon( phw_data_t pHwData, u8 enable )
Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
}
//---------------------------------------------------------------------------------------------------
-void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number )
+void hal_set_multicast_address( phw_data_t pHwData, u8 *address, u8 number )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
u8 Byte, Bit;
@@ -297,7 +297,7 @@ void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number )
}
// Updating register
- Wb35Reg_BurstWrite( pHwData, 0x0804, (PULONG)pWb35Reg->Multicast, 2, AUTO_INCREMENT );
+ Wb35Reg_BurstWrite( pHwData, 0x0804, (u32 *)pWb35Reg->Multicast, 2, AUTO_INCREMENT );
}
//---------------------------------------------------------------------------------------------------
u8 hal_get_accept_beacon( phw_data_t pHwData )
@@ -806,7 +806,7 @@ u8 hal_get_hw_radio_off( phw_data_t pHwData )
}
}
-unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, PULONG pValue )
+unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, u32 * pValue )
{
if( number < 0x1000 )
number += 0x1000;
diff --git a/drivers/staging/winbond/wbhal_f.h b/drivers/staging/winbond/wbhal_f.h
index fe25f97af72..ea9531ac847 100644
--- a/drivers/staging/winbond/wbhal_f.h
+++ b/drivers/staging/winbond/wbhal_f.h
@@ -16,23 +16,23 @@
//====================================================================================
// Function declaration
//====================================================================================
-void hal_remove_mapping_key( phw_data_t pHwData, PUCHAR pmac_addr );
+void hal_remove_mapping_key( phw_data_t pHwData, u8 *pmac_addr );
void hal_remove_default_key( phw_data_t pHwData, u32 index );
-unsigned char hal_set_mapping_key( phw_data_t Adapter, PUCHAR pmac_addr, u8 null_key, u8 wep_on, PUCHAR ptx_tsc, PUCHAR prx_tsc, u8 key_type, u8 key_len, PUCHAR pkey_data );
-unsigned char hal_set_default_key( phw_data_t Adapter, u8 index, u8 null_key, u8 wep_on, PUCHAR ptx_tsc, PUCHAR prx_tsc, u8 key_type, u8 key_len, PUCHAR pkey_data );
+unsigned char hal_set_mapping_key( phw_data_t Adapter, u8 *pmac_addr, u8 null_key, u8 wep_on, u8 *ptx_tsc, u8 *prx_tsc, u8 key_type, u8 key_len, u8 *pkey_data );
+unsigned char hal_set_default_key( phw_data_t Adapter, u8 index, u8 null_key, u8 wep_on, u8 *ptx_tsc, u8 *prx_tsc, u8 key_type, u8 key_len, u8 *pkey_data );
void hal_clear_all_default_key( phw_data_t pHwData );
void hal_clear_all_group_key( phw_data_t pHwData );
void hal_clear_all_mapping_key( phw_data_t pHwData );
void hal_clear_all_key( phw_data_t pHwData );
-void hal_get_ethernet_address( phw_data_t pHwData, PUCHAR current_address );
-void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address );
-void hal_get_permanent_address( phw_data_t pHwData, PUCHAR pethernet_address );
+void hal_get_ethernet_address( phw_data_t pHwData, u8 *current_address );
+void hal_set_ethernet_address( phw_data_t pHwData, u8 *current_address );
+void hal_get_permanent_address( phw_data_t pHwData, u8 *pethernet_address );
unsigned char hal_init_hardware( phw_data_t pHwData, PADAPTER Adapter );
void hal_set_power_save_mode( phw_data_t pHwData, unsigned char power_save, unsigned char wakeup, unsigned char dtim );
-void hal_get_power_save_mode( phw_data_t pHwData, PBOOLEAN pin_pwr_save );
+void hal_get_power_save_mode( phw_data_t pHwData, u8 *pin_pwr_save );
void hal_set_slot_time( phw_data_t pHwData, u8 type );
#define hal_set_atim_window( _A, _ATM )
-void hal_set_rates( phw_data_t pHwData, PUCHAR pbss_rates, u8 length, unsigned char basic_rate_set );
+void hal_set_rates( phw_data_t pHwData, u8 *pbss_rates, u8 length, unsigned char basic_rate_set );
#define hal_set_basic_rates( _A, _R, _L ) hal_set_rates( _A, _R, _L, TRUE )
#define hal_set_op_rates( _A, _R, _L ) hal_set_rates( _A, _R, _L, FALSE )
void hal_start_bss( phw_data_t pHwData, u8 mac_op_mode );
@@ -40,19 +40,19 @@ void hal_join_request( phw_data_t pHwData, u8 bss_type ); // 0:BSS STA 1:IBSS
void hal_stop_sync_bss( phw_data_t pHwData );
void hal_resume_sync_bss( phw_data_t pHwData);
void hal_set_aid( phw_data_t pHwData, u16 aid );
-void hal_set_bssid( phw_data_t pHwData, PUCHAR pbssid );
-void hal_get_bssid( phw_data_t pHwData, PUCHAR pbssid );
+void hal_set_bssid( phw_data_t pHwData, u8 *pbssid );
+void hal_get_bssid( phw_data_t pHwData, u8 *pbssid );
void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period );
void hal_set_listen_interval( phw_data_t pHwData, u16 listen_interval );
void hal_set_cap_info( phw_data_t pHwData, u16 capability_info );
-void hal_set_ssid( phw_data_t pHwData, PUCHAR pssid, u8 ssid_len );
+void hal_set_ssid( phw_data_t pHwData, u8 *pssid, u8 ssid_len );
void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel );
void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel );
void hal_get_current_channel( phw_data_t pHwData, ChanInfo *channel );
void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable );
void hal_set_accept_multicast( phw_data_t pHwData, u8 enable );
void hal_set_accept_beacon( phw_data_t pHwData, u8 enable );
-void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number );
+void hal_set_multicast_address( phw_data_t pHwData, u8 *address, u8 number );
u8 hal_get_accept_beacon( phw_data_t pHwData );
void hal_stop( phw_data_t pHwData );
void hal_halt( phw_data_t pHwData, void *ppa_data );
@@ -97,7 +97,7 @@ void hal_surprise_remove( phw_data_t pHwData );
void hal_rate_change( phw_data_t pHwData ); // Notify the HAL rate is changing 20060613.1
-unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, PULONG pValue );
+unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, u32 * pValue );
unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value );
#define hal_get_time_count( _P ) (_P->time_count/10) // return 100ms count
#define hal_detect_error( _P ) (_P->WbUsb.DetectCount)
@@ -116,7 +116,7 @@ unsigned char hal_idle( phw_data_t pHwData );
#define pa_stall_execution( _A ) //OS_SLEEP( 1 )
#define hw_get_cxx_reg( _A, _B, _C )
#define hw_set_cxx_reg( _A, _B, _C )
-#define hw_get_dxx_reg( _A, _B, _C ) hal_get_dxx_reg( _A, _B, (PULONG)_C )
+#define hw_get_dxx_reg( _A, _B, _C ) hal_get_dxx_reg( _A, _B, (u32 *)_C )
#define hw_set_dxx_reg( _A, _B, _C ) hal_set_dxx_reg( _A, _B, (u32)_C )
diff --git a/drivers/staging/winbond/wbhal_s.h b/drivers/staging/winbond/wbhal_s.h
index 5b862ff357b..2ee3f0fc1ad 100644
--- a/drivers/staging/winbond/wbhal_s.h
+++ b/drivers/staging/winbond/wbhal_s.h
@@ -461,7 +461,7 @@ typedef struct _HW_DATA_T
//=====================================================================
// Definition for 802.11
//=====================================================================
- PUCHAR bssid_pointer; // Used by hal_get_bssid for return value
+ u8 *bssid_pointer; // Used by hal_get_bssid for return value
u8 bssid[8];// Only 6 byte will be used. 8 byte is required for read buffer
u8 ssid[32];// maximum ssid length is 32 byte
@@ -486,7 +486,7 @@ typedef struct _HW_DATA_T
u32 CurrentRadioSw; // 20060320.2 0:On 1:Off
u32 CurrentRadioHw; // 20060825 0:On 1:Off
- PUCHAR power_save_point; // Used by hal_get_power_save_mode for return value
+ u8 *power_save_point; // Used by hal_get_power_save_mode for return value
u8 cwmin;
u8 desired_power_save;
u8 dtim;// Is running dtim
diff --git a/drivers/staging/winbond/wblinux.c b/drivers/staging/winbond/wblinux.c
index 2eade5a47b1..4ed45e48831 100644
--- a/drivers/staging/winbond/wblinux.c
+++ b/drivers/staging/winbond/wblinux.c
@@ -25,11 +25,11 @@ EncapAtomicInc(PADAPTER Adapter, void* pAtomic)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
u32 ltmp;
- PULONG pltmp = (PULONG)pAtomic;
- OS_SPIN_LOCK_ACQUIRED( &pWbLinux->AtomicSpinLock );
+ u32 * pltmp = (u32 *)pAtomic;
+ spin_lock_irq( &pWbLinux->AtomicSpinLock );
(*pltmp)++;
ltmp = (*pltmp);
- OS_SPIN_LOCK_RELEASED( &pWbLinux->AtomicSpinLock );
+ spin_unlock_irq( &pWbLinux->AtomicSpinLock );
return ltmp;
}
@@ -38,11 +38,11 @@ EncapAtomicDec(PADAPTER Adapter, void* pAtomic)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
u32 ltmp;
- PULONG pltmp = (PULONG)pAtomic;
- OS_SPIN_LOCK_ACQUIRED( &pWbLinux->AtomicSpinLock );
+ u32 * pltmp = (u32 *)pAtomic;
+ spin_lock_irq( &pWbLinux->AtomicSpinLock );
(*pltmp)--;
ltmp = (*pltmp);
- OS_SPIN_LOCK_RELEASED( &pWbLinux->AtomicSpinLock );
+ spin_unlock_irq( &pWbLinux->AtomicSpinLock );
return ltmp;
}
@@ -51,8 +51,8 @@ WBLINUX_Initial(PADAPTER Adapter)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
- OS_SPIN_LOCK_ALLOCATE( &pWbLinux->SpinLock );
- OS_SPIN_LOCK_ALLOCATE( &pWbLinux->AtomicSpinLock );
+ spin_lock_init( &pWbLinux->SpinLock );
+ spin_lock_init( &pWbLinux->AtomicSpinLock );
return TRUE;
}
@@ -79,7 +79,6 @@ void
WBLINUX_Destroy(PADAPTER Adapter)
{
WBLINUX_stop( Adapter );
- OS_SPIN_LOCK_FREE( &pWbNdis->SpinLock );
#ifdef _PE_USB_INI_DUMP_
WBDEBUG(("[w35und] unregister_netdev!\n"));
#endif
@@ -142,119 +141,118 @@ unsigned char
WbWLanInitialize(PADAPTER Adapter)
{
phw_data_t pHwData;
- PUCHAR pMacAddr, pMacAddr2;
+ u8 *pMacAddr;
+ u8 *pMacAddr2;
u32 InitStep = 0;
u8 EEPROM_region;
u8 HwRadioOff;
- do {
- //
- // Setting default value for Linux
- //
- Adapter->sLocalPara.region_INF = REGION_AUTO;
- Adapter->sLocalPara.TxRateMode = RATE_AUTO;
- psLOCAL->bMacOperationMode = MODE_802_11_BG; // B/G mode
- Adapter->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
- Adapter->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
- hal_set_phy_type( &Adapter->sHwData, RF_WB_242_1 );
- Adapter->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
- psLOCAL->bPreambleMode = AUTO_MODE;
- Adapter->sLocalPara.RadioOffStatus.boSwRadioOff = FALSE;
- pHwData = &Adapter->sHwData;
- hal_set_phy_type( pHwData, RF_DECIDE_BY_INF );
-
- //
- // Initial each module and variable
- //
- if (!WBLINUX_Initial(Adapter)) {
+ //
+ // Setting default value for Linux
+ //
+ Adapter->sLocalPara.region_INF = REGION_AUTO;
+ Adapter->sLocalPara.TxRateMode = RATE_AUTO;
+ psLOCAL->bMacOperationMode = MODE_802_11_BG; // B/G mode
+ Adapter->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
+ Adapter->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
+ hal_set_phy_type( &Adapter->sHwData, RF_WB_242_1 );
+ Adapter->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
+ psLOCAL->bPreambleMode = AUTO_MODE;
+ Adapter->sLocalPara.RadioOffStatus.boSwRadioOff = FALSE;
+ pHwData = &Adapter->sHwData;
+ hal_set_phy_type( pHwData, RF_DECIDE_BY_INF );
+
+ //
+ // Initial each module and variable
+ //
+ if (!WBLINUX_Initial(Adapter)) {
#ifdef _PE_USB_INI_DUMP_
- WBDEBUG(("[w35und]WBNDIS initialization failed\n"));
+ WBDEBUG(("[w35und]WBNDIS initialization failed\n"));
#endif
- break;
- }
+ goto error;
+ }
- // Initial Software variable
- Adapter->sLocalPara.ShutDowned = FALSE;
-
- //added by ws for wep key error detection
- Adapter->sLocalPara.bWepKeyError= FALSE;
- Adapter->sLocalPara.bToSelfPacketReceived = FALSE;
- Adapter->sLocalPara.WepKeyDetectTimerCount= 2 * 100; /// 2 seconds
-
- // Initial USB hal
- InitStep = 1;
- pHwData = &Adapter->sHwData;
- if (!hal_init_hardware(pHwData, Adapter))
- break;
-
- EEPROM_region = hal_get_region_from_EEPROM( pHwData );
- if (EEPROM_region != REGION_AUTO)
- psLOCAL->region = EEPROM_region;
- else {
- if (psLOCAL->region_INF != REGION_AUTO)
- psLOCAL->region = psLOCAL->region_INF;
- else
- psLOCAL->region = REGION_USA; //default setting
- }
+ // Initial Software variable
+ Adapter->sLocalPara.ShutDowned = FALSE;
+
+ //added by ws for wep key error detection
+ Adapter->sLocalPara.bWepKeyError= FALSE;
+ Adapter->sLocalPara.bToSelfPacketReceived = FALSE;
+ Adapter->sLocalPara.WepKeyDetectTimerCount= 2 * 100; /// 2 seconds
+
+ // Initial USB hal
+ InitStep = 1;
+ pHwData = &Adapter->sHwData;
+ if (!hal_init_hardware(pHwData, Adapter))
+ goto error;
+
+ EEPROM_region = hal_get_region_from_EEPROM( pHwData );
+ if (EEPROM_region != REGION_AUTO)
+ psLOCAL->region = EEPROM_region;
+ else {
+ if (psLOCAL->region_INF != REGION_AUTO)
+ psLOCAL->region = psLOCAL->region_INF;
+ else
+ psLOCAL->region = REGION_USA; //default setting
+ }
- // Get Software setting flag from hal
- Adapter->sLocalPara.boAntennaDiversity = FALSE;
- if (hal_software_set(pHwData) & 0x00000001)
- Adapter->sLocalPara.boAntennaDiversity = TRUE;
-
- //
- // For TS module
- //
- InitStep = 2;
-
- // For MDS module
- InitStep = 3;
- Mds_initial(Adapter);
-
- //=======================================
- // Initialize the SME, SCAN, MLME, ROAM
- //=======================================
- InitStep = 4;
- InitStep = 5;
- InitStep = 6;
-
- // If no user-defined address in the registry, use the addresss "burned" on the NIC instead.
- pMacAddr = Adapter->sLocalPara.ThisMacAddress;
- pMacAddr2 = Adapter->sLocalPara.PermanentAddress;
- hal_get_permanent_address( pHwData, Adapter->sLocalPara.PermanentAddress );// Reading ethernet address from EEPROM
- if (OS_MEMORY_COMPARE(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH )) // Is equal
- {
- memcpy( pMacAddr, pMacAddr2, MAC_ADDR_LENGTH );
- } else {
- // Set the user define MAC address
- hal_set_ethernet_address( pHwData, Adapter->sLocalPara.ThisMacAddress );
- }
+ // Get Software setting flag from hal
+ Adapter->sLocalPara.boAntennaDiversity = FALSE;
+ if (hal_software_set(pHwData) & 0x00000001)
+ Adapter->sLocalPara.boAntennaDiversity = TRUE;
+
+ //
+ // For TS module
+ //
+ InitStep = 2;
+
+ // For MDS module
+ InitStep = 3;
+ Mds_initial(Adapter);
+
+ //=======================================
+ // Initialize the SME, SCAN, MLME, ROAM
+ //=======================================
+ InitStep = 4;
+ InitStep = 5;
+ InitStep = 6;
+
+ // If no user-defined address in the registry, use the addresss "burned" on the NIC instead.
+ pMacAddr = Adapter->sLocalPara.ThisMacAddress;
+ pMacAddr2 = Adapter->sLocalPara.PermanentAddress;
+ hal_get_permanent_address( pHwData, Adapter->sLocalPara.PermanentAddress );// Reading ethernet address from EEPROM
+ if (OS_MEMORY_COMPARE(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH )) // Is equal
+ {
+ memcpy( pMacAddr, pMacAddr2, MAC_ADDR_LENGTH );
+ } else {
+ // Set the user define MAC address
+ hal_set_ethernet_address( pHwData, Adapter->sLocalPara.ThisMacAddress );
+ }
- //get current antenna
- psLOCAL->bAntennaNo = hal_get_antenna_number(pHwData);
+ //get current antenna
+ psLOCAL->bAntennaNo = hal_get_antenna_number(pHwData);
#ifdef _PE_STATE_DUMP_
- WBDEBUG(("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo));
+ WBDEBUG(("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo));
#endif
- hal_get_hw_radio_off( pHwData );
+ hal_get_hw_radio_off( pHwData );
- // Waiting for HAL setting OK
- while (!hal_idle(pHwData))
- OS_SLEEP(10000);
+ // Waiting for HAL setting OK
+ while (!hal_idle(pHwData))
+ OS_SLEEP(10000);
- MTO_Init(Adapter);
+ MTO_Init(Adapter);
- HwRadioOff = hal_get_hw_radio_off( pHwData );
- psLOCAL->RadioOffStatus.boHwRadioOff = !!HwRadioOff;
+ HwRadioOff = hal_get_hw_radio_off( pHwData );
+ psLOCAL->RadioOffStatus.boHwRadioOff = !!HwRadioOff;
- hal_set_radio_mode( pHwData, (unsigned char)(psLOCAL->RadioOffStatus.boSwRadioOff || psLOCAL->RadioOffStatus.boHwRadioOff) );
+ hal_set_radio_mode( pHwData, (unsigned char)(psLOCAL->RadioOffStatus.boSwRadioOff || psLOCAL->RadioOffStatus.boHwRadioOff) );
- hal_driver_init_OK(pHwData) = 1; // Notify hal that the driver is ready now.
- //set a tx power for reference.....
-// sme_set_tx_power_level(Adapter, 12); FIXME?
- return TRUE;
- }
- while(FALSE);
+ hal_driver_init_OK(pHwData) = 1; // Notify hal that the driver is ready now.
+ //set a tx power for reference.....
+// sme_set_tx_power_level(Adapter, 12); FIXME?
+ return TRUE;
+error:
switch (InitStep) {
case 5:
case 4:
diff --git a/drivers/staging/winbond/wblinux_s.h b/drivers/staging/winbond/wblinux_s.h
index 97e9167ab83..fd2bb43bf3c 100644
--- a/drivers/staging/winbond/wblinux_s.h
+++ b/drivers/staging/winbond/wblinux_s.h
@@ -24,8 +24,8 @@
typedef struct _WBLINUX
{
- OS_SPIN_LOCK AtomicSpinLock;
- OS_SPIN_LOCK SpinLock;
+ spinlock_t AtomicSpinLock;
+ spinlock_t SpinLock;
u32 shutdown;
OS_ATOMIC ThreadCount;
diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig
index 10b1f0f634d..2425d860dca 100644
--- a/drivers/staging/wlan-ng/Kconfig
+++ b/drivers/staging/wlan-ng/Kconfig
@@ -1,6 +1,6 @@
config PRISM2_USB
tristate "Prism2.5 USB driver"
- depends on USB
+ depends on WLAN_80211 && USB
default n
---help---
This is the wlan-ng prism 2.5 USB driver for a wide range of
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index a2054639d24..0dfb8ce9aae 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -824,7 +824,7 @@ PD Record codes
#define HFA384x_CMD_MACPORT_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value))
#define HFA384x_CMD_ISRECL(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_RECL)))
#define HFA384x_CMD_RECL_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value))
-#define HFA384x_CMD_QOS_GET(value) ((UINT16((((UINT16)(value))&((UINT16)0x3000)) >> 12))
+#define HFA384x_CMD_QOS_GET(value) ((UINT16)((((UINT16)(value))&((UINT16)0x3000)) >> 12))
#define HFA384x_CMD_QOS_SET(value) ((UINT16)((((UINT16)(value)) << 12) & 0x3000))
#define HFA384x_CMD_ISWRITE(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_WRITE)))
#define HFA384x_CMD_WRITE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value))
diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c
index 53fe2985971..11a50c7fbfc 100644
--- a/drivers/staging/wlan-ng/p80211wep.c
+++ b/drivers/staging/wlan-ng/p80211wep.c
@@ -64,7 +64,6 @@
/*================================================================*/
/* Project Includes */
-#include "version.h"
#include "p80211hdr.h"
#include "p80211types.h"
#include "p80211msg.h"
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index 268fd9bba1e..eac06f793d8 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -90,8 +90,6 @@
#include <linux/usb.h>
//#endif
-#include "wlan_compat.h"
-
/*================================================================*/
/* Project Includes */
diff --git a/drivers/staging/wlan-ng/wlan_compat.h b/drivers/staging/wlan-ng/wlan_compat.h
index 17026570708..59dfa8f84cb 100644
--- a/drivers/staging/wlan-ng/wlan_compat.h
+++ b/drivers/staging/wlan-ng/wlan_compat.h
@@ -245,11 +245,11 @@ typedef int64_t INT64;
# define preempt_count() (0UL)
#endif
-#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __FUNCTION__ , ##args);
+#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __func__ , ##args);
-#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __FUNCTION__ , ##args);
+#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __func__ , ##args);
-#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __FUNCTION__ , ##args);
+#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __func__ , ##args);
#define WLAN_LOG_INFO(args... ) printk(KERN_INFO args)
@@ -265,7 +265,7 @@ typedef int64_t INT64;
#define DBFENTER { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"---->\n"); } }
#define DBFEXIT { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"<----\n"); } }
- #define WLAN_LOG_DEBUG(l,x,args...) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s(%lu): " x , __FUNCTION__, (preempt_count() & PREEMPT_MASK), ##args );
+ #define WLAN_LOG_DEBUG(l,x,args...) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s(%lu): " x , __func__, (preempt_count() & PREEMPT_MASK), ##args );
#else
#define WLAN_ASSERT(c)
#define WLAN_HEX_DUMP( l, s, p, n)
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index 4d74ba36c3a..37caf4d6903 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -54,7 +54,6 @@ static int phone_open(struct inode *inode, struct file *file)
if (minor >= PHONE_NUM_DEVICES)
return -ENODEV;
- lock_kernel();
mutex_lock(&phone_lock);
p = phone_device[minor];
if (p)
@@ -81,7 +80,6 @@ static int phone_open(struct inode *inode, struct file *file)
fops_put(old_fops);
end:
mutex_unlock(&phone_lock);
- unlock_kernel();
return err;
}
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 5dccf057a7d..f9b4647255a 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -47,6 +47,9 @@ static struct uio_class {
struct class *class;
} *uio_class;
+/* Protect idr accesses */
+static DEFINE_MUTEX(minor_lock);
+
/*
* attributes
*/
@@ -239,7 +242,6 @@ static void uio_dev_del_attributes(struct uio_device *idev)
static int uio_get_minor(struct uio_device *idev)
{
- static DEFINE_MUTEX(minor_lock);
int retval = -ENOMEM;
int id;
@@ -261,7 +263,9 @@ exit:
static void uio_free_minor(struct uio_device *idev)
{
+ mutex_lock(&minor_lock);
idr_remove(&uio_idr, idev->minor);
+ mutex_unlock(&minor_lock);
}
/**
@@ -305,8 +309,9 @@ static int uio_open(struct inode *inode, struct file *filep)
struct uio_listener *listener;
int ret = 0;
- lock_kernel();
+ mutex_lock(&minor_lock);
idev = idr_find(&uio_idr, iminor(inode));
+ mutex_unlock(&minor_lock);
if (!idev) {
ret = -ENODEV;
goto out;
@@ -332,18 +337,15 @@ static int uio_open(struct inode *inode, struct file *filep)
if (ret)
goto err_infoopen;
}
- unlock_kernel();
return 0;
err_infoopen:
-
kfree(listener);
-err_alloc_listener:
+err_alloc_listener:
module_put(idev->owner);
out:
- unlock_kernel();
return ret;
}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index c23a9857ee6..289d81adfb9 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -36,7 +36,8 @@ config USB_ARCH_HAS_OHCI
default y if PXA3xx
default y if ARCH_EP93XX
default y if ARCH_AT91
- default y if ARCH_PNX4008
+ default y if ARCH_PNX4008 && I2C
+ default y if MFD_TC6393XB
# PPC:
default y if STB03xxx
default y if PPC_MPC52xx
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 76fce44c2f9..3e862401a63 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -722,6 +722,16 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de
flush_scheduled_work();
}
+static int speedtch_pre_reset(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int speedtch_post_reset(struct usb_interface *intf)
+{
+ return 0;
+}
+
/**********
** USB **
@@ -740,6 +750,8 @@ static struct usb_driver speedtch_usb_driver = {
.name = speedtch_driver_name,
.probe = speedtch_usb_probe,
.disconnect = usbatm_usb_disconnect,
+ .pre_reset = speedtch_pre_reset,
+ .post_reset = speedtch_post_reset,
.id_table = speedtch_usb_ids
};
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index fab23ee8702..20104443081 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -849,9 +849,10 @@ static void acm_write_buffers_free(struct acm *acm)
{
int i;
struct acm_wb *wb;
+ struct usb_device *usb_dev = interface_to_usbdev(acm->control);
for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
- usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
+ usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah);
}
}
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 7429f70b9d0..5a8ecc045e3 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -42,6 +42,8 @@ static struct usb_device_id wdm_ids[] = {
{ }
};
+MODULE_DEVICE_TABLE (usb, wdm_ids);
+
#define WDM_MINOR_BASE 176
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index e935be7eb46..3d7793d9303 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1610,7 +1610,8 @@ int usb_external_resume_device(struct usb_device *udev)
status = usb_resume_both(udev);
udev->last_busy = jiffies;
usb_pm_unlock(udev);
- do_unbind_rebind(udev, DO_REBIND);
+ if (status == 0)
+ do_unbind_rebind(udev, DO_REBIND);
/* Now that the device is awake, we can start trying to autosuspend
* it again. */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d73ce262c36..9b3f16bd12c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3504,7 +3504,7 @@ int usb_reset_device(struct usb_device *udev)
USB_INTERFACE_BOUND)
rebind = 1;
}
- if (rebind)
+ if (ret == 0 && rebind)
usb_rebind_intf(cintf);
}
}
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 1ca1c326392..e1191b9a316 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -168,7 +168,7 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
* usb_find_endpoint - find a copy of an endpoint descriptor
* @src: original vector of descriptors
* @copy: copy of @src
- * @ep: endpoint descriptor found in @src
+ * @match: endpoint descriptor found in @src
*
* This returns the copy of the @match descriptor made for @copy. Its
* intended use is to help remembering the endpoint descriptor to use
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index bcf375ca3d7..caa37c95802 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -650,7 +650,7 @@ pxa_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
struct pxa27x_request *req;
req = kzalloc(sizeof *req, gfp_flags);
- if (!req || !_ep)
+ if (!req)
return NULL;
INIT_LIST_HEAD(&req->queue);
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 48f51b12d2e..00ba06b4475 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1894,11 +1894,8 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
udc->regs_info = debugfs_create_file("registers", S_IRUGO,
s3c2410_udc_debugfs_root,
udc, &s3c2410_udc_debugfs_fops);
- if (IS_ERR(udc->regs_info)) {
- dev_warn(dev, "debugfs file creation failed %ld\n",
- PTR_ERR(udc->regs_info));
- udc->regs_info = NULL;
- }
+ if (!udc->regs_info)
+ dev_warn(dev, "debugfs file creation failed\n");
}
dev_dbg(dev, "probe ok\n");
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 72fb655e603..56f592dc0b3 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -138,7 +138,6 @@ config USB_OHCI_HCD
tristate "OHCI HCD support"
depends on USB && USB_ARCH_HAS_OHCI
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
- select I2C if ARCH_PNX4008
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing
USB 1.1 host controller hardware. It does more in hardware than Intel's
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d343afacb0b..15a803b206b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1111,8 +1111,8 @@ clean0:
#ifdef DEBUG
debugfs_remove(ehci_debug_root);
ehci_debug_root = NULL;
-#endif
err_debug:
+#endif
clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
return retval;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 8647dab0d7f..8aa3f4556a3 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1075,12 +1075,18 @@ MODULE_LICENSE ("GPL");
#define SM501_OHCI_DRIVER ohci_hcd_sm501_driver
#endif
+#ifdef CONFIG_MFD_TC6393XB
+#include "ohci-tmio.c"
+#define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver
+#endif
+
#if !defined(PCI_DRIVER) && \
!defined(PLATFORM_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(SA1111_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(SM501_OHCI_DRIVER) && \
+ !defined(TMIO_OHCI_DRIVER) && \
!defined(SSB_OHCI_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
@@ -1147,13 +1153,25 @@ static int __init ohci_hcd_mod_init(void)
goto error_sm501;
#endif
+#ifdef TMIO_OHCI_DRIVER
+ retval = platform_driver_register(&TMIO_OHCI_DRIVER);
+ if (retval < 0)
+ goto error_tmio;
+#endif
+
return retval;
/* Error path */
+#ifdef TMIO_OHCI_DRIVER
+ platform_driver_unregister(&TMIO_OHCI_DRIVER);
+ error_tmio:
+#endif
#ifdef SM501_OHCI_DRIVER
+ platform_driver_unregister(&SM501_OHCI_DRIVER);
error_sm501:
#endif
#ifdef SSB_OHCI_DRIVER
+ ssb_driver_unregister(&SSB_OHCI_DRIVER);
error_ssb:
#endif
#ifdef PCI_DRIVER
@@ -1189,6 +1207,9 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void)
{
+#ifdef TMIO_OHCI_DRIVER
+ platform_driver_unregister(&TMIO_OHCI_DRIVER);
+#endif
#ifdef SM501_OHCI_DRIVER
platform_driver_unregister(&SM501_OHCI_DRIVER);
#endif
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
new file mode 100644
index 00000000000..f9f134af0bd
--- /dev/null
+++ b/drivers/usb/host/ohci-tmio.c
@@ -0,0 +1,376 @@
+/*
+ * OHCI HCD(Host Controller Driver) for USB.
+ *
+ *(C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ *(C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ *(C) Copyright 2002 Hewlett-Packard Company
+ *
+ * Bus glue for Toshiba Mobile IO(TMIO) Controller's OHCI core
+ * (C) Copyright 2005 Chris Humbert <mahadri-usb@drigon.com>
+ * (C) Copyright 2007, 2008 Dmitry Baryshkov <dbaryshkov@gmail.com>
+ *
+ * This is known to work with the following variants:
+ * TC6393XB revision 3 (32kB SRAM)
+ *
+ * The TMIO's OHCI core DMAs through a small internal buffer that
+ * is directly addressable by the CPU.
+ *
+ * Written from sparse documentation from Toshiba and Sharp's driver
+ * for the 2.4 kernel,
+ * usb-ohci-tc6393.c(C) Copyright 2004 Lineo Solutions, 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/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/sched.h>*/
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/dma-mapping.h>
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * USB Host Controller Configuration Register
+ */
+#define CCR_REVID 0x08 /* b Revision ID */
+#define CCR_BASE 0x10 /* l USB Control Register Base Address Low */
+#define CCR_ILME 0x40 /* b Internal Local Memory Enable */
+#define CCR_PM 0x4c /* w Power Management */
+#define CCR_INTC 0x50 /* b INT Control */
+#define CCR_LMW1L 0x54 /* w Local Memory Window 1 LMADRS Low */
+#define CCR_LMW1H 0x56 /* w Local Memory Window 1 LMADRS High */
+#define CCR_LMW1BL 0x58 /* w Local Memory Window 1 Base Address Low */
+#define CCR_LMW1BH 0x5A /* w Local Memory Window 1 Base Address High */
+#define CCR_LMW2L 0x5C /* w Local Memory Window 2 LMADRS Low */
+#define CCR_LMW2H 0x5E /* w Local Memory Window 2 LMADRS High */
+#define CCR_LMW2BL 0x60 /* w Local Memory Window 2 Base Address Low */
+#define CCR_LMW2BH 0x62 /* w Local Memory Window 2 Base Address High */
+#define CCR_MISC 0xFC /* b MISC */
+
+#define CCR_PM_GKEN 0x0001
+#define CCR_PM_CKRNEN 0x0002
+#define CCR_PM_USBPW1 0x0004
+#define CCR_PM_USBPW2 0x0008
+#define CCR_PM_USBPW3 0x0008
+#define CCR_PM_PMEE 0x0100
+#define CCR_PM_PMES 0x8000
+
+/*-------------------------------------------------------------------------*/
+
+struct tmio_hcd {
+ void __iomem *ccr;
+ spinlock_t lock; /* protects RMW cycles */
+};
+
+#define hcd_to_tmio(hcd) ((struct tmio_hcd *)(hcd_to_ohci(hcd) + 1))
+
+/*-------------------------------------------------------------------------*/
+
+static void tmio_write_pm(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+ u16 pm;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tmio->lock, flags);
+
+ pm = CCR_PM_GKEN | CCR_PM_CKRNEN |
+ CCR_PM_PMEE | CCR_PM_PMES;
+
+ tmio_iowrite16(pm, tmio->ccr + CCR_PM);
+ spin_unlock_irqrestore(&tmio->lock, flags);
+}
+
+static void tmio_stop_hc(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+ u16 pm;
+
+ pm = CCR_PM_GKEN | CCR_PM_CKRNEN;
+ switch (ohci->num_ports) {
+ default:
+ dev_err(&dev->dev, "Unsupported amount of ports: %d\n", ohci->num_ports);
+ case 3:
+ pm |= CCR_PM_USBPW3;
+ case 2:
+ pm |= CCR_PM_USBPW2;
+ case 1:
+ pm |= CCR_PM_USBPW1;
+ }
+ tmio_iowrite8(0, tmio->ccr + CCR_INTC);
+ tmio_iowrite8(0, tmio->ccr + CCR_ILME);
+ tmio_iowrite16(0, tmio->ccr + CCR_BASE);
+ tmio_iowrite16(0, tmio->ccr + CCR_BASE + 2);
+ tmio_iowrite16(pm, tmio->ccr + CCR_PM);
+}
+
+static void tmio_start_hc(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+ unsigned long base = hcd->rsrc_start;
+
+ tmio_write_pm(dev);
+ tmio_iowrite16(base, tmio->ccr + CCR_BASE);
+ tmio_iowrite16(base >> 16, tmio->ccr + CCR_BASE + 2);
+ tmio_iowrite8(1, tmio->ccr + CCR_ILME);
+ tmio_iowrite8(2, tmio->ccr + CCR_INTC);
+
+ dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n",
+ tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq);
+}
+
+static int ohci_tmio_start(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int ret;
+
+ if ((ret = ohci_init(ohci)) < 0)
+ return ret;
+
+ if ((ret = ohci_run(ohci)) < 0) {
+ err("can't start %s", hcd->self.bus_name);
+ ohci_stop(hcd);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct hc_driver ohci_tmio_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "TMIO OHCI USB Host Controller",
+ .hcd_priv_size = sizeof(struct ohci_hcd) + sizeof (struct tmio_hcd),
+
+ /* generic hardware linkage */
+ .irq = ohci_irq,
+ .flags = HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM,
+
+ /* basic lifecycle operations */
+ .start = ohci_tmio_start,
+ .stop = ohci_stop,
+ .shutdown = ohci_shutdown,
+
+ /* managing i/o requests and associated device resources */
+ .urb_enqueue = ohci_urb_enqueue,
+ .urb_dequeue = ohci_urb_dequeue,
+ .endpoint_disable = ohci_endpoint_disable,
+
+ /* scheduling support */
+ .get_frame_number = ohci_get_frame,
+
+ /* root hub support */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver ohci_hcd_tmio_driver;
+
+static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ struct resource *config = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ int irq = platform_get_irq(dev, 0);
+ struct tmio_hcd *tmio;
+ struct ohci_hcd *ohci;
+ struct usb_hcd *hcd;
+ int ret;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ if (!cell)
+ return -EINVAL;
+
+ hcd = usb_create_hcd(&ohci_tmio_hc_driver, &dev->dev, dev->dev.bus_id);
+ if (!hcd) {
+ ret = -ENOMEM;
+ goto err_usb_create_hcd;
+ }
+
+ hcd->rsrc_start = regs->start;
+ hcd->rsrc_len = regs->end - regs->start + 1;
+
+ tmio = hcd_to_tmio(hcd);
+
+ spin_lock_init(&tmio->lock);
+
+ tmio->ccr = ioremap(config->start, config->end - config->start + 1);
+ if (!tmio->ccr) {
+ ret = -ENOMEM;
+ goto err_ioremap_ccr;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ ret = -ENOMEM;
+ goto err_ioremap_regs;
+ }
+
+ if (!dma_declare_coherent_memory(&dev->dev, sram->start,
+ sram->start,
+ sram->end - sram->start + 1,
+ DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) {
+ ret = -EBUSY;
+ goto err_dma_declare;
+ }
+
+ if (cell->enable) {
+ ret = cell->enable(dev);
+ if (ret)
+ goto err_enable;
+ }
+
+ tmio_start_hc(dev);
+ ohci = hcd_to_ohci(hcd);
+ ohci_hcd_init(ohci);
+
+ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+ if (ret)
+ goto err_add_hcd;
+
+ if (ret == 0)
+ return ret;
+
+ usb_remove_hcd(hcd);
+
+err_add_hcd:
+ tmio_stop_hc(dev);
+ if (cell->disable)
+ cell->disable(dev);
+err_enable:
+ dma_release_declared_memory(&dev->dev);
+err_dma_declare:
+ iounmap(hcd->regs);
+err_ioremap_regs:
+ iounmap(tmio->ccr);
+err_ioremap_ccr:
+ usb_put_hcd(hcd);
+err_usb_create_hcd:
+
+ return ret;
+}
+
+static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+ struct mfd_cell *cell = dev->dev.platform_data;
+
+ usb_remove_hcd(hcd);
+ tmio_stop_hc(dev);
+ if (cell->disable)
+ cell->disable(dev);
+ dma_release_declared_memory(&dev->dev);
+ iounmap(hcd->regs);
+ iounmap(tmio->ccr);
+ usb_put_hcd(hcd);
+
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+ unsigned long flags;
+ u8 misc;
+ int ret;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ spin_lock_irqsave(&tmio->lock, flags);
+
+ misc = tmio_ioread8(tmio->ccr + CCR_MISC);
+ misc |= 1 << 3; /* USSUSP */
+ tmio_iowrite8(misc, tmio->ccr + CCR_MISC);
+
+ spin_unlock_irqrestore(&tmio->lock, flags);
+
+ if (cell->suspend) {
+ ret = cell->suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ hcd->state = HC_STATE_SUSPENDED;
+
+ return 0;
+}
+
+static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+ unsigned long flags;
+ u8 misc;
+ int ret;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ if (cell->resume) {
+ ret = cell->resume(dev);
+ if (ret)
+ return ret;
+ }
+
+ tmio_start_hc(dev);
+
+ spin_lock_irqsave(&tmio->lock, flags);
+
+ misc = tmio_ioread8(tmio->ccr + CCR_MISC);
+ misc &= ~(1 << 3); /* USSUSP */
+ tmio_iowrite8(misc, tmio->ccr + CCR_MISC);
+
+ spin_unlock_irqrestore(&tmio->lock, flags);
+
+ ohci_finish_controller_resume(hcd);
+
+ return 0;
+}
+#else
+#define ohci_hcd_tmio_drv_suspend NULL
+#define ohci_hcd_tmio_drv_resume NULL
+#endif
+
+static struct platform_driver ohci_hcd_tmio_driver = {
+ .probe = ohci_hcd_tmio_drv_probe,
+ .remove = __devexit_p(ohci_hcd_tmio_drv_remove),
+ .shutdown = usb_hcd_platform_shutdown,
+ .suspend = ohci_hcd_tmio_drv_suspend,
+ .resume = ohci_hcd_tmio_drv_resume,
+ .driver = {
+ .name = "tmio-ohci",
+ .owner = THIS_MODULE,
+ },
+};
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index b358c4e1cf2..444c69c447b 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1561,8 +1561,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if (code != USBTEST_REQUEST)
return -EOPNOTSUPP;
- if (param->iterations <= 0 || param->length < 0
- || param->sglen < 0 || param->vary < 0)
+ if (param->iterations <= 0)
return -EINVAL;
if (mutex_lock_interruptible(&dev->lock))
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 3d87eabcd92..bd07eaa300b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -95,11 +95,20 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
#define HUAWEI_PRODUCT_E220 0x1003
#define HUAWEI_PRODUCT_E220BIS 0x1004
#define HUAWEI_PRODUCT_E1401 0x1401
+#define HUAWEI_PRODUCT_E1402 0x1402
#define HUAWEI_PRODUCT_E1403 0x1403
+#define HUAWEI_PRODUCT_E1404 0x1404
#define HUAWEI_PRODUCT_E1405 0x1405
#define HUAWEI_PRODUCT_E1406 0x1406
+#define HUAWEI_PRODUCT_E1407 0x1407
#define HUAWEI_PRODUCT_E1408 0x1408
#define HUAWEI_PRODUCT_E1409 0x1409
+#define HUAWEI_PRODUCT_E140A 0x140A
+#define HUAWEI_PRODUCT_E140B 0x140B
+#define HUAWEI_PRODUCT_E140C 0x140C
+#define HUAWEI_PRODUCT_E140D 0x140D
+#define HUAWEI_PRODUCT_E140E 0x140E
+#define HUAWEI_PRODUCT_E140F 0x140F
#define HUAWEI_PRODUCT_E1410 0x1410
#define HUAWEI_PRODUCT_E1411 0x1411
#define HUAWEI_PRODUCT_E1412 0x1412
@@ -110,6 +119,44 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
#define HUAWEI_PRODUCT_E1417 0x1417
#define HUAWEI_PRODUCT_E1418 0x1418
#define HUAWEI_PRODUCT_E1419 0x1419
+#define HUAWEI_PRODUCT_E141A 0x141A
+#define HUAWEI_PRODUCT_E141B 0x141B
+#define HUAWEI_PRODUCT_E141C 0x141C
+#define HUAWEI_PRODUCT_E141D 0x141D
+#define HUAWEI_PRODUCT_E141E 0x141E
+#define HUAWEI_PRODUCT_E141F 0x141F
+#define HUAWEI_PRODUCT_E1420 0x1420
+#define HUAWEI_PRODUCT_E1421 0x1421
+#define HUAWEI_PRODUCT_E1422 0x1422
+#define HUAWEI_PRODUCT_E1423 0x1423
+#define HUAWEI_PRODUCT_E1424 0x1424
+#define HUAWEI_PRODUCT_E1425 0x1425
+#define HUAWEI_PRODUCT_E1426 0x1426
+#define HUAWEI_PRODUCT_E1427 0x1427
+#define HUAWEI_PRODUCT_E1428 0x1428
+#define HUAWEI_PRODUCT_E1429 0x1429
+#define HUAWEI_PRODUCT_E142A 0x142A
+#define HUAWEI_PRODUCT_E142B 0x142B
+#define HUAWEI_PRODUCT_E142C 0x142C
+#define HUAWEI_PRODUCT_E142D 0x142D
+#define HUAWEI_PRODUCT_E142E 0x142E
+#define HUAWEI_PRODUCT_E142F 0x142F
+#define HUAWEI_PRODUCT_E1430 0x1430
+#define HUAWEI_PRODUCT_E1431 0x1431
+#define HUAWEI_PRODUCT_E1432 0x1432
+#define HUAWEI_PRODUCT_E1433 0x1433
+#define HUAWEI_PRODUCT_E1434 0x1434
+#define HUAWEI_PRODUCT_E1435 0x1435
+#define HUAWEI_PRODUCT_E1436 0x1436
+#define HUAWEI_PRODUCT_E1437 0x1437
+#define HUAWEI_PRODUCT_E1438 0x1438
+#define HUAWEI_PRODUCT_E1439 0x1439
+#define HUAWEI_PRODUCT_E143A 0x143A
+#define HUAWEI_PRODUCT_E143B 0x143B
+#define HUAWEI_PRODUCT_E143C 0x143C
+#define HUAWEI_PRODUCT_E143D 0x143D
+#define HUAWEI_PRODUCT_E143E 0x143E
+#define HUAWEI_PRODUCT_E143F 0x143F
#define NOVATELWIRELESS_VENDOR_ID 0x1410
@@ -207,6 +254,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
#define ZTE_PRODUCT_MF628 0x0015
+#define ZTE_PRODUCT_MF626 0x0031
#define ZTE_PRODUCT_CDMA_TECH 0xfffe
/* Ericsson products */
@@ -248,11 +296,20 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
@@ -263,6 +320,44 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
@@ -336,6 +431,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
+ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) },
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 4995bb595ae..2dd9bd4bff5 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -95,11 +95,10 @@ int usb_stor_huawei_e220_init(struct us_data *us)
{
int result;
- us->iobuf[0] = 0x1;
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
USB_REQ_SET_FEATURE,
USB_TYPE_STANDARD | USB_RECIP_DEVICE,
- 0x01, 0x0, us->iobuf, 0x1, 1000);
+ 0x01, 0x0, NULL, 0x0, 1000);
US_DEBUGP("usb_control_msg performing result is %d\n", result);
return (result ? 0 : -1);
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index cd155475cb6..a2b9ebbef38 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1628,97 +1628,332 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
/* Reported by fangxiaozhi <huananhu@huawei.com>
* This brings the HUAWEI data card devices into multi-port mode
*/
-UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
0),
-UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000,
+UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
@@ -1745,6 +1980,15 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
+ * JMicron responds to USN and several other SCSI ioctls with a
+ * residue that causes subsequent I/O requests to fail. */
+UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100,
+ "JMicron",
+ "USB to ATA/ATAPI Bridge",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* Reported by Robert Schedel <r.schedel@yahoo.de>
* Note: this is a 'super top' device like the above 14cd/6600 device */
UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
@@ -1818,6 +2062,15 @@ UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>
+ * Mio Moov 330
+ */
+UNUSUAL_DEV( 0x3340, 0xffff, 0x0000, 0x0000,
+ "Mitac",
+ "Mio DigiWalker USB Sync",
+ US_SC_DEVICE,US_PR_DEVICE,NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/* Reported by Andrey Rahmatullin <wrar@altlinux.org> */
UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100,
"iRiver",
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index c72a1356295..4a4dd9adc32 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -75,6 +75,15 @@ config LCD_PLATFORM
This driver provides a platform-device registered LCD power
control interface.
+config LCD_TOSA
+ tristate "Sharp SL-6000 LCD Driver"
+ depends on LCD_CLASS_DEVICE && SPI
+ depends on MACH_TOSA
+ default n
+ help
+ If you have an Sharp SL-6000 Zaurus say Y to enable a driver
+ for its LCD.
+
#
# Backlight
#
@@ -115,7 +124,7 @@ config BACKLIGHT_ATMEL_PWM
called atmel-pwm-bl.
config BACKLIGHT_CORGI
- tristate "Generic (aka Sharp Corgi) Backlight Driver"
+ tristate "Generic (aka Sharp Corgi) Backlight Driver (DEPRECATED)"
depends on BACKLIGHT_CLASS_DEVICE
default n
help
@@ -123,6 +132,9 @@ config BACKLIGHT_CORGI
known as the Corgi backlight driver. If you have a Sharp Zaurus
SL-C7xx, SL-Cxx00 or SL-6000x say y. Most users can say n.
+ Note: this driver is marked as deprecated, try enable SPI and
+ use the new corgi_lcd driver with integrated backlight control
+
config BACKLIGHT_LOCOMO
tristate "Sharp LOCOMO LCD/Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
@@ -171,6 +183,13 @@ config BACKLIGHT_PWM
If you have a LCD backlight adjustable by PWM, say Y to enable
this driver.
+config BACKLIGHT_DA903X
+ tristate "Backlight Driver for DA9030/DA9034 using WLED"
+ depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X
+ help
+ If you have a LCD backlight connected to the WLED output of DA9030
+ or DA9034 WLED output, say Y here to enable this driver.
+
config BACKLIGHT_MBP_NVIDIA
tristate "MacBook Pro Nvidia Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE && X86
@@ -179,3 +198,19 @@ config BACKLIGHT_MBP_NVIDIA
If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
to enable a driver for its backlight
+config BACKLIGHT_TOSA
+ tristate "Sharp SL-6000 Backlight Driver"
+ depends on BACKLIGHT_CLASS_DEVICE && I2C
+ depends on MACH_TOSA && LCD_TOSA
+ default n
+ help
+ If you have an Sharp SL-6000 Zaurus say Y to enable a driver
+ for its backlight
+
+config BACKLIGHT_SAHARA
+ tristate "Tabletkiosk Sahara Touch-iT Backlight Driver"
+ depends on BACKLIGHT_CLASS_DEVICE && X86
+ default n
+ help
+ If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
+ backlight driver.
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 3ec551eb472..103427de670 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_LCD_ILI9320) += ili9320.o
obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
+obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
@@ -17,5 +18,8 @@ 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_DA903X) += da903x.o
obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
+obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
+obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c
new file mode 100644
index 00000000000..242c3825016
--- /dev/null
+++ b/drivers/video/backlight/da903x.c
@@ -0,0 +1,201 @@
+/*
+ * Backlight driver for Dialog Semiconductor DA9030/DA9034
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Eric Miao <eric.miao@marvell.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/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/mfd/da903x.h>
+
+#define DA9030_WLED_CONTROL 0x25
+#define DA9030_WLED_CP_EN (1 << 6)
+#define DA9030_WLED_TRIM(x) ((x) & 0x7)
+
+#define DA9034_WLED_CONTROL1 0x3C
+#define DA9034_WLED_CONTROL2 0x3D
+
+#define DA9034_WLED_BOOST_EN (1 << 5)
+
+#define DA9030_MAX_BRIGHTNESS 7
+#define DA9034_MAX_BRIGHTNESS 0x7f
+
+struct da903x_backlight_data {
+ struct device *da903x_dev;
+ int id;
+ int current_brightness;
+};
+
+static int da903x_backlight_set(struct backlight_device *bl, int brightness)
+{
+ struct da903x_backlight_data *data = bl_get_data(bl);
+ struct device *dev = data->da903x_dev;
+ uint8_t val;
+ int ret = 0;
+
+ switch (data->id) {
+ case DA9034_ID_WLED:
+ ret = da903x_update(dev, DA9034_WLED_CONTROL1,
+ brightness, 0x7f);
+ if (ret)
+ return ret;
+
+ if (data->current_brightness && brightness == 0)
+ ret = da903x_clr_bits(dev,
+ DA9034_WLED_CONTROL2,
+ DA9034_WLED_BOOST_EN);
+
+ if (data->current_brightness == 0 && brightness)
+ ret = da903x_set_bits(dev,
+ DA9034_WLED_CONTROL2,
+ DA9034_WLED_BOOST_EN);
+ break;
+ case DA9030_ID_WLED:
+ val = DA9030_WLED_TRIM(brightness);
+ val |= brightness ? DA9030_WLED_CP_EN : 0;
+ ret = da903x_write(dev, DA9030_WLED_CONTROL, val);
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ data->current_brightness = brightness;
+ return 0;
+}
+
+static int da903x_backlight_update_status(struct backlight_device *bl)
+{
+ int brightness = bl->props.brightness;
+
+ if (bl->props.power != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ return da903x_backlight_set(bl, brightness);
+}
+
+static int da903x_backlight_get_brightness(struct backlight_device *bl)
+{
+ struct da903x_backlight_data *data = bl_get_data(bl);
+ return data->current_brightness;
+}
+
+static struct backlight_ops da903x_backlight_ops = {
+ .update_status = da903x_backlight_update_status,
+ .get_brightness = da903x_backlight_get_brightness,
+};
+
+static int da903x_backlight_probe(struct platform_device *pdev)
+{
+ struct da903x_backlight_data *data;
+ struct backlight_device *bl;
+ int max_brightness;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ switch (pdev->id) {
+ case DA9030_ID_WLED:
+ max_brightness = DA9030_MAX_BRIGHTNESS;
+ break;
+ case DA9034_ID_WLED:
+ max_brightness = DA9034_MAX_BRIGHTNESS;
+ break;
+ default:
+ dev_err(&pdev->dev, "invalid backlight device ID(%d)\n",
+ pdev->id);
+ return -EINVAL;
+ }
+
+ data->id = pdev->id;
+ data->da903x_dev = pdev->dev.parent;
+ data->current_brightness = 0;
+
+ bl = backlight_device_register(pdev->name, data->da903x_dev,
+ data, &da903x_backlight_ops);
+ if (IS_ERR(bl)) {
+ dev_err(&pdev->dev, "failed to register backlight\n");
+ return PTR_ERR(bl);
+ }
+
+ bl->props.max_brightness = max_brightness;
+ bl->props.brightness = max_brightness;
+
+ platform_set_drvdata(pdev, bl);
+ backlight_update_status(bl);
+ return 0;
+}
+
+static int da903x_backlight_remove(struct platform_device *pdev)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct da903x_backlight_data *data = bl_get_data(bl);
+
+ backlight_device_unregister(bl);
+ kfree(data);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int da903x_backlight_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ return da903x_backlight_set(bl, 0);
+}
+
+static int da903x_backlight_resume(struct platform_device *pdev)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+
+ backlight_update_status(bl);
+ return 0;
+}
+#else
+#define da903x_backlight_suspend NULL
+#define da903x_backlight_resume NULL
+#endif
+
+static struct platform_driver da903x_backlight_driver = {
+ .driver = {
+ .name = "da903x-backlight",
+ .owner = THIS_MODULE,
+ },
+ .probe = da903x_backlight_probe,
+ .remove = da903x_backlight_remove,
+ .suspend = da903x_backlight_suspend,
+ .resume = da903x_backlight_resume,
+};
+
+static int __init da903x_backlight_init(void)
+{
+ return platform_driver_register(&da903x_backlight_driver);
+}
+module_init(da903x_backlight_init);
+
+static void __exit da903x_backlight_exit(void)
+{
+ platform_driver_unregister(&da903x_backlight_driver);
+}
+module_exit(da903x_backlight_exit);
+
+MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+ "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da903x-backlight");
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 6fa0b9d5559..d4cfed0b26d 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -19,7 +19,7 @@
#include <linux/backlight.h>
#include <cpu/dac.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
#include <asm/hd64461.h>
#define HP680_MAX_INTENSITY 255
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
new file mode 100644
index 00000000000..a38fda1742d
--- /dev/null
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -0,0 +1,204 @@
+/*
+ * Backlight Driver for the KB3886 Backlight
+ *
+ * Copyright (c) 2007-2008 Claudio Nieder
+ *
+ * Based on corgi_bl.c by Richard Purdie and kb3886 driver by Robert Woerle
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
+
+#define KB3886_PARENT 0x64
+#define KB3886_IO 0x60
+#define KB3886_ADC_DAC_PWM 0xC4
+#define KB3886_PWM0_WRITE 0x81
+#define KB3886_PWM0_READ 0x41
+
+static DEFINE_MUTEX(bl_mutex);
+
+static void kb3886_bl_set_intensity(int intensity)
+{
+ mutex_lock(&bl_mutex);
+ intensity = intensity&0xff;
+ outb(KB3886_ADC_DAC_PWM, KB3886_PARENT);
+ msleep(10);
+ outb(KB3886_PWM0_WRITE, KB3886_IO);
+ msleep(10);
+ outb(intensity, KB3886_IO);
+ mutex_unlock(&bl_mutex);
+}
+
+struct kb3886bl_machinfo {
+ int max_intensity;
+ int default_intensity;
+ int limit_mask;
+ void (*set_bl_intensity)(int intensity);
+};
+
+static struct kb3886bl_machinfo kb3886_bl_machinfo = {
+ .max_intensity = 0xff,
+ .default_intensity = 0xa0,
+ .limit_mask = 0x7f,
+ .set_bl_intensity = kb3886_bl_set_intensity,
+};
+
+static struct platform_device kb3886bl_device = {
+ .name = "kb3886-bl",
+ .dev = {
+ .platform_data = &kb3886_bl_machinfo,
+ },
+ .id = -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &kb3886bl_device,
+};
+
+/*
+ * Back to driver
+ */
+
+static int kb3886bl_intensity;
+static struct backlight_device *kb3886_backlight_device;
+static struct kb3886bl_machinfo *bl_machinfo;
+
+static unsigned long kb3886bl_flags;
+#define KB3886BL_SUSPENDED 0x01
+
+static struct dmi_system_id __initdata kb3886bl_device_table[] = {
+ {
+ .ident = "Sahara Touch-iT",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SDV"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iTouch T201"),
+ },
+ },
+ { }
+};
+
+static int kb3886bl_send_intensity(struct backlight_device *bd)
+{
+ int intensity = bd->props.brightness;
+
+ if (bd->props.power != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (kb3886bl_flags & KB3886BL_SUSPENDED)
+ intensity = 0;
+
+ bl_machinfo->set_bl_intensity(intensity);
+
+ kb3886bl_intensity = intensity;
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct backlight_device *bd = platform_get_drvdata(pdev);
+
+ kb3886bl_flags |= KB3886BL_SUSPENDED;
+ backlight_update_status(bd);
+ return 0;
+}
+
+static int kb3886bl_resume(struct platform_device *pdev)
+{
+ struct backlight_device *bd = platform_get_drvdata(pdev);
+
+ kb3886bl_flags &= ~KB3886BL_SUSPENDED;
+ backlight_update_status(bd);
+ return 0;
+}
+#else
+#define kb3886bl_suspend NULL
+#define kb3886bl_resume NULL
+#endif
+
+static int kb3886bl_get_intensity(struct backlight_device *bd)
+{
+ return kb3886bl_intensity;
+}
+
+static struct backlight_ops kb3886bl_ops = {
+ .get_brightness = kb3886bl_get_intensity,
+ .update_status = kb3886bl_send_intensity,
+};
+
+static int kb3886bl_probe(struct platform_device *pdev)
+{
+ struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data;
+
+ bl_machinfo = machinfo;
+ if (!machinfo->limit_mask)
+ machinfo->limit_mask = -1;
+
+ kb3886_backlight_device = backlight_device_register("kb3886-bl",
+ &pdev->dev, NULL, &kb3886bl_ops);
+ if (IS_ERR(kb3886_backlight_device))
+ return PTR_ERR(kb3886_backlight_device);
+
+ platform_set_drvdata(pdev, kb3886_backlight_device);
+
+ kb3886_backlight_device->props.max_brightness = machinfo->max_intensity;
+ kb3886_backlight_device->props.power = FB_BLANK_UNBLANK;
+ kb3886_backlight_device->props.brightness = machinfo->default_intensity;
+ backlight_update_status(kb3886_backlight_device);
+
+ return 0;
+}
+
+static int kb3886bl_remove(struct platform_device *pdev)
+{
+ struct backlight_device *bd = platform_get_drvdata(pdev);
+
+ backlight_device_unregister(bd);
+
+ return 0;
+}
+
+static struct platform_driver kb3886bl_driver = {
+ .probe = kb3886bl_probe,
+ .remove = kb3886bl_remove,
+ .suspend = kb3886bl_suspend,
+ .resume = kb3886bl_resume,
+ .driver = {
+ .name = "kb3886-bl",
+ },
+};
+
+static int __init kb3886_init(void)
+{
+ if (!dmi_check_system(kb3886bl_device_table))
+ return -ENODEV;
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+ return platform_driver_register(&kb3886bl_driver);
+}
+
+static void __exit kb3886_exit(void)
+{
+ platform_driver_unregister(&kb3886bl_driver);
+}
+
+module_init(kb3886_init);
+module_exit(kb3886_exit);
+
+MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>");
+MODULE_DESCRIPTION("Tabletkiosk Sahara Touch-iT Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("dmi:*:svnSDV:pniTouchT201:*");
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
new file mode 100644
index 00000000000..43edbada12d
--- /dev/null
+++ b/drivers/video/backlight/tosa_bl.c
@@ -0,0 +1,198 @@
+/*
+ * LCD / Backlight control code for Sharp SL-6000x (tosa)
+ *
+ * Copyright (c) 2005 Dirk Opfer
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+
+#include <asm/mach/sharpsl_param.h>
+
+#include <mach/tosa.h>
+
+#define COMADJ_DEFAULT 97
+
+#define DAC_CH1 0
+#define DAC_CH2 1
+
+struct tosa_bl_data {
+ struct i2c_client *i2c;
+ struct backlight_device *bl;
+
+ int comadj;
+};
+
+static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness)
+{
+ struct spi_device *spi = data->i2c->dev.platform_data;
+
+ i2c_smbus_write_byte_data(data->i2c, DAC_CH1, data->comadj);
+
+ /* SetBacklightDuty */
+ i2c_smbus_write_byte_data(data->i2c, DAC_CH2, (u8)(brightness & 0xff));
+
+ /* SetBacklightVR */
+ gpio_set_value(TOSA_GPIO_BL_C20MA, brightness & 0x100);
+
+ tosa_bl_enable(spi, brightness);
+}
+
+static int tosa_bl_update_status(struct backlight_device *dev)
+{
+ struct backlight_properties *props = &dev->props;
+ struct tosa_bl_data *data = dev_get_drvdata(&dev->dev);
+ int power = max(props->power, props->fb_blank);
+ int brightness = props->brightness;
+
+ if (power)
+ brightness = 0;
+
+ tosa_bl_set_backlight(data, brightness);
+
+ return 0;
+}
+
+static int tosa_bl_get_brightness(struct backlight_device *dev)
+{
+ struct backlight_properties *props = &dev->props;
+
+ return props->brightness;
+}
+
+static struct backlight_ops bl_ops = {
+ .get_brightness = tosa_bl_get_brightness,
+ .update_status = tosa_bl_update_status,
+};
+
+static int __devinit tosa_bl_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tosa_bl_data *data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL);
+ int ret = 0;
+ if (!data)
+ return -ENOMEM;
+
+ data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
+
+ ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight");
+ if (ret) {
+ dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
+ goto err_gpio_bl;
+ }
+ ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
+ if (ret)
+ goto err_gpio_dir;
+
+ i2c_set_clientdata(client, data);
+ data->i2c = client;
+
+ data->bl = backlight_device_register("tosa-bl", &client->dev,
+ data, &bl_ops);
+ if (IS_ERR(data->bl)) {
+ ret = PTR_ERR(data->bl);
+ goto err_reg;
+ }
+
+ data->bl->props.brightness = 69;
+ data->bl->props.max_brightness = 512 - 1;
+ data->bl->props.power = FB_BLANK_UNBLANK;
+
+ backlight_update_status(data->bl);
+
+ return 0;
+
+err_reg:
+ data->bl = NULL;
+ i2c_set_clientdata(client, NULL);
+err_gpio_dir:
+ gpio_free(TOSA_GPIO_BL_C20MA);
+err_gpio_bl:
+ kfree(data);
+ return ret;
+}
+
+static int __devexit tosa_bl_remove(struct i2c_client *client)
+{
+ struct tosa_bl_data *data = i2c_get_clientdata(client);
+
+ backlight_device_unregister(data->bl);
+ data->bl = NULL;
+ i2c_set_clientdata(client, NULL);
+
+ gpio_free(TOSA_GPIO_BL_C20MA);
+
+ kfree(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int tosa_bl_suspend(struct i2c_client *client, pm_message_t pm)
+{
+ struct tosa_bl_data *data = i2c_get_clientdata(client);
+
+ tosa_bl_set_backlight(data, 0);
+
+ return 0;
+}
+
+static int tosa_bl_resume(struct i2c_client *client)
+{
+ struct tosa_bl_data *data = i2c_get_clientdata(client);
+
+ backlight_update_status(data->bl);
+ return 0;
+}
+#else
+#define tosa_bl_suspend NULL
+#define tosa_bl_resume NULL
+#endif
+
+static const struct i2c_device_id tosa_bl_id[] = {
+ { "tosa-bl", 0 },
+ { },
+};
+
+
+static struct i2c_driver tosa_bl_driver = {
+ .driver = {
+ .name = "tosa-bl",
+ .owner = THIS_MODULE,
+ },
+ .probe = tosa_bl_probe,
+ .remove = __devexit_p(tosa_bl_remove),
+ .suspend = tosa_bl_suspend,
+ .resume = tosa_bl_resume,
+ .id_table = tosa_bl_id,
+};
+
+static int __init tosa_bl_init(void)
+{
+ return i2c_add_driver(&tosa_bl_driver);
+}
+
+static void __exit tosa_bl_exit(void)
+{
+ i2c_del_driver(&tosa_bl_driver);
+}
+
+module_init(tosa_bl_init);
+module_exit(tosa_bl_exit);
+
+MODULE_AUTHOR("Dmitry Baryshkov");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");
+
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
new file mode 100644
index 00000000000..57a26649f1a
--- /dev/null
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -0,0 +1,280 @@
+/*
+ * LCD / Backlight control code for Sharp SL-6000x (tosa)
+ *
+ * Copyright (c) 2005 Dirk Opfer
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/lcd.h>
+#include <linux/fb.h>
+
+#include <asm/mach/sharpsl_param.h>
+
+#include <mach/tosa.h>
+
+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
+
+#define TG_REG0_VQV 0x0001
+#define TG_REG0_COLOR 0x0002
+#define TG_REG0_UD 0x0004
+#define TG_REG0_LR 0x0008
+
+#define DAC_BASE 0x4e
+
+struct tosa_lcd_data {
+ struct spi_device *spi;
+ struct lcd_device *lcd;
+ struct i2c_client *i2c;
+
+ int lcd_power;
+};
+
+static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data)
+{
+ u8 buf[1];
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 1,
+ .cs_change = 1,
+ .tx_buf = buf,
+ };
+
+ buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(spi, &msg);
+}
+
+int tosa_bl_enable(struct spi_device *spi, int enable)
+{
+ /* bl_enable GP04=1 otherwise GP04=0*/
+ return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00);
+}
+EXPORT_SYMBOL(tosa_bl_enable);
+
+static void tosa_lcd_tg_init(struct tosa_lcd_data *data)
+{
+ /* TG on */
+ gpio_set_value(TOSA_GPIO_TG_ON, 0);
+
+ mdelay(60);
+
+ /* delayed 0clk TCTL signal for VGA */
+ tosa_tg_send(data->spi, TG_TPOSCTL, 0x00);
+ /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
+ tosa_tg_send(data->spi, TG_GPOSR, 0x02);
+}
+
+static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
+{
+ struct spi_device *spi = data->spi;
+ const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
+ tosa_tg_send(spi, TG_PNLCTL, value | TG_REG0_VQV); /* this depends on mode */
+
+ /* TG LCD pannel power up */
+ tosa_tg_send(spi, TG_PINICTL,0x4);
+ mdelay(50);
+
+ /* TG LCD GVSS */
+ tosa_tg_send(spi, TG_PINICTL,0x0);
+
+ if (!data->i2c) {
+ /* after the pannel is powered up the first time, we can access the i2c bus */
+ /* so probe for the DAC */
+ struct i2c_adapter *adap = i2c_get_adapter(0);
+ struct i2c_board_info info = {
+ .type = "tosa-bl",
+ .addr = DAC_BASE,
+ .platform_data = data->spi,
+ };
+ data->i2c = i2c_new_device(adap, &info);
+ }
+}
+
+static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
+{
+ struct spi_device *spi = data->spi;
+
+ /* TG LCD VHSA off */
+ tosa_tg_send(spi, TG_PINICTL,0x4);
+ mdelay(50);
+
+ /* TG LCD signal off */
+ tosa_tg_send(spi, TG_PINICTL,0x6);
+ mdelay(50);
+
+ /* TG Off */
+ gpio_set_value(TOSA_GPIO_TG_ON, 1);
+ mdelay(100);
+}
+
+int tosa_lcd_set_power(struct lcd_device *lcd, int power)
+{
+ struct tosa_lcd_data *data = lcd_get_data(lcd);
+
+ if (POWER_IS_ON(power) && !POWER_IS_ON(data->lcd_power))
+ tosa_lcd_tg_on(data);
+
+ if (!POWER_IS_ON(power) && POWER_IS_ON(data->lcd_power))
+ tosa_lcd_tg_off(data);
+
+ data->lcd_power = power;
+ return 0;
+}
+
+static int tosa_lcd_get_power(struct lcd_device *lcd)
+{
+ struct tosa_lcd_data *data = lcd_get_data(lcd);
+
+ return data->lcd_power;
+}
+
+static struct lcd_ops tosa_lcd_ops = {
+ .set_power = tosa_lcd_set_power,
+ .get_power = tosa_lcd_get_power,
+};
+
+static int __devinit tosa_lcd_probe(struct spi_device *spi)
+{
+ int ret;
+ struct tosa_lcd_data *data;
+
+ data = kzalloc(sizeof(struct tosa_lcd_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /*
+ * bits_per_word cannot be configured in platform data
+ */
+ spi->bits_per_word = 8;
+
+ ret = spi_setup(spi);
+ if (ret < 0)
+ goto err_spi;
+
+ data->spi = spi;
+ dev_set_drvdata(&spi->dev, data);
+
+ ret = gpio_request(TOSA_GPIO_TG_ON, "tg #pwr");
+ if (ret < 0)
+ goto err_gpio_tg;
+
+ mdelay(60);
+
+ ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0);
+ if (ret < 0)
+ goto err_gpio_dir;
+
+ mdelay(60);
+ tosa_lcd_tg_init(data);
+
+ tosa_lcd_tg_on(data);
+
+ data->lcd = lcd_device_register("tosa-lcd", &spi->dev, data,
+ &tosa_lcd_ops);
+
+ if (IS_ERR(data->lcd)) {
+ ret = PTR_ERR(data->lcd);
+ data->lcd = NULL;
+ goto err_register;
+ }
+
+ return 0;
+
+err_register:
+ tosa_lcd_tg_off(data);
+err_gpio_dir:
+ gpio_free(TOSA_GPIO_TG_ON);
+err_gpio_tg:
+ dev_set_drvdata(&spi->dev, NULL);
+err_spi:
+ kfree(data);
+ return ret;
+}
+
+static int __devexit tosa_lcd_remove(struct spi_device *spi)
+{
+ struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
+
+ lcd_device_unregister(data->lcd);
+
+ if (data->i2c)
+ i2c_unregister_device(data->i2c);
+
+ tosa_lcd_tg_off(data);
+
+ gpio_free(TOSA_GPIO_TG_ON);
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state)
+{
+ struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
+
+ tosa_lcd_tg_off(data);
+
+ return 0;
+}
+
+static int tosa_lcd_resume(struct spi_device *spi)
+{
+ struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
+
+ tosa_lcd_tg_init(data);
+ if (POWER_IS_ON(data->lcd_power))
+ tosa_lcd_tg_on(data);
+ else
+ tosa_lcd_tg_off(data);
+
+ return 0;
+}
+#else
+#define tosa_lcd_suspend NULL
+#define tosa_lcd_reume NULL
+#endif
+
+static struct spi_driver tosa_lcd_driver = {
+ .driver = {
+ .name = "tosa-lcd",
+ .owner = THIS_MODULE,
+ },
+ .probe = tosa_lcd_probe,
+ .remove = __devexit_p(tosa_lcd_remove),
+ .suspend = tosa_lcd_suspend,
+ .resume = tosa_lcd_resume,
+};
+
+static int __init tosa_lcd_init(void)
+{
+ return spi_register_driver(&tosa_lcd_driver);
+}
+
+static void __exit tosa_lcd_exit(void)
+{
+ spi_unregister_driver(&tosa_lcd_driver);
+}
+
+module_init(tosa_lcd_init);
+module_exit(tosa_lcd_exit);
+
+MODULE_AUTHOR("Dmitry Baryshkov");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");
+
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 217c5118ae9..cd5f20da738 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1002,101 +1002,132 @@ fb_blank(struct fb_info *info, int blank)
return ret;
}
-static int
-fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+static long
+fb_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
- struct fb_info *info = registered_fb[fbidx];
- struct fb_ops *fb = info->fbops;
+ struct fb_info *info;
+ struct fb_ops *fb;
struct fb_var_screeninfo var;
struct fb_fix_screeninfo fix;
struct fb_con2fbmap con2fb;
struct fb_cmap_user cmap;
struct fb_event event;
void __user *argp = (void __user *)arg;
- int i;
-
- if (!fb)
+ long ret = 0;
+
+ info = registered_fb[fbidx];
+ mutex_lock(&info->lock);
+ fb = info->fbops;
+
+ if (!fb) {
+ mutex_unlock(&info->lock);
return -ENODEV;
+ }
switch (cmd) {
case FBIOGET_VSCREENINFO:
- return copy_to_user(argp, &info->var,
+ ret = copy_to_user(argp, &info->var,
sizeof(var)) ? -EFAULT : 0;
+ break;
case FBIOPUT_VSCREENINFO:
- if (copy_from_user(&var, argp, sizeof(var)))
- return -EFAULT;
+ if (copy_from_user(&var, argp, sizeof(var))) {
+ ret = -EFAULT;
+ break;
+ }
acquire_console_sem();
info->flags |= FBINFO_MISC_USEREVENT;
- i = fb_set_var(info, &var);
+ ret = fb_set_var(info, &var);
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
- if (i) return i;
- if (copy_to_user(argp, &var, sizeof(var)))
- return -EFAULT;
- return 0;
+ if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+ ret = -EFAULT;
+ break;
case FBIOGET_FSCREENINFO:
- return copy_to_user(argp, &info->fix,
+ ret = copy_to_user(argp, &info->fix,
sizeof(fix)) ? -EFAULT : 0;
+ break;
case FBIOPUTCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
- return -EFAULT;
- return (fb_set_user_cmap(&cmap, info));
+ ret = -EFAULT;
+ else
+ ret = fb_set_user_cmap(&cmap, info);
+ break;
case FBIOGETCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
- return -EFAULT;
- return fb_cmap_to_user(&info->cmap, &cmap);
+ ret = -EFAULT;
+ else
+ ret = fb_cmap_to_user(&info->cmap, &cmap);
+ break;
case FBIOPAN_DISPLAY:
- if (copy_from_user(&var, argp, sizeof(var)))
- return -EFAULT;
+ if (copy_from_user(&var, argp, sizeof(var))) {
+ ret = -EFAULT;
+ break;
+ }
acquire_console_sem();
- i = fb_pan_display(info, &var);
+ ret = fb_pan_display(info, &var);
release_console_sem();
- if (i)
- return i;
- if (copy_to_user(argp, &var, sizeof(var)))
- return -EFAULT;
- return 0;
+ if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+ ret = -EFAULT;
+ break;
case FBIO_CURSOR:
- return -EINVAL;
+ ret = -EINVAL;
+ break;
case FBIOGET_CON2FBMAP:
if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
- return -EFAULT;
- if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
- return -EINVAL;
- con2fb.framebuffer = -1;
- event.info = info;
- event.data = &con2fb;
- fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
- return copy_to_user(argp, &con2fb,
+ ret = -EFAULT;
+ else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+ ret = -EINVAL;
+ else {
+ con2fb.framebuffer = -1;
+ event.info = info;
+ event.data = &con2fb;
+ fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
+ &event);
+ ret = copy_to_user(argp, &con2fb,
sizeof(con2fb)) ? -EFAULT : 0;
+ }
+ break;
case FBIOPUT_CON2FBMAP:
- if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
- return - EFAULT;
- if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
- return -EINVAL;
- if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
- return -EINVAL;
- if (!registered_fb[con2fb.framebuffer])
- request_module("fb%d", con2fb.framebuffer);
+ if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
+ ret = -EFAULT;
+ break;
+ }
+ if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
+ ret = -EINVAL;
+ break;
+ }
+ if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
+ ret = -EINVAL;
+ break;
+ }
if (!registered_fb[con2fb.framebuffer])
- return -EINVAL;
+ request_module("fb%d", con2fb.framebuffer);
+ if (!registered_fb[con2fb.framebuffer]) {
+ ret = -EINVAL;
+ break;
+ }
event.info = info;
event.data = &con2fb;
- return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
+ ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
&event);
+ break;
case FBIOBLANK:
acquire_console_sem();
info->flags |= FBINFO_MISC_USEREVENT;
- i = fb_blank(info, arg);
+ ret = fb_blank(info, arg);
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
- return i;
+ break;;
default:
if (fb->fb_ioctl == NULL)
- return -EINVAL;
- return fb->fb_ioctl(info, cmd, arg);
+ ret = -ENOTTY;
+ else
+ ret = fb->fb_ioctl(info, cmd, arg);
}
+ mutex_unlock(&info->lock);
+ return ret;
}
#ifdef CONFIG_COMPAT
@@ -1150,7 +1181,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file,
put_user(compat_ptr(data), &cmap->transp))
return -EFAULT;
- err = fb_ioctl(inode, file, cmd, (unsigned long) cmap);
+ err = fb_ioctl(file, cmd, (unsigned long) cmap);
if (!err) {
if (copy_in_user(&cmap32->start,
@@ -1204,7 +1235,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
old_fs = get_fs();
set_fs(KERNEL_DS);
- err = fb_ioctl(inode, file, cmd, (unsigned long) &fix);
+ err = fb_ioctl(file, cmd, (unsigned long) &fix);
set_fs(old_fs);
if (!err)
@@ -1222,7 +1253,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct fb_ops *fb = info->fbops;
long ret = -ENOIOCTLCMD;
- lock_kernel();
+ mutex_lock(&info->lock);
switch(cmd) {
case FBIOGET_VSCREENINFO:
case FBIOPUT_VSCREENINFO:
@@ -1231,7 +1262,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case FBIOPUT_CON2FBMAP:
arg = (unsigned long) compat_ptr(arg);
case FBIOBLANK:
- ret = fb_ioctl(inode, file, cmd, arg);
+ ret = fb_ioctl(file, cmd, arg);
break;
case FBIOGET_FSCREENINFO:
@@ -1248,7 +1279,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = fb->fb_compat_ioctl(info, cmd, arg);
break;
}
- unlock_kernel();
+ mutex_unlock(&info->lock);
return ret;
}
#endif
@@ -1270,13 +1301,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
return -ENODEV;
if (fb->fb_mmap) {
int res;
- lock_kernel();
+ mutex_lock(&info->lock);
res = fb->fb_mmap(info, vma);
- unlock_kernel();
+ mutex_unlock(&info->lock);
return res;
}
- lock_kernel();
+ mutex_lock(&info->lock);
/* frame buffer memory */
start = info->fix.smem_start;
@@ -1285,13 +1316,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
/* memory mapped io */
off -= len;
if (info->var.accel_flags) {
- unlock_kernel();
+ mutex_unlock(&info->lock);
return -EINVAL;
}
start = info->fix.mmio_start;
len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
}
- unlock_kernel();
+ mutex_unlock(&info->lock);
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL;
@@ -1315,13 +1346,13 @@ fb_open(struct inode *inode, struct file *file)
if (fbidx >= FB_MAX)
return -ENODEV;
- lock_kernel();
- if (!(info = registered_fb[fbidx]))
+ info = registered_fb[fbidx];
+ if (!info)
request_module("fb%d", fbidx);
- if (!(info = registered_fb[fbidx])) {
- res = -ENODEV;
- goto out;
- }
+ info = registered_fb[fbidx];
+ if (!info)
+ return -ENODEV;
+ mutex_lock(&info->lock);
if (!try_module_get(info->fbops->owner)) {
res = -ENODEV;
goto out;
@@ -1337,7 +1368,7 @@ fb_open(struct inode *inode, struct file *file)
fb_deferred_io_open(info, inode, file);
#endif
out:
- unlock_kernel();
+ mutex_unlock(&info->lock);
return res;
}
@@ -1346,11 +1377,11 @@ fb_release(struct inode *inode, struct file *file)
{
struct fb_info * const info = file->private_data;
- lock_kernel();
+ mutex_lock(&info->lock);
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
module_put(info->fbops->owner);
- unlock_kernel();
+ mutex_unlock(&info->lock);
return 0;
}
@@ -1358,7 +1389,7 @@ static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
- .ioctl = fb_ioctl,
+ .unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
@@ -1429,6 +1460,7 @@ register_framebuffer(struct fb_info *fb_info)
if (!registered_fb[i])
break;
fb_info->node = i;
+ mutex_init(&fb_info->lock);
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/drivers/video/imacfb.c
+++ /dev/null
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 4c32c06579a..efff672fd7b 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -16,7 +16,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <asm/sh_mobile_lcdc.h>
+#include <video/sh_mobile_lcdc.h>
#define PALETTE_NR 16
@@ -34,7 +34,9 @@ struct sh_mobile_lcdc_chan {
struct sh_mobile_lcdc_priv {
void __iomem *base;
+#ifdef CONFIG_HAVE_CLK
struct clk *clk;
+#endif
unsigned long lddckr;
struct sh_mobile_lcdc_chan ch[2];
};
@@ -260,6 +262,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
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;
+ tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
+ tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
+ tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
+ tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
+ tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
lcdc_write_chan(ch, LDMT1R, tmp);
/* setup SYS bus */
@@ -422,6 +429,7 @@ static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
priv->lddckr = icksel << 16;
+#ifdef CONFIG_HAVE_CLK
if (str) {
priv->clk = clk_get(dev, str);
if (IS_ERR(priv->clk)) {
@@ -431,6 +439,7 @@ static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
clk_enable(priv->clk);
}
+#endif
return 0;
}
@@ -585,7 +594,6 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
goto err1;
}
- priv->lddckr = pdata->lddckr;
priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
for (i = 0; i < j; i++) {
@@ -688,10 +696,12 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
fb_dealloc_cmap(&info->cmap);
}
+#ifdef CONFIG_HAVE_CLK
if (priv->clk) {
clk_disable(priv->clk);
clk_put(priv->clk);
}
+#endif
if (priv->base)
iounmap(priv->base);
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
index ed6b0576208..1f09d4e4144 100644
--- a/drivers/w1/slaves/w1_ds2760.c
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -80,7 +80,6 @@ static struct bin_attribute w1_ds2760_bin_attr = {
.attr = {
.name = "w1_slave",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = DS2760_DATA_SIZE,
.read = w1_ds2760_read_bin,
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 05a28106e8e..8782ec1f5aa 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -154,7 +154,7 @@ static int ibwdt_set_heartbeat(int t)
return -EINVAL;
for (i = 0x0F; i > -1; i--)
- if (wd_times[i] > t)
+ if (wd_times[i] >= t)
break;
wd_margin = i;
return 0;
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c
index c73b5e2919c..ada8ad82d99 100644
--- a/drivers/watchdog/w83697ug_wdt.c
+++ b/drivers/watchdog/w83697ug_wdt.c
@@ -102,7 +102,7 @@ static void w83697ug_select_wd_register(void)
} else {
printk(KERN_ERR PFX "No W83697UG/UF could be found\n");
- return -EIO;
+ return;
}
outb_p(0x07, WDT_EFER); /* point to logical device number reg */
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index 565280ec1c6..974f56d1ebe 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -2,7 +2,7 @@
#include <xen/xenbus.h>
-#include <asm-x86/xen/hypervisor.h>
+#include <asm/xen/hypervisor.h>
#include <asm/cpu.h>
static void enable_hotplug_cpu(int cpu)
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index c3290bc186a..9ce1ab6c268 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -125,7 +125,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
BUG_ON(irq == -1);
#ifdef CONFIG_SMP
- irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+ irq_to_desc(irq)->affinity = cpumask_of_cpu(cpu);
#endif
__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
@@ -137,10 +137,12 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
static void init_evtchn_cpu_bindings(void)
{
#ifdef CONFIG_SMP
+ struct irq_desc *desc;
int i;
+
/* By default all event channels notify CPU#0. */
- for (i = 0; i < NR_IRQS; i++)
- irq_desc[i].affinity = cpumask_of_cpu(0);
+ for_each_irq_desc(i, desc)
+ desc->affinity = cpumask_of_cpu(0);
#endif
memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
@@ -229,12 +231,12 @@ static int find_unbound_irq(void)
int irq;
/* Only allocate from dynirq range */
- for (irq = 0; irq < NR_IRQS; irq++)
+ for_each_irq_nr(irq)
if (irq_bindcount[irq] == 0)
break;
- if (irq == NR_IRQS)
- panic("No available IRQ to bind to: increase NR_IRQS!\n");
+ if (irq == nr_irqs)
+ panic("No available IRQ to bind to: increase nr_irqs!\n");
return irq;
}
@@ -790,7 +792,7 @@ void xen_irq_resume(void)
mask_evtchn(evtchn);
/* No IRQ <-> event-channel mappings. */
- for (irq = 0; irq < NR_IRQS; irq++)
+ for_each_irq_nr(irq)
irq_info[irq].evtchn = 0; /* zap event-channel binding */
for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
@@ -822,7 +824,7 @@ void __init xen_init_IRQ(void)
mask_evtchn(i);
/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
- for (i = 0; i < NR_IRQS; i++)
+ for_each_irq_nr(i)
irq_bindcount[i] = 0;
irq_ctx_init(smp_processor_id());