summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/osl.c8
-rw-r--r--drivers/acpi/pci_root.c11
-rw-r--r--drivers/acpi/pci_slot.c4
-rw-r--r--drivers/acpi/processor_idle.c28
-rw-r--r--drivers/acpi/scan.c12
-rw-r--r--drivers/acpi/sleep.c40
-rw-r--r--drivers/ata/ahci.c56
-rw-r--r--drivers/ata/libata-core.c20
-rw-r--r--drivers/ata/libata-eh.c56
-rw-r--r--drivers/ata/pata_amd.c3
-rw-r--r--drivers/ata/pata_cmd64x.c2
-rw-r--r--drivers/ata/pata_hpt37x.c32
-rw-r--r--drivers/ata/pata_hpt3x2n.c79
-rw-r--r--drivers/ata/pata_sc1200.c3
-rw-r--r--drivers/ata/pata_via.c2
-rw-r--r--drivers/ata/sata_nv.c18
-rw-r--r--drivers/ata/sata_via.c1
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c23
-rw-r--r--drivers/base/class.c2
-rw-r--r--drivers/base/core.c2
-rw-r--r--drivers/base/driver.c2
-rw-r--r--drivers/block/cciss.c3
-rw-r--r--drivers/char/Kconfig24
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/backend.c4
-rw-r--r--drivers/char/agp/intel-agp.c54
-rw-r--r--drivers/char/hvc_xen.c25
-rw-r--r--drivers/char/hw_random/fsl-rngc.c48
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/char/nozomi.c2
-rw-r--r--drivers/char/pty.c6
-rw-r--r--drivers/char/tpm/tpm.c8
-rw-r--r--drivers/char/tpm/tpm_tis.c12
-rw-r--r--drivers/char/tty_buffer.c29
-rw-r--r--drivers/char/tty_io.c3
-rw-r--r--drivers/char/tty_ldisc.c7
-rw-r--r--drivers/char/tty_port.c39
-rw-r--r--drivers/char/vt.c3
-rw-r--r--drivers/connector/cn_proc.c3
-rw-r--r--drivers/connector/cn_queue.c15
-rw-r--r--drivers/connector/connector.c197
-rw-r--r--drivers/cpuidle/cpuidle.c5
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/crypto/dcp.c102
-rw-r--r--drivers/crypto/padlock-aes.c4
-rw-r--r--drivers/dma/at_hdmac.c4
-rw-r--r--drivers/dma/pxp/pxp_device.c8
-rw-r--r--drivers/dma/pxp/pxp_dma.c211
-rw-r--r--drivers/edac/i5000_edac.c8
-rw-r--r--drivers/firewire/ohci.c12
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/drm_edid.c6
-rw-r--r--drivers/gpu/drm/drm_irq.c34
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h7
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c55
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c15
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c10
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h22
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c2
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c3
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c13
-rw-r--r--drivers/gpu/drm/i915/intel_display.c173
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c11
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c96
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c11
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c18
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h8
-rw-r--r--drivers/gpu/drm/r128/r128_state.c36
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c7
-rw-r--r--drivers/hid/hid-apple.c7
-rw-r--r--drivers/hid/hid-core.c4
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hwmon/adt7462.c4
-rw-r--r--drivers/hwmon/adt7475.c5
-rw-r--r--drivers/hwmon/coretemp.c2
-rw-r--r--drivers/hwmon/fschmd.c9
-rw-r--r--drivers/hwmon/it87.c5
-rw-r--r--drivers/hwmon/lm78.c25
-rw-r--r--drivers/hwmon/sht15.c6
-rw-r--r--drivers/hwmon/w83781d.c26
-rw-r--r--drivers/i2c/busses/i2c-amd756.c2
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c4
-rw-r--r--drivers/i2c/busses/i2c-i801.c4
-rw-r--r--drivers/i2c/busses/i2c-isch.c2
-rw-r--r--drivers/i2c/busses/i2c-mxs.c45
-rw-r--r--drivers/i2c/busses/i2c-mxs.h1
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c4
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c4
-rw-r--r--drivers/i2c/busses/i2c-piix4.c4
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c2
-rw-r--r--drivers/i2c/busses/i2c-tiny-usb.c12
-rw-r--r--drivers/i2c/busses/i2c-viapro.c2
-rw-r--r--drivers/i2c/chips/tsl2550.c3
-rw-r--r--drivers/i2c/i2c-core.c16
-rw-r--r--drivers/ide/cmd64x.c6
-rw-r--r--drivers/ide/ide-ioctls.c2
-rw-r--r--drivers/ide/ide-probe.c9
-rw-r--r--drivers/ide/sis5513.c10
-rw-r--r--drivers/ide/slc90e66.c3
-rw-r--r--drivers/input/evdev.c29
-rw-r--r--drivers/input/keyboard/Makefile2
-rw-r--r--drivers/input/keyboard/atkbd.c9
-rw-r--r--drivers/input/keyboard/mxc_keyb.c2
-rw-r--r--drivers/input/mouse/alps.c252
-rw-r--r--drivers/input/mouse/alps.h1
-rw-r--r--drivers/input/mouse/synaptics.c10
-rw-r--r--drivers/input/touchscreen/mxc_ts.c55
-rw-r--r--drivers/isdn/gigaset/interface.c19
-rw-r--r--drivers/isdn/hisax/hfc_usb.c4
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c342
-rw-r--r--drivers/leds/leds-mxs-pwm.c25
-rw-r--r--drivers/macintosh/therm_adt746x.c17
-rw-r--r--drivers/macintosh/therm_pm72.c4
-rw-r--r--drivers/macintosh/via-pmu.c40
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c4
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c4
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c4
-rw-r--r--drivers/md/bitmap.c24
-rw-r--r--drivers/md/bitmap.h2
-rw-r--r--drivers/md/dm-exception-store.c22
-rw-r--r--drivers/md/dm-exception-store.h8
-rw-r--r--drivers/md/dm-log-userspace-base.c4
-rw-r--r--drivers/md/dm-log-userspace-transfer.c6
-rw-r--r--drivers/md/dm-snap-persistent.c16
-rw-r--r--drivers/md/dm-snap.c25
-rw-r--r--drivers/md/dm.c11
-rw-r--r--drivers/md/md.c16
-rw-r--r--drivers/md/md.h1
-rw-r--r--drivers/md/raid1.c8
-rw-r--r--drivers/md/raid10.c1
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/media/common/tuners/mxl5007t.c2
-rw-r--r--drivers/media/common/tuners/tda18271-fe.c8
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c4
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c10
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h1
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c5
-rw-r--r--drivers/media/dvb/siano/smsusb.c6
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c2
-rw-r--r--drivers/media/video/Kconfig11
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c33
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c5
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c32
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c1
-rw-r--r--drivers/media/video/em28xx/em28xx.h4
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c20
-rw-r--r--drivers/media/video/gspca/ov519.c1
-rw-r--r--drivers/media/video/gspca/sonixj.c40
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.c2
-rw-r--r--drivers/media/video/mxc/capture/ov3640.c9
-rw-r--r--drivers/media/video/mxc/output/Makefile3
-rw-r--r--drivers/media/video/mxc/output/mxc_v4l2_output.c157
-rw-r--r--drivers/media/video/mxc/output/mxc_v4l2_output.h5
-rw-r--r--drivers/media/video/ov511.c2
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c2
-rw-r--r--drivers/media/video/s2255drv.c5
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c56
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c6
-rw-r--r--drivers/media/video/saa7134/saa7134.h5
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h2
-rw-r--r--drivers/media/video/uvc/uvc_driver.c3
-rw-r--r--drivers/media/video/uvc/uvc_video.c8
-rw-r--r--drivers/media/video/uvc/uvcvideo.h3
-rw-r--r--drivers/media/video/v4l1-compat.c14
-rw-r--r--drivers/media/video/videobuf-dma-contig.c2
-rw-r--r--drivers/message/fusion/mptbase.c10
-rw-r--r--drivers/mfd/ab3100-core.c2
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/enclosure.c1
-rw-r--r--drivers/misc/sgi-gru/gruprocfs.c13
-rw-r--r--drivers/mmc/core/mmc.c298
-rw-r--r--drivers/mmc/core/sd.c10
-rw-r--r--drivers/mmc/host/mx_sdhci.c130
-rw-r--r--drivers/mmc/host/mx_sdhci.h3
-rw-r--r--drivers/mmc/host/mxs-mmc.c24
-rw-r--r--drivers/mmc/host/pxamci.c4
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c11
-rw-r--r--drivers/mtd/chips/cfi_util.c4
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/gpmi-nfc/Makefile1
-rw-r--r--drivers/mtd/nand/gpmi-nfc/gpmi-nfc-main.c65
-rw-r--r--drivers/mtd/nand/gpmi-nfc/gpmi-nfc-mil.c41
-rw-r--r--drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h8
-rw-r--r--drivers/mtd/nand/mxc_nd2.c47
-rw-r--r--drivers/mtd/nand/ndfc.c4
-rw-r--r--drivers/mtd/ofpart.c21
-rw-r--r--drivers/mtd/ubi/cdev.c1
-rw-r--r--drivers/mxc/amd-gpu/Kconfig2
-rw-r--r--drivers/mxc/amd-gpu/Makefile20
-rw-r--r--drivers/mxc/amd-gpu/common/gsl_device.c50
-rw-r--r--drivers/mxc/amd-gpu/common/gsl_driver.c9
-rw-r--r--drivers/mxc/amd-gpu/common/gsl_g12.c6
-rw-r--r--drivers/mxc/amd-gpu/common/gsl_yamato.c1
-rw-r--r--drivers/mxc/amd-gpu/include/api/gsl_types.h1
-rw-r--r--drivers/mxc/amd-gpu/include/gsl_driver.h1
-rw-r--r--drivers/mxc/amd-gpu/include/gsl_hal.h10
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h62
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h195
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h63
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c524
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c31
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h41
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h62
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h222
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h58
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c598
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c31
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h40
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h27
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c103
-rw-r--r--drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h2
-rw-r--r--drivers/mxc/ipu3/ipu_capture.c118
-rw-r--r--drivers/mxc/ipu3/ipu_common.c40
-rw-r--r--drivers/mxc/ipu3/ipu_disp.c142
-rw-r--r--drivers/mxc/ipu3/ipu_regs.h1
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c23
-rw-r--r--drivers/net/acenic.c3
-rw-r--r--drivers/net/appletalk/ipddp.c3
-rw-r--r--drivers/net/au1000_eth.c15
-rw-r--r--drivers/net/b44.c6
-rw-r--r--drivers/net/bonding/bond_main.c10
-rw-r--r--drivers/net/can/flexcan/mbm.c2
-rw-r--r--drivers/net/can/vcan.c2
-rw-r--r--drivers/net/e100.c19
-rw-r--r--drivers/net/e1000e/82571.c4
-rw-r--r--drivers/net/fec.c45
-rw-r--r--drivers/net/fec_1588.c92
-rw-r--r--drivers/net/fec_1588.h45
-rw-r--r--drivers/net/fec_switch.c17
-rw-r--r--drivers/net/iseries_veth.c2
-rw-r--r--drivers/net/mlx4/eq.c42
-rw-r--r--drivers/net/mlx4/main.c9
-rw-r--r--drivers/net/mlx4/mlx4.h7
-rw-r--r--drivers/net/sfc/rx.c9
-rw-r--r--drivers/net/sfc/tx.c4
-rw-r--r--drivers/net/sky2.c6
-rw-r--r--drivers/net/smc91x.c2
-rw-r--r--drivers/net/smsc9420.c14
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/usb/hso.c4
-rw-r--r--drivers/net/usb/kaweth.c18
-rw-r--r--drivers/net/usb/rtl8150.c2
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/usb/usbnet.c2
-rw-r--r--drivers/net/wireless/airo.c34
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c57
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c33
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h8
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c26
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c155
-rw-r--r--drivers/net/wireless/b43/b43.h1
-rw-r--r--drivers/net/wireless/b43/dma.c36
-rw-r--r--drivers/net/wireless/b43/main.c13
-rw-r--r--drivers/net/wireless/b43/rfkill.c3
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c7
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c3
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c58
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c67
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h43
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c184
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c78
-rw-r--r--drivers/net/wireless/libertas/if_usb.c2
-rw-r--r--drivers/net/wireless/libertas/wext.c2
-rw-r--r--drivers/net/wireless/p54/p54usb.c11
-rw-r--r--drivers/net/wireless/ray_cs.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.c4
-rw-r--r--drivers/parisc/ccio-dma.c4
-rw-r--r--drivers/parisc/sba_iommu.c4
-rw-r--r--drivers/pci/dmar.c22
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c2
-rw-r--r--drivers/pci/quirks.c4
-rw-r--r--drivers/pcmcia/at91_cf.c2
-rw-r--r--drivers/pcmcia/au1000_generic.c2
-rw-r--r--drivers/pcmcia/bfin_cf_pcmcia.c2
-rw-r--r--drivers/pcmcia/cs.c69
-rw-r--r--drivers/pcmcia/i82092.c2
-rw-r--r--drivers/pcmcia/i82365.c2
-rw-r--r--drivers/pcmcia/m32r_cfc.c2
-rw-r--r--drivers/pcmcia/m32r_pcc.c2
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c2
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pcmcia/pd6729.c2
-rw-r--r--drivers/pcmcia/pxa2xx_base.c2
-rw-r--r--drivers/pcmcia/sa1100_generic.c2
-rw-r--r--drivers/pcmcia/sa1111_generic.c2
-rw-r--r--drivers/pcmcia/tcic.c2
-rw-r--r--drivers/pcmcia/vrc4171_card.c2
-rw-r--r--drivers/pcmcia/yenta_socket.c98
-rw-r--r--drivers/platform/x86/acerhdf.c118
-rw-r--r--drivers/platform/x86/asus-laptop.c4
-rw-r--r--drivers/platform/x86/sony-laptop.c6
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c46
-rw-r--r--drivers/pps/kapi.c20
-rw-r--r--drivers/pps/pps.c11
-rw-r--r--drivers/ps3/ps3stor_lib.c65
-rw-r--r--drivers/regulator/max17135-regulator.c163
-rw-r--r--drivers/rtc/Kconfig10
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-fm3130.c6
-rw-r--r--drivers/rtc/rtc-mxs.c2
-rw-r--r--drivers/rtc/rtc-v3020.c2
-rw-r--r--drivers/s390/block/dasd_diag.c19
-rw-r--r--drivers/scsi/dpt_i2o.c4
-rw-r--r--drivers/scsi/gdth.c2
-rw-r--r--drivers/scsi/hosts.c13
-rw-r--r--drivers/scsi/libsrp.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c10
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c23
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h43
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c61
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c16
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c224
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c29
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c3
-rw-r--r--drivers/scsi/scsi.c11
-rw-r--r--drivers/scsi/scsi_error.c3
-rw-r--r--drivers/scsi/scsi_lib_dma.c4
-rw-r--r--drivers/scsi/scsi_transport_fc.c17
-rw-r--r--drivers/scsi/sd.c2
-rw-r--r--drivers/scsi/sg.c12
-rw-r--r--drivers/serial/8250.c15
-rw-r--r--drivers/serial/8250_pci.c11
-rw-r--r--drivers/serial/8250_pnp.c10
-rw-r--r--drivers/serial/Kconfig18
-rw-r--r--drivers/serial/bfin_5xx.c4
-rw-r--r--drivers/serial/mxs-auart.c163
-rw-r--r--drivers/serial/of_serial.c1
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/serial/suncore.c37
-rw-r--r--drivers/serial/suncore.h5
-rw-r--r--drivers/serial/sunhv.c2
-rw-r--r--drivers/serial/sunsab.c9
-rw-r--r--drivers/serial/sunsu.c36
-rw-r--r--drivers/serial/sunzilog.c8
-rw-r--r--drivers/ssb/sprom.c20
-rw-r--r--drivers/staging/android/binder.c10
-rw-r--r--drivers/staging/android/logger.c7
-rw-r--r--drivers/staging/android/logger.h1
-rw-r--r--drivers/staging/android/lowmemorykiller.c40
-rw-r--r--drivers/staging/dst/dcore.c8
-rw-r--r--drivers/staging/pohmelfs/config.c6
-rw-r--r--drivers/staging/rt2860/common/cmm_data_2860.c2
-rw-r--r--drivers/uio/uio_pdrv_genirq.c6
-rw-r--r--drivers/usb/class/cdc-acm.c7
-rw-r--r--drivers/usb/class/cdc-wdm.c30
-rw-r--r--drivers/usb/class/usbtmc.c36
-rw-r--r--drivers/usb/core/config.c2
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/devio.c61
-rw-r--r--drivers/usb/core/driver.c3
-rw-r--r--drivers/usb/core/generic.c27
-rw-r--r--drivers/usb/core/hcd.c27
-rw-r--r--drivers/usb/core/hub.c19
-rw-r--r--drivers/usb/core/message.c8
-rw-r--r--drivers/usb/core/sysfs.c6
-rw-r--r--drivers/usb/core/usb.c31
-rw-r--r--drivers/usb/gadget/Kconfig9
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/amd5536udc.c49
-rw-r--r--drivers/usb/gadget/arcotg_udc.c451
-rw-r--r--drivers/usb/gadget/arcotg_udc.h11
-rw-r--r--drivers/usb/gadget/composite.c39
-rw-r--r--drivers/usb/gadget/f_acm.c9
-rw-r--r--drivers/usb/gadget/file_storage.c9
-rw-r--r--drivers/usb/host/ehci-arc.c280
-rw-r--r--drivers/usb/host/ehci-hcd.c7
-rw-r--r--drivers/usb/host/ehci-hub.c21
-rw-r--r--drivers/usb/host/ehci-pci.c6
-rw-r--r--drivers/usb/host/ehci-q.c27
-rw-r--r--drivers/usb/host/ehci-sched.c12
-rw-r--r--drivers/usb/host/ehci.h2
-rw-r--r--drivers/usb/host/ohci-hcd.c5
-rw-r--r--drivers/usb/host/ohci-pci.c20
-rw-r--r--drivers/usb/host/ohci-q.c18
-rw-r--r--drivers/usb/host/ohci.h9
-rw-r--r--drivers/usb/host/sl811-hcd.c8
-rw-r--r--drivers/usb/host/uhci-hcd.c15
-rw-r--r--drivers/usb/host/uhci-hub.c2
-rw-r--r--drivers/usb/host/xhci-dbg.c5
-rw-r--r--drivers/usb/host/xhci-hcd.c370
-rw-r--r--drivers/usb/host/xhci-mem.c74
-rw-r--r--drivers/usb/host/xhci-pci.c13
-rw-r--r--drivers/usb/host/xhci-ring.c239
-rw-r--r--drivers/usb/host/xhci.h41
-rw-r--r--drivers/usb/misc/appledisplay.c4
-rw-r--r--drivers/usb/misc/emi62.c2
-rw-r--r--drivers/usb/mon/mon_bin.c11
-rw-r--r--drivers/usb/musb/musb_gadget.c79
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c15
-rw-r--r--drivers/usb/otg/fsl_otg.c219
-rw-r--r--drivers/usb/serial/ark3116.c46
-rw-r--r--drivers/usb/serial/console.c28
-rw-r--r--drivers/usb/serial/cp210x.c28
-rw-r--r--drivers/usb/serial/cypress_m8.c12
-rw-r--r--drivers/usb/serial/digi_acceleport.c8
-rw-r--r--drivers/usb/serial/empeg.c12
-rw-r--r--drivers/usb/serial/ftdi_sio.c432
-rw-r--r--drivers/usb/serial/ftdi_sio.h10
-rw-r--r--drivers/usb/serial/generic.c4
-rw-r--r--drivers/usb/serial/ipaq.c9
-rw-r--r--drivers/usb/serial/iuu_phoenix.c31
-rw-r--r--drivers/usb/serial/kobil_sct.c22
-rw-r--r--drivers/usb/serial/option.c60
-rw-r--r--drivers/usb/serial/oti6858.c21
-rw-r--r--drivers/usb/serial/pl2303.c9
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/serial/sierra.c23
-rw-r--r--drivers/usb/serial/spcp8x5.c21
-rw-r--r--drivers/usb/serial/usb-serial.c391
-rw-r--r--drivers/usb/serial/whiteheat.c6
-rw-r--r--drivers/usb/storage/initializers.c2
-rw-r--r--drivers/usb/storage/onetouch.c2
-rw-r--r--drivers/usb/storage/transport.c59
-rw-r--r--drivers/usb/storage/unusual_devs.h14
-rw-r--r--drivers/usb/storage/usb.c21
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/console/Kconfig9
-rw-r--r--drivers/video/console/Makefile12
-rw-r--r--drivers/video/console/fbcon.c10
-rw-r--r--drivers/video/matrox/g450_pll.c3
-rw-r--r--drivers/video/modedb.c5
-rw-r--r--drivers/video/mxc/Kconfig4
-rw-r--r--drivers/video/mxc/Makefile1
-rw-r--r--drivers/video/mxc/mxc_elcdif_fb.c73
-rw-r--r--drivers/video/mxc/mxc_epdc_fb.c630
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c306
-rw-r--r--drivers/video/mxc/tve.c7
-rw-r--r--drivers/video/s3c-fb.c2
-rw-r--r--drivers/video/sis/vstruct.h2
-rw-r--r--drivers/video/uvesafb.c6
-rw-r--r--drivers/virtio/virtio_ring.c3
-rw-r--r--drivers/w1/w1_netlink.c3
-rw-r--r--drivers/watchdog/riowd.c2
-rw-r--r--drivers/xen/Makefile3
-rw-r--r--drivers/xen/balloon.c4
461 files changed, 8317 insertions, 6101 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 5dacbbd42483..48bbdbe43e69 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -90,8 +90,6 @@ source "drivers/memstick/Kconfig"
source "drivers/leds/Kconfig"
-source "drivers/switch/Kconfig"
-
source "drivers/accessibility/Kconfig"
source "drivers/infiniband/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index c19a0c18e5ed..4a9a1c55b598 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -95,7 +95,6 @@ obj-$(CONFIG_ARCH_MXC) += mxc/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-$(CONFIG_NEW_LEDS) += leds/
-obj-$(CONFIG_SWITCH) += switch/
obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 5691f165a952..8dff236f7ed3 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1182,7 +1182,13 @@ int acpi_check_resource_conflict(struct resource *res)
res_list_elem->name,
(long long) res_list_elem->start,
(long long) res_list_elem->end);
- printk(KERN_INFO "ACPI: Device needs an ACPI driver\n");
+ if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
+ printk(KERN_NOTICE "ACPI: This conflict may"
+ " cause random problems and system"
+ " instability\n");
+ printk(KERN_INFO "ACPI: If an ACPI driver is available"
+ " for this device, you should use it instead of"
+ " the native driver\n");
}
if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
return -EBUSY;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 55b5b90c2a44..97fad2979920 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -400,6 +400,17 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
pbus = pdev->subordinate;
pci_dev_put(pdev);
+
+ /*
+ * This function may be called for a non-PCI device that has a
+ * PCI parent (eg. a disk under a PCI SATA controller). In that
+ * case pdev->subordinate will be NULL for the parent.
+ */
+ if (!pbus) {
+ dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge\n");
+ pdev = NULL;
+ break;
+ }
}
out:
list_for_each_entry_safe(node, tmp, &device_list, node)
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index 12158e0d009b..da9d6d25cf6d 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -57,7 +57,7 @@ ACPI_MODULE_NAME("pci_slot");
MY_NAME , ## arg); \
} while (0)
-#define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */
+#define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */
struct acpi_pci_slot {
acpi_handle root_handle; /* handle of the root bridge */
@@ -149,7 +149,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
}
- snprintf(name, sizeof(name), "%u", (u32)sun);
+ snprintf(name, sizeof(name), "%llu", sun);
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));
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 66393d5c4c7c..f6d84694f17f 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -876,12 +876,14 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
return(acpi_idle_enter_c1(dev, state));
local_irq_disable();
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
+ if (cx->entry_method != ACPI_CSTATE_FFH) {
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+ }
if (unlikely(need_resched())) {
current_thread_info()->status |= TS_POLLING;
@@ -961,12 +963,14 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
}
local_irq_disable();
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
+ if (cx->entry_method != ACPI_CSTATE_FFH) {
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we test
+ * NEED_RESCHED:
+ */
+ smp_mb();
+ }
if (unlikely(need_resched())) {
current_thread_info()->status |= TS_POLLING;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 781435d7e369..5dd702c9c1fa 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1264,16 +1264,6 @@ 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
* ----------------
*/
@@ -1303,6 +1293,8 @@ 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);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 42159a28f433..1caac3b1a558 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -405,6 +405,46 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
},
},
{
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Hewlett-Packard Pavilion dv4",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Hewlett-Packard Pavilion dv7",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Hewlett-Packard Compaq Presario C700 Notebook PC",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario C700 Notebook PC"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Hewlett-Packard Compaq Presario CQ40 Notebook PC",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario CQ40 Notebook PC"),
+ },
+ },
+ {
.callback = init_old_suspend_ordering,
.ident = "Panasonic CF51-2L",
.matches = {
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index edc9b0ec9f39..38f4d0fc46a8 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -122,7 +122,8 @@ static const struct ata_port_info ahci_port_info[] = {
[board_ahci_sb600] =
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
- AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255),
+ AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+ AHCI_HFLAG_SECT255),
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
@@ -692,51 +693,6 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
}
}
-/*
- * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older
- * BIOS. The oldest version known to be broken is 0901 and working is
- * 1501 which was released on 2007-10-26. Force 32bit DMA on anything
- * older than 1501. Please read bko#9412 for more info.
- */
-static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev)
-{
- static const struct dmi_system_id sysids[] = {
- {
- .ident = "ASUS M2A-VM",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR,
- "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
- },
- },
- { }
- };
- const char *cutoff_mmdd = "10/26";
- const char *date;
- int year;
-
- if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
- !dmi_check_system(sysids))
- return false;
-
- /*
- * Argh.... both version and date are free form strings.
- * Let's hope they're using the same date format across
- * different versions.
- */
- date = dmi_get_system_info(DMI_BIOS_DATE);
- year = dmi_get_year(DMI_BIOS_DATE);
- if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' &&
- (year > 2007 ||
- (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0)))
- return false;
-
- dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, "
- "forcing 32bit DMA, update BIOS\n");
-
- return true;
-}
-
static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
{
static const struct dmi_system_id broken_systems[] = {
@@ -996,12 +952,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
- /* apply ASUS M2A_VM quirk */
- if (ahci_asus_m2a_vm_32bit_only(pdev))
- hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
-
- if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
- pci_enable_msi(pdev);
+ if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
+ pci_intx(pdev, 1);
hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 98af50f16e0c..299d32721a56 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -709,7 +709,13 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
head = tf->device & 0xf;
sect = tf->lbal;
- block = (cyl * dev->heads + head) * dev->sectors + sect;
+ if (!sect) {
+ ata_dev_printk(dev, KERN_WARNING, "device reported "
+ "invalid CHS sector 0\n");
+ sect = 1; /* oh well */
+ }
+
+ block = (cyl * dev->heads + head) * dev->sectors + sect - 1;
}
return block;
@@ -5024,12 +5030,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_FAILED;
if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
- if (!ata_tag_internal(qc->tag)) {
- /* always fill result TF for failed qc */
- fill_result_tf(qc);
+ /* always fill result TF for failed qc */
+ fill_result_tf(qc);
+
+ if (!ata_tag_internal(qc->tag))
ata_qc_schedule_eh(qc);
- return;
- }
+ else
+ __ata_qc_complete(qc);
+ return;
}
/* read result TF if requested */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 79711b64054b..1652b9190607 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2541,14 +2541,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))) {
- /* 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;
+ 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;
}
/* record current link speed */
@@ -2581,34 +2581,48 @@ int ata_eh_reset(struct ata_link *link, int classify,
slave->eh_info.serror = 0;
spin_unlock_irqrestore(link->ap->lock, flags);
- /* Make sure onlineness and classification result correspond.
+ /*
+ * Make sure onlineness and classification result correspond.
* Hotplug could have happened during reset and some
* controllers fail to wait while a drive is spinning up after
* being hotplugged causing misdetection. By cross checking
- * link onlineness and classification result, those conditions
- * can be reliably detected and retried.
+ * link on/offlineness and classification result, those
+ * conditions can be reliably detected and retried.
*/
nr_unknown = 0;
ata_for_each_dev(dev, link, ALL) {
- /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
- if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
- classes[dev->devno] = ATA_DEV_NONE;
- if (ata_phys_link_online(ata_dev_phys_link(dev)))
+ if (ata_phys_link_online(ata_dev_phys_link(dev))) {
+ if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
+ ata_dev_printk(dev, KERN_DEBUG, "link online "
+ "but device misclassifed\n");
+ classes[dev->devno] = ATA_DEV_NONE;
nr_unknown++;
+ }
+ } else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
+ if (ata_class_enabled(classes[dev->devno]))
+ ata_dev_printk(dev, KERN_DEBUG, "link offline, "
+ "clearing class %d to NONE\n",
+ classes[dev->devno]);
+ classes[dev->devno] = ATA_DEV_NONE;
+ } else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
+ ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
+ "clearing UNKNOWN to NONE\n");
+ classes[dev->devno] = ATA_DEV_NONE;
}
}
if (classify && nr_unknown) {
if (try < max_tries) {
ata_link_printk(link, KERN_WARNING, "link online but "
- "device misclassified, retrying\n");
+ "%d devices misclassified, retrying\n",
+ nr_unknown);
failed_link = link;
rc = -EAGAIN;
goto fail;
}
ata_link_printk(link, KERN_WARNING,
- "link online but device misclassified, "
- "device detection might fail\n");
+ "link online but %d devices misclassified, "
+ "device detection might fail\n", nr_unknown);
}
/* reset successful, schedule revalidation */
@@ -2835,12 +2849,14 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
* device detection messages backwards.
*/
ata_for_each_dev(dev, link, ALL) {
- if (!(new_mask & (1 << dev->devno)) ||
- dev->class == ATA_DEV_PMP)
+ if (!(new_mask & (1 << dev->devno)))
continue;
dev->class = ehc->classes[dev->devno];
+ if (dev->class == ATA_DEV_PMP)
+ continue;
+
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 33a74f11171c..567f3f72774e 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -307,6 +307,9 @@ static unsigned long nv_mode_filter(struct ata_device *dev,
limit |= ATA_MASK_PIO;
if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA)))
limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA;
+ /* PIO4, MWDMA2, UDMA2 should always be supported regardless of
+ cable detection result */
+ limit |= ata_pack_xfermask(ATA_PIO4, ATA_MWDMA2, ATA_UDMA2);
ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index f98dffedf4bc..f0bad9be0f65 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -219,7 +219,7 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
/* Merge the control bits */
regU |= 1 << adev->devno; /* UDMA on */
- if (adev->dma_mode > 2) /* 15nS timing */
+ if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */
regU |= 4 << adev->devno;
} else {
regU &= ~ (1 << adev->devno); /* UDMA off */
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 122c786449a9..ca5f8d7f638c 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
-#define DRV_VERSION "0.6.12"
+#define DRV_VERSION "0.6.14"
struct hpt_clock {
u8 xfer_speed;
@@ -404,9 +404,8 @@ static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_read_config_dword(pdev, addr1, &reg);
mode = hpt37x_find_mode(ap, adev->pio_mode);
- mode &= ~0x8000000; /* No FIFO in PIO */
- mode &= ~0x30070000; /* Leave config bits alone */
- reg &= 0x30070000; /* Strip timing bits */
+ mode &= 0xCFC3FFFF; /* Leave DMA bits alone */
+ reg &= ~0xCFC3FFFF; /* Strip timing bits */
pci_write_config_dword(pdev, addr1, reg | mode);
}
@@ -423,8 +422,7 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 addr1, addr2;
- u32 reg;
- u32 mode;
+ u32 reg, mode, mask;
u8 fast;
addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -436,11 +434,12 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
fast |= 0x01;
pci_write_config_byte(pdev, addr2, fast);
+ mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
+
pci_read_config_dword(pdev, addr1, &reg);
mode = hpt37x_find_mode(ap, adev->dma_mode);
- mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
- mode &= ~0xC0000000; /* Leave config bits alone */
- reg &= 0xC0000000; /* Strip timing bits */
+ mode &= mask;
+ reg &= ~mask;
pci_write_config_dword(pdev, addr1, reg | mode);
}
@@ -508,9 +507,8 @@ static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev)
mode = hpt37x_find_mode(ap, adev->pio_mode);
printk("Find mode for %d reports %X\n", adev->pio_mode, mode);
- mode &= ~0x80000000; /* No FIFO in PIO */
- mode &= ~0x30070000; /* Leave config bits alone */
- reg &= 0x30070000; /* Strip timing bits */
+ mode &= 0xCFC3FFFF; /* Leave DMA bits alone */
+ reg &= ~0xCFC3FFFF; /* Strip timing bits */
pci_write_config_dword(pdev, addr1, reg | mode);
}
@@ -527,8 +525,7 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 addr1, addr2;
- u32 reg;
- u32 mode;
+ u32 reg, mode, mask;
u8 fast;
addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -539,12 +536,13 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev)
fast &= ~0x07;
pci_write_config_byte(pdev, addr2, fast);
+ mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
+
pci_read_config_dword(pdev, addr1, &reg);
mode = hpt37x_find_mode(ap, adev->dma_mode);
printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode);
- mode &= ~0xC0000000; /* Leave config bits alone */
- mode |= 0x80000000; /* FIFO in MWDMA or UDMA */
- reg &= 0xC0000000; /* Strip timing bits */
+ mode &= mask;
+ reg &= ~mask;
pci_write_config_dword(pdev, addr1, reg | mode);
}
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 3d59fe0a408d..d16e87e29189 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -8,7 +8,7 @@
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
- * Portions Copyright (C) 2005-2007 MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
*
*
* TODO
@@ -25,7 +25,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x2n"
-#define DRV_VERSION "0.3.4"
+#define DRV_VERSION "0.3.8"
enum {
HPT_PCI_FAST = (1 << 31),
@@ -185,9 +185,8 @@ static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_read_config_dword(pdev, addr1, &reg);
mode = hpt3x2n_find_mode(ap, adev->pio_mode);
- mode &= ~0x8000000; /* No FIFO in PIO */
- mode &= ~0x30070000; /* Leave config bits alone */
- reg &= 0x30070000; /* Strip timing bits */
+ mode &= 0xCFC3FFFF; /* Leave DMA bits alone */
+ reg &= ~0xCFC3FFFF; /* Strip timing bits */
pci_write_config_dword(pdev, addr1, reg | mode);
}
@@ -204,8 +203,7 @@ static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 addr1, addr2;
- u32 reg;
- u32 mode;
+ u32 reg, mode, mask;
u8 fast;
addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -216,11 +214,12 @@ static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev)
fast &= ~0x07;
pci_write_config_byte(pdev, addr2, fast);
+ mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
+
pci_read_config_dword(pdev, addr1, &reg);
mode = hpt3x2n_find_mode(ap, adev->dma_mode);
- mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
- mode &= ~0xC0000000; /* Leave config bits alone */
- reg &= 0xC0000000; /* Strip timing bits */
+ mode &= mask;
+ reg &= ~mask;
pci_write_config_dword(pdev, addr1, reg | mode);
}
@@ -263,7 +262,7 @@ static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc)
static void hpt3x2n_set_clock(struct ata_port *ap, int source)
{
- void __iomem *bmdma = ap->ioaddr.bmdma_addr;
+ void __iomem *bmdma = ap->ioaddr.bmdma_addr - ap->port_no * 8;
/* Tristate the bus */
iowrite8(0x80, bmdma+0x73);
@@ -273,9 +272,9 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source)
iowrite8(source, bmdma+0x7B);
iowrite8(0xC0, bmdma+0x79);
- /* Reset state machines */
- iowrite8(0x37, bmdma+0x70);
- iowrite8(0x37, bmdma+0x74);
+ /* Reset state machines, avoid enabling the disabled channels */
+ iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70);
+ iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74);
/* Complete reset */
iowrite8(0x00, bmdma+0x79);
@@ -285,21 +284,10 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source)
iowrite8(0x00, bmdma+0x77);
}
-/* Check if our partner interface is busy */
-
-static int hpt3x2n_pair_idle(struct ata_port *ap)
-{
- struct ata_host *host = ap->host;
- struct ata_port *pair = host->ports[ap->port_no ^ 1];
-
- if (pair->hsm_task_state == HSM_ST_IDLE)
- return 1;
- return 0;
-}
-
static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
{
long flags = (long)ap->host->private_data;
+
/* See if we should use the DPLL */
if (writing)
return USE_DPLL; /* Needed for write */
@@ -308,20 +296,35 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
return 0;
}
+static int hpt3x2n_qc_defer(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_port *alt = ap->host->ports[ap->port_no ^ 1];
+ int rc, flags = (long)ap->host->private_data;
+ int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE);
+
+ /* First apply the usual rules */
+ rc = ata_std_qc_defer(qc);
+ if (rc != 0)
+ return rc;
+
+ if ((flags & USE_DPLL) != dpll && alt->qc_active)
+ return ATA_DEFER_PORT;
+ return 0;
+}
+
static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc)
{
- struct ata_taskfile *tf = &qc->tf;
struct ata_port *ap = qc->ap;
int flags = (long)ap->host->private_data;
+ int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE);
- if (hpt3x2n_pair_idle(ap)) {
- int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE));
- if ((flags & USE_DPLL) != dpll) {
- if (dpll == 1)
- hpt3x2n_set_clock(ap, 0x21);
- else
- hpt3x2n_set_clock(ap, 0x23);
- }
+ if ((flags & USE_DPLL) != dpll) {
+ flags &= ~USE_DPLL;
+ flags |= dpll;
+ ap->host->private_data = (void *)(long)flags;
+
+ hpt3x2n_set_clock(ap, dpll ? 0x21 : 0x23);
}
return ata_sff_qc_issue(qc);
}
@@ -338,6 +341,8 @@ static struct ata_port_operations hpt3x2n_port_ops = {
.inherits = &ata_bmdma_port_ops,
.bmdma_stop = hpt3x2n_bmdma_stop,
+
+ .qc_defer = hpt3x2n_qc_defer,
.qc_issue = hpt3x2n_qc_issue,
.cable_detect = hpt3x2n_cable_detect,
@@ -455,7 +460,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
unsigned int f_low, f_high;
int adjust;
unsigned long iobase = pci_resource_start(dev, 4);
- void *hpriv = NULL;
+ void *hpriv = (void *)USE_DPLL;
int rc;
rc = pcim_enable_device(dev);
@@ -543,7 +548,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* Set our private data up. We only need a few flags so we use
it directly */
if (pci_mhz > 60) {
- hpriv = (void *)PCI66;
+ hpriv = (void *)(PCI66 | USE_DPLL);
/*
* On HPT371N, if ATA clock is 66 MHz we must set bit 2 in
* the MISC. register to stretch the UltraDMA Tss timing.
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index f49814d6fd2e..3bbed8322ecf 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -235,8 +235,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA2,
.port_ops = &sc1200_port_ops
};
- /* Can't enable port 2 yet, see top comments */
- const struct ata_port_info *ppi[] = { &info, };
+ const struct ata_port_info *ppi[] = { &info, NULL };
return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
}
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 45657cacec43..88984b803d6d 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -111,7 +111,7 @@ static const struct via_isa_bridge {
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
- { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
+ { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0xff, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
{ "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 86a40582999c..1eb4e020eb5c 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1594,9 +1594,21 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
!ata_dev_enabled(link->device))
sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
NULL, NULL);
- else if (!(ehc->i.flags & ATA_EHI_QUIET))
- ata_link_printk(link, KERN_INFO,
- "nv: skipping hardreset on occupied port\n");
+ else {
+ const unsigned long *timing = sata_ehc_deb_timing(ehc);
+ int rc;
+
+ if (!(ehc->i.flags & ATA_EHI_QUIET))
+ ata_link_printk(link, KERN_INFO, "nv: skipping "
+ "hardreset on occupied port\n");
+
+ /* make sure the link is online */
+ rc = sata_link_resume(link, timing, deadline);
+ /* whine about phy resume failure but proceed */
+ if (rc && rc != -EOPNOTSUPP)
+ ata_link_printk(link, KERN_WARNING, "failed to resume "
+ "link (errno=%d)\n", rc);
+ }
/* device signature acquisition is unreliable */
return -EAGAIN;
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index bdd43c7f432e..02efd9a83d26 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -93,7 +93,6 @@ static const struct pci_device_id svia_pci_tbl[] = {
{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
{ PCI_VDEVICE(VIA, 0x9000), vt8251 },
- { PCI_VDEVICE(VIA, 0x9040), vt8251 },
{ } /* terminate list */
};
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b528145a078f..1e52c125f437 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -104,7 +104,7 @@ extern int system_bus_init(void);
extern int cpu_dev_init(void);
extern int bus_add_device(struct device *dev);
-extern void bus_attach_device(struct device *dev);
+extern void bus_probe_device(struct device *dev);
extern void bus_remove_device(struct device *dev);
extern int bus_add_driver(struct device_driver *drv);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 4b04a15146d7..973bf2ad4e0d 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -459,8 +459,9 @@ static inline void remove_deprecated_bus_links(struct device *dev) { }
* bus_add_device - add device to bus
* @dev: device being added
*
+ * - Add device's bus attributes.
+ * - Create links to device's bus.
* - Add the device to its bus's list of devices.
- * - Create link to device's bus.
*/
int bus_add_device(struct device *dev)
{
@@ -483,6 +484,7 @@ int bus_add_device(struct device *dev)
error = make_deprecated_bus_links(dev);
if (error)
goto out_deprecated;
+ klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
}
return 0;
@@ -498,24 +500,19 @@ out_put:
}
/**
- * bus_attach_device - add device to bus
- * @dev: device tried to attach to a driver
+ * bus_probe_device - probe drivers for a new device
+ * @dev: device to probe
*
- * - Add device to bus's list of devices.
- * - Try to attach to driver.
+ * - Automatically probe for a driver if the bus allows it.
*/
-void bus_attach_device(struct device *dev)
+void bus_probe_device(struct device *dev)
{
struct bus_type *bus = dev->bus;
- int ret = 0;
+ int ret;
- if (bus) {
- if (bus->p->drivers_autoprobe)
- ret = device_attach(dev);
+ if (bus && bus->p->drivers_autoprobe) {
+ ret = device_attach(dev);
WARN_ON(ret < 0);
- if (ret >= 0)
- klist_add_tail(&dev->p->knode_bus,
- &bus->p->klist_devices);
}
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index eb85e4312301..4317d4ca540a 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -59,6 +59,8 @@ static void class_release(struct kobject *kobj)
else
pr_debug("class '%s' does not have a release() function, "
"be careful\n", class->name);
+
+ kfree(cp);
}
static struct sysfs_ops class_sysfs_ops = {
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 7ecb1938e590..c34774d0b9d3 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -945,7 +945,7 @@ int device_add(struct device *dev)
BUS_NOTIFY_ADD_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_ADD);
- bus_attach_device(dev);
+ bus_probe_device(dev);
if (parent)
klist_add_tail(&dev->p->knode_parent,
&parent->p->klist_children);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 8ae0f63602e0..2b7f5bc8c021 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -236,7 +236,7 @@ int driver_register(struct device_driver *drv)
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
- return -EEXIST;
+ return -EBUSY;
}
ret = bus_add_driver(drv);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index a52cc7fe45ea..c18bbbf04e47 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -323,6 +323,9 @@ static int cciss_seq_show(struct seq_file *seq, void *v)
if (*pos > h->highest_lun)
return 0;
+ if (drv == NULL) /* it's possible for h->drv[] to have holes. */
+ return 0;
+
if (drv->heads == 0)
return 0;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 49f086977c37..00ebf36b0059 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -323,7 +323,7 @@ config SPECIALIX
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/serial/sx.txt> for details.
@@ -334,7 +334,7 @@ config SX
config RIO
tristate "Specialix RIO system support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && BROKEN
help
This is a driver for the Specialix RIO, a smart serial card which
drives an outboard box that can support up to 128 ports. Product
@@ -395,7 +395,7 @@ config NOZOMI
config A2232
tristate "Commodore A2232 serial support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
+ depends on EXPERIMENTAL && ZORRO && BROKEN
---help---
This option supports the 2232 7-port serial card shipped with the
Amiga 2000 and other Zorro-bus machines, dating from 1989. At
@@ -444,7 +444,7 @@ config MXC_IIM
config MXS_VIIM
tristate "MXS Virtual IIM device driver"
- depends on (ARCH_STMP3XXX || ARCH_MXS || ARCH_MX5)
+ depends on (ARCH_STMP3XXX || ARCH_MXS)
help
Support for access to MXS Virtual IIM device, most people should say N here.
@@ -564,22 +564,6 @@ config BFIN_OTP_WRITE_ENABLE
If unsure, say N.
-config FSL_OTP
- tristate "Freescale On-Chip OTP Memory Support"
- depends on (ARCH_MX23 || ARCH_MX28 || ARCH_MX50)
- default n
- help
- If you say Y here, you will get support for a character device
- interface into the One Time Programmable memory pages that are
- stored on the iMX23/28/50 processor. This will not get you access
- to the secure memory pages however. You will need to write your
- own secure code and reader for that.
-
- To compile this driver as a module, choose M here: the module
- will be called fsl_otp.
-
- If unsure, it is safe to say Y.
-
config PRINTER
tristate "Parallel printer support"
depends on PARPORT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 898ce27e335d..c711f02de8f7 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -69,7 +69,6 @@ obj-$(CONFIG_IBM_BSR) += bsr.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o
obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
-obj-$(CONFIG_FSL_OTP) += fsl_otp.o
obj-$(CONFIG_PRINTER) += lp.o
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index cfa5a649dfe7..19ce9d6c69f1 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -114,9 +114,9 @@ static int agp_find_max(void)
long memory, index, result;
#if PAGE_SHIFT < 20
- memory = num_physpages >> (20 - PAGE_SHIFT);
+ memory = totalram_pages >> (20 - PAGE_SHIFT);
#else
- memory = num_physpages << (PAGE_SHIFT - 20);
+ memory = totalram_pages << (PAGE_SHIFT - 20);
#endif
index = 1;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index c58557790585..62711ddeb53a 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -36,6 +36,8 @@
#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
+#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40
+#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
#define PCI_DEVICE_ID_INTEL_IGD_E_HB 0x2E00
@@ -50,6 +52,7 @@
#define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042
#define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044
#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB 0x0062
+#define PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB 0x006a
#define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046
/* cover 915 and 945 variants */
@@ -81,9 +84,11 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB)
extern int agp_memory_reserved;
@@ -679,23 +684,39 @@ static void intel_i830_setup_flush(void)
if (!intel_private.i8xx_page)
return;
- /* make page uncached */
- map_page_into_agp(intel_private.i8xx_page);
-
intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
if (!intel_private.i8xx_flush_page)
intel_i830_fini_flush();
}
+static void
+do_wbinvd(void *null)
+{
+ wbinvd();
+}
+
+/* The chipset_flush interface needs to get data that has already been
+ * flushed out of the CPU all the way out to main memory, because the GPU
+ * doesn't snoop those buffers.
+ *
+ * The 8xx series doesn't have the same lovely interface for flushing the
+ * chipset write buffers that the later chips do. According to the 865
+ * specs, it's 64 octwords, or 1KB. So, to get those previous things in
+ * that buffer out, we just fill 1KB and clflush it out, on the assumption
+ * that it'll push whatever was in there out. It appears to work.
+ */
static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
{
unsigned int *pg = intel_private.i8xx_flush_page;
- int i;
- for (i = 0; i < 256; i += 2)
- *(pg + i) = i;
+ memset(pg, 0, 1024);
- wmb();
+ if (cpu_has_clflush) {
+ clflush_cache_range(pg, 1024);
+ } else {
+ if (on_each_cpu(do_wbinvd, NULL, 1) != 0)
+ printk(KERN_ERR "Timed out waiting for cache flush.\n");
+ }
}
/* The intel i830 automatically initializes the agp aperture during POST.
@@ -1216,9 +1237,11 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
case PCI_DEVICE_ID_INTEL_Q45_HB:
case PCI_DEVICE_ID_INTEL_G45_HB:
case PCI_DEVICE_ID_INTEL_G41_HB:
+ case PCI_DEVICE_ID_INTEL_B43_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_D_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_M_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB:
+ case PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB:
*gtt_offset = *gtt_size = MB(2);
break;
default:
@@ -2192,6 +2215,8 @@ static const struct intel_driver_description {
"Q45/Q43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0,
"G45/G43", NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0,
+ "B43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
"G41", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0,
@@ -2200,6 +2225,8 @@ static const struct intel_driver_description {
"IGDNG/M", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
"IGDNG/MA", NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
+ "IGDNG/MC2", NULL, &intel_i965_driver },
{ 0, 0, 0, NULL, NULL, NULL }
};
@@ -2313,15 +2340,6 @@ static int agp_intel_resume(struct pci_dev *pdev)
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
int ret_val;
- pci_restore_state(pdev);
-
- /* We should restore our graphics device's config space,
- * as host bridge (00:00) resumes before graphics device (02:00),
- * then our access to its pci space can work right.
- */
- if (intel_private.pcidev)
- pci_restore_state(intel_private.pcidev);
-
if (bridge->driver == &intel_generic_driver)
intel_configure();
else if (bridge->driver == &intel_850_driver)
@@ -2401,9 +2419,11 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_Q45_HB),
ID(PCI_DEVICE_ID_INTEL_G45_HB),
ID(PCI_DEVICE_ID_INTEL_G41_HB),
+ ID(PCI_DEVICE_ID_INTEL_B43_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB),
+ ID(PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB),
{ }
};
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c
index eba999f8598d..ae453cc25a66 100644
--- a/drivers/char/hvc_xen.c
+++ b/drivers/char/hvc_xen.c
@@ -55,7 +55,7 @@ static inline void notify_daemon(void)
notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
}
-static int write_console(uint32_t vtermno, const char *data, int len)
+static int __write_console(const char *data, int len)
{
struct xencons_interface *intf = xencons_interface();
XENCONS_RING_IDX cons, prod;
@@ -76,6 +76,29 @@ static int write_console(uint32_t vtermno, const char *data, int len)
return sent;
}
+static int write_console(uint32_t vtermno, const char *data, int len)
+{
+ int ret = len;
+
+ /*
+ * Make sure the whole buffer is emitted, polling if
+ * necessary. We don't ever want to rely on the hvc daemon
+ * because the most interesting console output is when the
+ * kernel is crippled.
+ */
+ while (len) {
+ int sent = __write_console(data, len);
+
+ data += sent;
+ len -= sent;
+
+ if (unlikely(len))
+ HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+ }
+
+ return ret;
+}
+
static int read_console(uint32_t vtermno, char *buf, int len)
{
struct xencons_interface *intf = xencons_interface();
diff --git a/drivers/char/hw_random/fsl-rngc.c b/drivers/char/hw_random/fsl-rngc.c
index 9e788f97c4d8..9bf78e846fa0 100644
--- a/drivers/char/hw_random/fsl-rngc.c
+++ b/drivers/char/hw_random/fsl-rngc.c
@@ -1,7 +1,7 @@
/*
* RNG driver for Freescale RNGC
*
- * Copyright (C) 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -42,6 +42,7 @@
#include <linux/interrupt.h>
#include <linux/hw_random.h>
#include <linux/io.h>
+#include <asm/hardware.h>
#define RNGC_VERSION_MAJOR3 3
@@ -291,7 +292,7 @@ static int __init fsl_rngc_probe(struct platform_device *pdev)
if (rng_dev)
return -EBUSY;
- clk = clk_get(&pdev->dev, "rng_clk");
+ clk = clk_get(NULL, "rng_clk");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Can not get rng_clk\n");
@@ -333,17 +334,9 @@ static int __init fsl_rngc_probe(struct platform_device *pdev)
static int __exit fsl_rngc_remove(struct platform_device *pdev)
{
- struct clk *clk;
struct resource *mem = dev_get_drvdata(&pdev->dev);
void __iomem *rngc_base = (void __iomem *)fsl_rngc.priv;
- clk = clk_get(&pdev->dev, "rng_clk");
-
- if (IS_ERR(clk))
- dev_err(&pdev->dev, "Can not get rng_clk\n");
- else
- clk_disable(clk);
-
hwrng_unregister(&fsl_rngc);
release_resource(mem);
@@ -353,47 +346,12 @@ static int __exit fsl_rngc_remove(struct platform_device *pdev)
return 0;
}
-static int fsl_rngc_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
-#ifdef CONFIG_PM
- struct clk *clk = clk_get(&pdev->dev, "rng_clk");
-
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Can not get rng_clk\n");
- return PTR_ERR(clk);
- }
-
- clk_disable(clk);
-#endif
-
- return 0;
-}
-
-static int fsl_rngc_resume(struct platform_device *pdev)
-{
-#ifdef CONFIG_PM
- struct clk *clk = clk_get(&pdev->dev, "rng_clk");
-
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Can not get rng_clk\n");
- return PTR_ERR(clk);
- }
-
- clk_enable(clk);
-#endif
-
- return 0;
-}
-
static struct platform_driver fsl_rngc_driver = {
.driver = {
.name = "fsl_rngc",
.owner = THIS_MODULE,
},
.remove = __exit_p(fsl_rngc_remove),
- .suspend = fsl_rngc_suspend,
- .resume = fsl_rngc_resume,
};
static int __init mod_init(void)
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 737be953cc58..950837cf9e9c 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1249,7 +1249,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
if (keycode >= NR_KEYS)
if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
- keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
+ keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
else
return;
else
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index ec58d8c387ff..2171e9dac1ab 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1628,10 +1628,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file)
dc->open_ttys--;
port->count--;
- tty_port_tty_set(port, NULL);
if (port->count == 0) {
DBG1("close: %d", nport->token_dl);
+ tty_port_tty_set(port, NULL);
spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier &= ~(nport->token_dl);
writew(dc->last_ier, dc->reg_ier);
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index b33d6688e910..53761cefa915 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -120,8 +120,10 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
/* Stuff the data into the input queue of the other end */
c = tty_insert_flip_string(to, buf, c);
/* And shovel */
- tty_flip_buffer_push(to);
- tty_wakeup(tty);
+ if (c) {
+ tty_flip_buffer_push(to);
+ tty_wakeup(tty);
+ }
}
return c;
}
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index b0603b2e5684..47c2d2763456 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -696,8 +696,7 @@ int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
cmd.header.in = pcrread_header;
cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
- BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE);
- rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
+ rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
"attempting to read a pcr value");
if (rc == 0)
@@ -742,7 +741,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
* the module usage count.
*/
#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
-#define EXTEND_PCR_SIZE 34
+#define EXTEND_PCR_RESULT_SIZE 34
static struct tpm_input_header pcrextend_header = {
.tag = TPM_TAG_RQU_COMMAND,
.length = cpu_to_be32(34),
@@ -760,10 +759,9 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
return -ENODEV;
cmd.header.in = pcrextend_header;
- BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE);
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
- rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
+ rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
"attempting extend a PCR value");
module_put(chip->dev->driver->owner);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index aec1931608aa..0b73e4ec1add 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -450,6 +450,12 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
goto out_err;
}
+ /* Default timeouts */
+ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
if (request_locality(chip, 0) != 0) {
rc = -ENODEV;
goto out_err;
@@ -457,12 +463,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
- /* Default timeouts */
- chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
- chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
- chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
- chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
-
dev_info(dev,
"1.2 TPM (device-id 0x%X, rev-id %d)\n",
vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
index 3108991c5c8b..0296612cc7df 100644
--- a/drivers/char/tty_buffer.c
+++ b/drivers/char/tty_buffer.c
@@ -402,28 +402,26 @@ static void flush_to_ldisc(struct work_struct *work)
container_of(work, struct tty_struct, buf.work.work);
unsigned long flags;
struct tty_ldisc *disc;
- struct tty_buffer *tbuf, *head;
- char *char_buf;
- unsigned char *flag_buf;
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
return;
spin_lock_irqsave(&tty->buf.lock, flags);
- /* So we know a flush is running */
- set_bit(TTY_FLUSHING, &tty->flags);
- head = tty->buf.head;
- if (head != NULL) {
- tty->buf.head = NULL;
- for (;;) {
- int count = head->commit - head->read;
+
+ if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+ struct tty_buffer *head;
+ while ((head = tty->buf.head) != NULL) {
+ int count;
+ char *char_buf;
+ unsigned char *flag_buf;
+
+ count = head->commit - head->read;
if (!count) {
if (head->next == NULL)
break;
- tbuf = head;
- head = head->next;
- tty_buffer_free(tty, tbuf);
+ tty->buf.head = head->next;
+ tty_buffer_free(tty, head);
continue;
}
/* Ldisc or user is trying to flush the buffers
@@ -445,9 +443,9 @@ static void flush_to_ldisc(struct work_struct *work)
flag_buf, count);
spin_lock_irqsave(&tty->buf.lock, flags);
}
- /* Restore the queue head */
- tty->buf.head = head;
+ clear_bit(TTY_FLUSHING, &tty->flags);
}
+
/* We may have a deferred request to flush the input buffer,
if so pull the chain under the lock and empty the queue */
if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
@@ -455,7 +453,6 @@ static void flush_to_ldisc(struct work_struct *work)
clear_bit(TTY_FLUSHPENDING, &tty->flags);
wake_up(&tty->read_wait);
}
- clear_bit(TTY_FLUSHING, &tty->flags);
spin_unlock_irqrestore(&tty->buf.lock, flags);
tty_ldisc_deref(disc);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a3afa0c387cd..9531cf8b3482 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1184,6 +1184,7 @@ int tty_init_termios(struct tty_struct *tty)
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
return 0;
}
+EXPORT_SYMBOL_GPL(tty_init_termios);
/**
* tty_driver_install_tty() - install a tty entry in the driver
@@ -1911,8 +1912,10 @@ static int tty_fasync(int fd, struct file *filp, int on)
pid = task_pid(current);
type = PIDTYPE_PID;
}
+ get_pid(pid);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
retval = __f_setown(filp, pid, type, 0);
+ put_pid(pid);
if (retval)
goto out;
} else {
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index e48af9f79219..414372a442d9 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -516,7 +516,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
static int tty_ldisc_halt(struct tty_struct *tty)
{
clear_bit(TTY_LDISC, &tty->flags);
- return cancel_delayed_work(&tty->buf.work);
+ return cancel_delayed_work_sync(&tty->buf.work);
}
/**
@@ -754,12 +754,9 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* N_TTY.
*/
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- /* Make sure the old ldisc is quiescent */
- tty_ldisc_halt(tty);
- flush_scheduled_work();
-
/* Avoid racing set_ldisc or tty_ldisc_release */
mutex_lock(&tty->ldisc_mutex);
+ tty_ldisc_halt(tty);
if (tty->ldisc) { /* Not yet closed */
/* Switch back to N_TTY */
tty_ldisc_reinit(tty);
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 9769b1149f76..c0ff7eeafbb2 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -96,6 +96,14 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_port_tty_set);
+static void tty_port_shutdown(struct tty_port *port)
+{
+ if (port->ops->shutdown &&
+ test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
+ port->ops->shutdown(port);
+
+}
+
/**
* tty_port_hangup - hangup helper
* @port: tty port
@@ -116,6 +124,7 @@ void tty_port_hangup(struct tty_port *port)
port->tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
wake_up_interruptible(&port->open_wait);
+ tty_port_shutdown(port);
}
EXPORT_SYMBOL(tty_port_hangup);
@@ -208,8 +217,14 @@ int tty_port_block_til_ready(struct tty_port *port,
/* if non-blocking mode is set we can pass directly to open unless
the port has just hung up or is in another error state */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
+ if (tty->flags & (1 << TTY_IO_ERROR)) {
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+ if (filp->f_flags & O_NONBLOCK) {
+ /* Indicate we are open */
+ if (tty->termios->c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -296,15 +311,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
if (port->count) {
spin_unlock_irqrestore(&port->lock, flags);
+ if (port->ops->drop)
+ port->ops->drop(port);
return 0;
}
- port->flags |= ASYNC_CLOSING;
+ set_bit(ASYNCB_CLOSING, &port->flags);
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
/* Don't block on a stalled port, just pull the chain */
if (tty->flow_stopped)
tty_driver_flush_buffer(tty);
- if (port->flags & ASYNC_INITIALIZED &&
+ if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->closing_wait);
if (port->drain_delay) {
@@ -318,6 +335,9 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
}
+ /* Don't call port->drop for the last reference. Callers will want
+ to drop the last active reference in ->shutdown() or the tty
+ shutdown path */
return 1;
}
EXPORT_SYMBOL(tty_port_close_start);
@@ -348,3 +368,14 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL(tty_port_close_end);
+
+void tty_port_close(struct tty_port *port, struct tty_struct *tty,
+ struct file *filp)
+{
+ if (tty_port_close_start(port, tty, filp) == 0)
+ return;
+ tty_port_shutdown(port);
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
+}
+EXPORT_SYMBOL(tty_port_close);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 404f4c1ee431..6aa88f50b039 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2948,9 +2948,6 @@ int __init vty_init(const struct file_operations *console_fops)
panic("Couldn't register console driver\n");
kbd_init();
console_map_init();
-#ifdef CONFIG_PROM_CONSOLE
- prom_con_init();
-#endif
#ifdef CONFIG_MDA_CONSOLE
mda_console_init();
#endif
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index c5afc98e2675..9ca20d04dd5a 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -202,9 +202,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
* cn_proc_mcast_ctl
* @data: message sent from userspace via the connector
*/
-static void cn_proc_mcast_ctl(void *data)
+static void cn_proc_mcast_ctl(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
- struct cn_msg *msg = data;
enum proc_cn_mcast_op *mc_op = NULL;
int err = 0;
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index 408c2af25d50..210338ea222f 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -78,16 +78,20 @@ void cn_queue_wrapper(struct work_struct *work)
struct cn_callback_entry *cbq =
container_of(work, struct cn_callback_entry, work);
struct cn_callback_data *d = &cbq->data;
+ struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(d->skb));
+ struct netlink_skb_parms *nsp = &NETLINK_CB(d->skb);
- d->callback(d->callback_priv);
+ d->callback(msg, nsp);
- d->destruct_data(d->ddata);
- d->ddata = NULL;
+ kfree_skb(d->skb);
+ d->skb = NULL;
kfree(d->free);
}
-static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
+static struct cn_callback_entry *
+cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
{
struct cn_callback_entry *cbq;
@@ -120,7 +124,8 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
return ((i1->idx == i2->idx) && (i1->val == i2->val));
}
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
{
struct cn_callback_entry *cbq, *__cbq;
int found = 0;
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 08b2500f21ec..537c29ac4487 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -36,17 +36,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
-static u32 cn_idx = CN_IDX_CONNECTOR;
-static u32 cn_val = CN_VAL_CONNECTOR;
-
-module_param(cn_idx, uint, 0);
-module_param(cn_val, uint, 0);
-MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
-MODULE_PARM_DESC(cn_val, "Connector's main device val.");
-
-static DEFINE_MUTEX(notify_lock);
-static LIST_HEAD(notify_list);
-
static struct cn_dev cdev;
static int cn_already_initialized;
@@ -129,21 +118,19 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
/*
* Callback helper - queues work and setup destructor for given data.
*/
-static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
+static int cn_call_callback(struct sk_buff *skb)
{
struct cn_callback_entry *__cbq, *__new_cbq;
struct cn_dev *dev = &cdev;
+ struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb));
int err = -ENODEV;
spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
if (likely(!work_pending(&__cbq->work) &&
- __cbq->data.ddata == NULL)) {
- __cbq->data.callback_priv = msg;
-
- __cbq->data.ddata = data;
- __cbq->data.destruct_data = destruct_data;
+ __cbq->data.skb == NULL)) {
+ __cbq->data.skb = skb;
if (queue_cn_work(__cbq, &__cbq->work))
err = 0;
@@ -156,10 +143,8 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
__new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
if (__new_cbq) {
d = &__new_cbq->data;
- d->callback_priv = msg;
+ d->skb = skb;
d->callback = __cbq->data.callback;
- d->ddata = data;
- d->destruct_data = destruct_data;
d->free = __new_cbq;
__new_cbq->pdev = __cbq->pdev;
@@ -191,7 +176,6 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
*/
static void cn_rx_skb(struct sk_buff *__skb)
{
- struct cn_msg *msg;
struct nlmsghdr *nlh;
int err;
struct sk_buff *skb;
@@ -208,68 +192,20 @@ static void cn_rx_skb(struct sk_buff *__skb)
return;
}
- msg = NLMSG_DATA(nlh);
- err = cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+ err = cn_call_callback(skb);
if (err < 0)
kfree_skb(skb);
}
}
/*
- * Notification routing.
- *
- * Gets id and checks if there are notification request for it's idx
- * and val. If there are such requests notify the listeners with the
- * given notify event.
- *
- */
-static void cn_notify(struct cb_id *id, u32 notify_event)
-{
- struct cn_ctl_entry *ent;
-
- mutex_lock(&notify_lock);
- list_for_each_entry(ent, &notify_list, notify_entry) {
- int i;
- struct cn_notify_req *req;
- struct cn_ctl_msg *ctl = ent->msg;
- int idx_found, val_found;
-
- idx_found = val_found = 0;
-
- req = (struct cn_notify_req *)ctl->data;
- for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
- if (id->idx >= req->first &&
- id->idx < req->first + req->range) {
- idx_found = 1;
- break;
- }
- }
-
- for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
- if (id->val >= req->first &&
- id->val < req->first + req->range) {
- val_found = 1;
- break;
- }
- }
-
- if (idx_found && val_found) {
- struct cn_msg m = { .ack = notify_event, };
-
- memcpy(&m.id, id, sizeof(m.id));
- cn_netlink_send(&m, ctl->group, GFP_KERNEL);
- }
- }
- mutex_unlock(&notify_lock);
-}
-
-/*
* Callback add routing - adds callback with given ID and name.
* If there is registered callback with the same ID it will not be added.
*
* May sleep.
*/
-int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
+int cn_add_callback(struct cb_id *id, char *name,
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
{
int err;
struct cn_dev *dev = &cdev;
@@ -281,8 +217,6 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
if (err)
return err;
- cn_notify(id, 0);
-
return 0;
}
EXPORT_SYMBOL_GPL(cn_add_callback);
@@ -300,112 +234,9 @@ void cn_del_callback(struct cb_id *id)
struct cn_dev *dev = &cdev;
cn_queue_del_callback(dev->cbdev, id);
- cn_notify(id, 1);
}
EXPORT_SYMBOL_GPL(cn_del_callback);
-/*
- * Checks two connector's control messages to be the same.
- * Returns 1 if they are the same or if the first one is corrupted.
- */
-static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
-{
- int i;
- struct cn_notify_req *req1, *req2;
-
- if (m1->idx_notify_num != m2->idx_notify_num)
- return 0;
-
- if (m1->val_notify_num != m2->val_notify_num)
- return 0;
-
- if (m1->len != m2->len)
- return 0;
-
- if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
- m1->len)
- return 1;
-
- req1 = (struct cn_notify_req *)m1->data;
- req2 = (struct cn_notify_req *)m2->data;
-
- for (i = 0; i < m1->idx_notify_num; ++i) {
- if (req1->first != req2->first || req1->range != req2->range)
- return 0;
- req1++;
- req2++;
- }
-
- for (i = 0; i < m1->val_notify_num; ++i) {
- if (req1->first != req2->first || req1->range != req2->range)
- return 0;
- req1++;
- req2++;
- }
-
- return 1;
-}
-
-/*
- * Main connector device's callback.
- *
- * Used for notification of a request's processing.
- */
-static void cn_callback(void *data)
-{
- struct cn_msg *msg = data;
- struct cn_ctl_msg *ctl;
- struct cn_ctl_entry *ent;
- u32 size;
-
- if (msg->len < sizeof(*ctl))
- return;
-
- ctl = (struct cn_ctl_msg *)msg->data;
-
- size = (sizeof(*ctl) + ((ctl->idx_notify_num +
- ctl->val_notify_num) *
- sizeof(struct cn_notify_req)));
-
- if (msg->len != size)
- return;
-
- if (ctl->len + sizeof(*ctl) != msg->len)
- return;
-
- /*
- * Remove notification.
- */
- if (ctl->group == 0) {
- struct cn_ctl_entry *n;
-
- mutex_lock(&notify_lock);
- list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
- if (cn_ctl_msg_equals(ent->msg, ctl)) {
- list_del(&ent->notify_entry);
- kfree(ent);
- }
- }
- mutex_unlock(&notify_lock);
-
- return;
- }
-
- size += sizeof(*ent);
-
- ent = kzalloc(size, GFP_KERNEL);
- if (!ent)
- return;
-
- ent->msg = (struct cn_ctl_msg *)(ent + 1);
-
- memcpy(ent->msg, ctl, size - sizeof(*ent));
-
- mutex_lock(&notify_lock);
- list_add(&ent->notify_entry, &notify_list);
- mutex_unlock(&notify_lock);
-}
-
static int cn_proc_show(struct seq_file *m, void *v)
{
struct cn_queue_dev *dev = cdev.cbdev;
@@ -443,11 +274,8 @@ static const struct file_operations cn_file_ops = {
static int __devinit cn_init(void)
{
struct cn_dev *dev = &cdev;
- int err;
dev->input = cn_rx_skb;
- dev->id.idx = cn_idx;
- dev->id.val = cn_val;
dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
CN_NETLINK_USERS + 0xf,
@@ -463,14 +291,6 @@ static int __devinit cn_init(void)
cn_already_initialized = 1;
- err = cn_add_callback(&dev->id, "connector", &cn_callback);
- if (err) {
- cn_already_initialized = 0;
- cn_queue_free_dev(dev->cbdev);
- netlink_kernel_release(dev->nls);
- return -EINVAL;
- }
-
proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
return 0;
@@ -484,7 +304,6 @@ static void __devexit cn_fini(void)
proc_net_remove(&init_net, "connector");
- cn_del_callback(&dev->id);
cn_queue_free_dev(dev->cbdev);
netlink_kernel_release(dev->nls);
}
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 8504a2108557..910c49d2641c 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -75,8 +75,11 @@ static void cpuidle_idle_call(void)
#endif
/* ask the governor for the next state */
next_state = cpuidle_curr_governor->select(dev);
- if (need_resched())
+ if (need_resched()) {
+ local_irq_enable();
return;
+ }
+
target_state = &dev->states[next_state];
/* enter the state and update stats */
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 5057cb958230..9c2919a431a8 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -211,7 +211,7 @@ config CRYPTO_DEV_PPC4XX
config CRYPTO_DEV_DCP
tristate "Support for the DCP engine"
- depends on ARCH_MX28 || ARCH_MX23 || ARCH_MX50
+ depends on ARCH_MX28 || ARCH_MX23
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
help
diff --git a/drivers/crypto/dcp.c b/drivers/crypto/dcp.c
index eb7a83d276b7..8b54b127d6d0 100644
--- a/drivers/crypto/dcp.c
+++ b/drivers/crypto/dcp.c
@@ -36,7 +36,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
-#include <linux/clk.h>
+
#include <linux/io.h>
#include <linux/delay.h>
@@ -60,8 +60,6 @@ struct dcp {
int dcp_vmi_irq;
int dcp_irq;
u32 dcp_regs_base;
- ulong clock_state;
- bool chan_in_use[DCP_NUM_CHANNELS];
/* Following buffers used in hashing to meet 64-byte len alignment */
char *buf1;
@@ -97,10 +95,6 @@ struct dcp {
#define DCP_FILL 0x5000
#define DCP_MODE_MASK 0xf000
-/* clock defines */
-#define CLOCK_ON 1
-#define CLOCK_OFF 0
-
struct dcp_op {
unsigned int flags;
@@ -183,45 +177,6 @@ struct dcp_hash_op {
/* only one */
static struct dcp *global_sdcp;
-static void dcp_clock(struct dcp *sdcp, ulong state, bool force)
-{
- u32 chan;
- struct clk *clk = clk_get(sdcp->dev, "dcp_clk");
-
- /* unless force is true (used during suspend/resume), if any
- * channel is running, then clk is already on, and must stay on */
- if (!force)
- for (chan = 0; chan < DCP_NUM_CHANNELS; chan++)
- if (sdcp->chan_in_use[chan])
- goto exit;
-
- if (state == CLOCK_OFF) {
- /* gate at clock source */
- if (!IS_ERR(clk))
- clk_disable(clk);
- /* gate at DCP */
- else
- __raw_writel(BM_DCP_CTRL_CLKGATE,
- sdcp->dcp_regs_base + HW_DCP_CTRL_SET);
-
- sdcp->clock_state = CLOCK_OFF;
-
- } else {
- /* ungate at clock source */
- if (!IS_ERR(clk))
- clk_enable(clk);
- /* ungate at DCP */
- else
- __raw_writel(BM_DCP_CTRL_CLKGATE,
- sdcp->dcp_regs_base + HW_DCP_CTRL_CLR);
-
- sdcp->clock_state = CLOCK_ON;
- }
-
-exit:
- return;
-}
-
static void dcp_perform_op(struct dcp_op *op)
{
struct dcp *sdcp = global_sdcp;
@@ -307,8 +262,6 @@ static void dcp_perform_op(struct dcp_op *op)
/* submit the work */
mutex_lock(mutex);
- dcp_clock(sdcp, CLOCK_ON, false);
- sdcp->chan_in_use[chan] = true;
__raw_writel(-1, sdcp->dcp_regs_base + HW_DCP_CHnSTAT_CLR(chan));
@@ -337,9 +290,8 @@ static void dcp_perform_op(struct dcp_op *op)
__raw_readl(sdcp->dcp_regs_base +
HW_DCP_CHnSTAT(chan)) & 0xff);
out:
- sdcp->chan_in_use[chan] = false;
- dcp_clock(sdcp, CLOCK_OFF, false);
mutex_unlock(mutex);
+
dma_unmap_single(sdcp->dev, pkt_phys, sizeof(*pkt), DMA_TO_DEVICE);
}
@@ -1109,8 +1061,6 @@ static int dcp_sha_init(struct shash_desc *desc)
struct mutex *mutex = &sdcp->op_mutex[HASH_CHAN];
mutex_lock(mutex);
- dcp_clock(sdcp, CLOCK_ON, false);
- sdcp->chan_in_use[HASH_CHAN] = true;
op->length = 0;
@@ -1240,8 +1190,6 @@ static int dcp_sha_final(struct shash_desc *desc, u8 *out)
for (i = 0; i < digest_len; i++)
*out++ = *--digest;
- sdcp->chan_in_use[HASH_CHAN] = false;
- dcp_clock(sdcp, CLOCK_OFF, false);
mutex_unlock(mutex);
return ret;
@@ -1340,8 +1288,6 @@ static int dcp_bootstream_ioctl(struct inode *inode, struct file *file,
mutex = &sdcp->op_mutex[chan];
mutex_lock(mutex);
- dcp_clock(sdcp, CLOCK_ON, false);
- sdcp->chan_in_use[chan] = true;
__raw_writel(-1, sdcp->dcp_regs_base +
HW_DCP_CHnSTAT_CLR(ROM_DCP_CHAN));
@@ -1402,8 +1348,6 @@ static int dcp_bootstream_ioctl(struct inode *inode, struct file *file,
retVal = 0;
exit:
- sdcp->chan_in_use[chan] = false;
- dcp_clock(sdcp, CLOCK_OFF, false);
mutex_unlock(mutex);
return retVal;
}
@@ -1446,7 +1390,6 @@ static int dcp_probe(struct platform_device *pdev)
for (i = 0; i < DCP_NUM_CHANNELS; i++) {
mutex_init(&sdcp->op_mutex[i]);
init_completion(&sdcp->op_wait[i]);
- sdcp->chan_in_use[i] = false;
}
platform_set_drvdata(pdev, sdcp);
@@ -1457,8 +1400,7 @@ static int dcp_probe(struct platform_device *pdev)
ret = -ENXIO;
goto err_kfree;
}
- sdcp->dcp_regs_base = (u32) ioremap(r->start, r->end - r->start + 1);
- dcp_clock(sdcp, CLOCK_ON, true);
+ sdcp->dcp_regs_base = (u32) IO_ADDRESS(r->start);
/* Soft reset and remove the clock gate */
__raw_writel(BM_DCP_CTRL_SFTRST, sdcp->dcp_regs_base + HW_DCP_CTRL_SET);
@@ -1494,14 +1436,14 @@ static int dcp_probe(struct platform_device *pdev)
if (!r) {
dev_err(&pdev->dev, "can't get IRQ resource (0)\n");
ret = -EIO;
- goto err_gate_clk;
+ goto err_kfree;
}
sdcp->dcp_vmi_irq = r->start;
ret = request_irq(sdcp->dcp_vmi_irq, dcp_vmi_irq, 0, "dcp",
sdcp);
if (ret != 0) {
dev_err(&pdev->dev, "can't request_irq (0)\n");
- goto err_gate_clk;
+ goto err_kfree;
}
r = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
@@ -1522,7 +1464,7 @@ static int dcp_probe(struct platform_device *pdev)
ret = crypto_register_alg(&dcp_aes_alg);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to register aes crypto\n");
- goto err_free_irq1;
+ goto err_kfree;
}
ret = crypto_register_alg(&dcp_aes_ecb_alg);
@@ -1633,7 +1575,6 @@ static int dcp_probe(struct platform_device *pdev)
goto err_dereg;
}
- dcp_clock(sdcp, CLOCK_OFF, false);
dev_notice(&pdev->dev, "DCP crypto enabled.!\n");
return 0;
@@ -1647,12 +1588,8 @@ err_unregister_aes_ecb:
crypto_unregister_alg(&dcp_aes_ecb_alg);
err_unregister_aes:
crypto_unregister_alg(&dcp_aes_alg);
-err_free_irq1:
- free_irq(sdcp->dcp_irq, sdcp);
err_free_irq0:
free_irq(sdcp->dcp_vmi_irq, sdcp);
-err_gate_clk:
- dcp_clock(sdcp, CLOCK_OFF, false);
err_kfree:
kfree(sdcp);
err:
@@ -1667,8 +1604,6 @@ static int dcp_remove(struct platform_device *pdev)
sdcp = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
- dcp_clock(sdcp, CLOCK_ON, false);
-
free_irq(sdcp->dcp_irq, sdcp);
free_irq(sdcp->dcp_vmi_irq, sdcp);
@@ -1707,41 +1642,28 @@ static int dcp_remove(struct platform_device *pdev)
crypto_unregister_alg(&dcp_aes_cbc_alg);
crypto_unregister_alg(&dcp_aes_ecb_alg);
crypto_unregister_alg(&dcp_aes_alg);
-
- dcp_clock(sdcp, CLOCK_OFF, true);
- iounmap((void *) sdcp->dcp_regs_base);
kfree(sdcp);
global_sdcp = NULL;
return 0;
}
+
+#ifdef CONFIG_PM
static int dcp_suspend(struct platform_device *pdev,
pm_message_t state)
{
-#ifdef CONFIG_PM
- struct dcp *sdcp = platform_get_drvdata(pdev);
-
- if (sdcp->clock_state == CLOCK_ON) {
- dcp_clock(sdcp, CLOCK_OFF, true);
- /* indicate that clock needs to be turned on upon resume */
- sdcp->clock_state = CLOCK_ON;
- }
-#endif
return 0;
}
static int dcp_resume(struct platform_device *pdev)
{
-#ifdef CONFIG_PM
- struct dcp *sdcp = platform_get_drvdata(pdev);
-
- /* if clock was on prior to suspend, turn it back on */
- if (sdcp->clock_state == CLOCK_ON)
- dcp_clock(sdcp, CLOCK_ON, true);
-#endif
return 0;
}
+#else
+#define dcp_suspend NULL
+#define dcp_resume NULL
+#endif
static struct platform_driver dcp_driver = {
.probe = dcp_probe,
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index a9952b1236b0..84c51e177269 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -236,7 +236,7 @@ static inline void ecb_crypt(const u8 *in, u8 *out, u32 *key,
/* Padlock in ECB mode fetches at least ecb_fetch_bytes of data.
* We could avoid some copying here but it's probably not worth it.
*/
- if (unlikely(((unsigned long)in & PAGE_SIZE) + ecb_fetch_bytes > PAGE_SIZE)) {
+ if (unlikely(((unsigned long)in & ~PAGE_MASK) + ecb_fetch_bytes > PAGE_SIZE)) {
ecb_crypt_copy(in, out, key, cword, count);
return;
}
@@ -248,7 +248,7 @@ static inline u8 *cbc_crypt(const u8 *in, u8 *out, u32 *key,
u8 *iv, struct cword *cword, int count)
{
/* Padlock in CBC mode fetches at least cbc_fetch_bytes of data. */
- if (unlikely(((unsigned long)in & PAGE_SIZE) + cbc_fetch_bytes > PAGE_SIZE))
+ if (unlikely(((unsigned long)in & ~PAGE_MASK) + cbc_fetch_bytes > PAGE_SIZE))
return cbc_crypt_copy(in, out, key, iv, cword, count);
return rep_xcrypt_cbc(in, out, key, iv, cword, count);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 9a1e5fb412ed..73957fb9db5f 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -813,7 +813,7 @@ atc_is_tx_complete(struct dma_chan *chan,
dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n",
cookie, done ? *done : 0, used ? *used : 0);
- spin_lock_bh(atchan->lock);
+ spin_lock_bh(&atchan->lock);
last_complete = atchan->completed_cookie;
last_used = chan->cookie;
@@ -828,7 +828,7 @@ atc_is_tx_complete(struct dma_chan *chan,
ret = dma_async_is_complete(cookie, last_complete, last_used);
}
- spin_unlock_bh(atchan->lock);
+ spin_unlock_bh(&atchan->lock);
if (done)
*done = last_complete;
diff --git a/drivers/dma/pxp/pxp_device.c b/drivers/dma/pxp/pxp_device.c
index 74176d3da9d3..afd08ac6587c 100644
--- a/drivers/dma/pxp/pxp_device.c
+++ b/drivers/dma/pxp/pxp_device.c
@@ -132,6 +132,8 @@ static int pxp_ioc_config_chan(unsigned long arg)
init_waitqueue_head(&(irq_info[chan_id].waitq));
+ /* Fixme */
+ mdelay(100);
/* find the channel */
spin_lock(&pxp_chan_lock);
list_for_each_entry(info, &list, list) {
@@ -484,7 +486,7 @@ static int __devexit pxp_device_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver pxp_client_driver = {
+static struct platform_driver pxp_device = {
.probe = pxp_device_probe,
.remove = __exit_p(pxp_device_remove),
.driver = {
@@ -495,12 +497,12 @@ static struct platform_driver pxp_client_driver = {
static int __init pxp_device_init(void)
{
- return platform_driver_register(&pxp_client_driver);
+ return platform_driver_register(&pxp_device);
}
static void __exit pxp_device_exit(void)
{
- platform_driver_unregister(&pxp_client_driver);
+ platform_driver_unregister(&pxp_device);
}
module_init(pxp_device_init);
diff --git a/drivers/dma/pxp/pxp_dma.c b/drivers/dma/pxp/pxp_dma.c
index b8648049de89..e418f6c9715e 100644
--- a/drivers/dma/pxp/pxp_dma.c
+++ b/drivers/dma/pxp/pxp_dma.c
@@ -31,7 +31,6 @@
#include <linux/vmalloc.h>
#include <linux/dmaengine.h>
#include <linux/pxp_dma.h>
-#include <linux/timer.h>
#include <linux/clk.h>
#include "regs-pxp.h"
@@ -51,23 +50,16 @@ struct pxps {
int irq; /* PXP IRQ to the CPU */
spinlock_t lock;
- struct mutex mutex_clk;
- int clk_stat;
-#define CLK_STAT_OFF 0
-#define CLK_STAT_ON 1
+ struct mutex mutex;
struct device *dev;
struct pxp_dma pxp_dma;
struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
struct work_struct work;
struct workqueue_struct *workqueue;
- wait_queue_head_t done;
/* describes most recent processing configuration */
struct pxp_config_data pxp_conf_state;
-
- /* to turn clock off when pxp is inactive */
- struct timer_list clk_timer;
};
#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
@@ -78,9 +70,6 @@ struct pxps {
#define PXP_DEF_BUFS 2
#define PXP_MIN_PIX 8
-#define PXP_WAITCON ((__raw_readl(pxp->base + HW_PXP_STAT) & \
- BM_PXP_STAT_IRQ) != BM_PXP_STAT_IRQ)
-
static uint32_t pxp_s0_formats[] = {
PXP_PIX_FMT_RGB24,
PXP_PIX_FMT_RGB565,
@@ -94,76 +83,72 @@ static uint32_t pxp_s0_formats[] = {
*/
static void dump_pxp_reg(struct pxps *pxp)
{
- dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_CTRL));
- dev_dbg(pxp->dev, "PXP_STAT 0x%x",
+ dev_err(pxp->dev, "PXP_STAT 0x%x",
__raw_readl(pxp->base + HW_PXP_STAT));
- dev_dbg(pxp->dev, "PXP_OUTBUF 0x%x",
+ dev_err(pxp->dev, "PXP_OUTBUF 0x%x",
__raw_readl(pxp->base + HW_PXP_OUTBUF));
- dev_dbg(pxp->dev, "PXP_OUTBUF2 0x%x",
+ dev_err(pxp->dev, "PXP_OUTBUF2 0x%x",
__raw_readl(pxp->base + HW_PXP_OUTBUF2));
- dev_dbg(pxp->dev, "PXP_OUTSIZE 0x%x",
+ dev_err(pxp->dev, "PXP_OUTSIZE 0x%x",
__raw_readl(pxp->base + HW_PXP_OUTSIZE));
- dev_dbg(pxp->dev, "PXP_S0BUF 0x%x",
+ dev_err(pxp->dev, "PXP_S0BUF 0x%x",
__raw_readl(pxp->base + HW_PXP_S0BUF));
- dev_dbg(pxp->dev, "PXP_S0UBUF 0x%x",
+ dev_err(pxp->dev, "PXP_S0UBUF 0x%x",
__raw_readl(pxp->base + HW_PXP_S0UBUF));
- dev_dbg(pxp->dev, "PXP_S0VBUF 0x%x",
+ dev_err(pxp->dev, "PXP_S0VBUF 0x%x",
__raw_readl(pxp->base + HW_PXP_S0VBUF));
- dev_dbg(pxp->dev, "PXP_S0PARAM 0x%x",
+ dev_err(pxp->dev, "PXP_S0PARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_S0PARAM));
- dev_dbg(pxp->dev, "PXP_S0BACKGROUND 0x%x",
+ dev_err(pxp->dev, "PXP_S0BACKGROUND 0x%x",
__raw_readl(pxp->base + HW_PXP_S0BACKGROUND));
- dev_dbg(pxp->dev, "PXP_S0CROP 0x%x",
+ dev_err(pxp->dev, "PXP_S0CROP 0x%x",
__raw_readl(pxp->base + HW_PXP_S0CROP));
- dev_dbg(pxp->dev, "PXP_S0SCALE 0x%x",
+ dev_err(pxp->dev, "PXP_S0SCALE 0x%x",
__raw_readl(pxp->base + HW_PXP_S0SCALE));
- dev_dbg(pxp->dev, "PXP_OLn 0x%x",
+ dev_err(pxp->dev, "PXP_OLn 0x%x",
__raw_readl(pxp->base + HW_PXP_OLn(0)));
- dev_dbg(pxp->dev, "PXP_OLnSIZE 0x%x",
+ dev_err(pxp->dev, "PXP_OLnSIZE 0x%x",
__raw_readl(pxp->base + HW_PXP_OLnSIZE(0)));
- dev_dbg(pxp->dev, "PXP_OLnPARAM 0x%x",
+ dev_err(pxp->dev, "PXP_OLnPARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_OLnPARAM(0)));
- dev_dbg(pxp->dev, "PXP_CSCCOEF0 0x%x",
+ dev_err(pxp->dev, "PXP_CSCCOEF0 0x%x",
__raw_readl(pxp->base + HW_PXP_CSCCOEF0));
- dev_dbg(pxp->dev, "PXP_CSCCOEF1 0x%x",
- __raw_readl(pxp->base + HW_PXP_CSCCOEF1));
- dev_dbg(pxp->dev, "PXP_CSCCOEF2 0x%x",
- __raw_readl(pxp->base + HW_PXP_CSCCOEF2));
- dev_dbg(pxp->dev, "PXP_CSC2CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2CTRL));
- dev_dbg(pxp->dev, "PXP_CSC2COEF0 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF0 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF0));
- dev_dbg(pxp->dev, "PXP_CSC2COEF1 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF1 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF1));
- dev_dbg(pxp->dev, "PXP_CSC2COEF2 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF2 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF2));
- dev_dbg(pxp->dev, "PXP_CSC2COEF3 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF3 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF3));
- dev_dbg(pxp->dev, "PXP_CSC2COEF4 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF4 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF4));
- dev_dbg(pxp->dev, "PXP_CSC2COEF5 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF5 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF5));
- dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_LUT_CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_LUT_CTRL));
- dev_dbg(pxp->dev, "PXP_LUT 0x%x", __raw_readl(pxp->base + HW_PXP_LUT));
- dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_LUT 0x%x", __raw_readl(pxp->base + HW_PXP_LUT));
+ dev_err(pxp->dev, "PXP_HIST_CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST_CTRL));
- dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
+ dev_err(pxp->dev, "PXP_HIST2_PARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
- dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
+ dev_err(pxp->dev, "PXP_HIST4_PARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
- dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
+ dev_err(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
- dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
+ dev_err(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
}
@@ -268,7 +253,6 @@ static int pxp_start(struct pxps *pxp)
static void pxp_set_outbuf(struct pxps *pxp)
{
struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
struct pxp_layer_param *out_params = &pxp_conf->out_param;
__raw_writel(out_params->paddr, pxp->base + HW_PXP_OUTBUF);
@@ -340,7 +324,7 @@ static void pxp_set_olparam(int layer_no, struct pxps *pxp)
else
olparam |=
BF_PXP_OLnPARAM_FORMAT(BV_PXP_OLnPARAM_FORMAT__RGB565);
- if (olparams_data->global_alpha_enable)
+ if (olparams_data->global_alpha)
olparam |=
BF_PXP_OLnPARAM_ALPHA_CNTL
(BV_PXP_OLnPARAM_ALPHA_CNTL__Override);
@@ -493,9 +477,9 @@ static void pxp_set_csc(struct pxps *pxp)
*/
/* CSC1 - YUV->RGB */
- __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSCCOEF0);
- __raw_writel(0x01230204, pxp->base + HW_PXP_CSCCOEF1);
- __raw_writel(0x0730079c, pxp->base + HW_PXP_CSCCOEF2);
+ __raw_writel(0x04030000, pxp->base + HW_PXP_CSCCOEF0);
+ __raw_writel(0x01230208, pxp->base + HW_PXP_CSCCOEF1);
+ __raw_writel(0x076b079c, pxp->base + HW_PXP_CSCCOEF2);
/* CSC2 - Bypass */
__raw_writel(0x1, pxp->base + HW_PXP_CSC2CTRL);
@@ -596,43 +580,6 @@ static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
return 0;
}
-static void pxp_clk_enable(struct pxps *pxp)
-{
- mutex_lock(&pxp->mutex_clk);
-
- if (pxp->clk_stat == CLK_STAT_ON) {
- mutex_unlock(&pxp->mutex_clk);
- return;
- }
-
- clk_enable(pxp->clk);
- pxp->clk_stat = CLK_STAT_ON;
-
- mutex_unlock(&pxp->mutex_clk);
-}
-
-static void pxp_clk_disable(struct pxps *pxp)
-{
- mutex_lock(&pxp->mutex_clk);
-
- if (pxp->clk_stat == CLK_STAT_OFF) {
- mutex_unlock(&pxp->mutex_clk);
- return;
- }
-
- clk_disable(pxp->clk);
- pxp->clk_stat = CLK_STAT_OFF;
-
- mutex_unlock(&pxp->mutex_clk);
-}
-
-static void pxp_clkoff_timer(unsigned long arg)
-{
- struct pxps *pxp = (struct pxps *)arg;
-
- pxp_clk_disable(pxp);
-}
-
static struct pxp_tx_desc *pxpdma_first_active(struct pxp_channel *pxp_chan)
{
return list_entry(pxp_chan->active_list.next, struct pxp_tx_desc, list);
@@ -689,9 +636,13 @@ static void pxpdma_dostart_work(struct work_struct *w)
struct pxps *pxp = container_of(w, struct pxps, work);
struct pxp_channel *pxp_chan = NULL;
unsigned long flags, flags1;
+ int val;
- while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
- ;
+ val = __raw_readl(pxp->base + HW_PXP_CTRL);
+ if (val & BM_PXP_CTRL_ENABLE) {
+ pr_warning("pxp is active, quit.\n");
+ return;
+ }
spin_lock_irqsave(&pxp->lock, flags);
if (list_empty(&head)) {
@@ -813,7 +764,7 @@ static int pxp_init_channel(struct pxp_dma *pxp_dma,
spin_lock_irqsave(&pxp->lock, flags);
/* max desc nr: S0+OL+OUT = 1+8+1 */
- n_desc = 16;
+ n_desc = 10;
spin_unlock_irqrestore(&pxp->lock, flags);
@@ -844,38 +795,25 @@ static int pxp_uninit_channel(struct pxp_dma *pxp_dma,
static irqreturn_t pxp_irq(int irq, void *dev_id)
{
- struct pxps *pxp = dev_id;
- struct pxp_channel *pxp_chan;
+ struct pxp_channel *pxp_chan = dev_id;
+ struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
+ struct pxps *pxp = to_pxp(pxp_dma);
struct pxp_tx_desc *desc;
dma_async_tx_callback callback;
void *callback_param;
- unsigned long flags, flags1;
+ unsigned long flags;
u32 hist_status;
- dump_pxp_reg(pxp);
-
hist_status =
__raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
__raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
- mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(4000));
-
spin_lock_irqsave(&pxp->lock, flags);
- if (list_empty(&head)) {
- spin_unlock_irqrestore(&pxp->lock, flags);
- return IRQ_NONE;
- }
-
- spin_lock_irqsave(&pxp_chan->lock, flags1);
- pxp_chan = list_entry(head.next, struct pxp_channel, list);
- list_del_init(&pxp_chan->list);
-
if (list_empty(&pxp_chan->active_list)) {
pr_debug("PXP_IRQ pxp_chan->active_list empty. chan_id %d\n",
pxp_chan->dma_chan.chan_id);
- spin_unlock_irqrestore(&pxp_chan->lock, flags1);
spin_unlock_irqrestore(&pxp->lock, flags);
return IRQ_NONE;
}
@@ -901,11 +839,10 @@ static irqreturn_t pxp_irq(int irq, void *dev_id)
list_del(&pxp_chan->list);
- wake_up(&pxp->done);
-
- spin_unlock_irqrestore(&pxp_chan->lock, flags1);
spin_unlock_irqrestore(&pxp->lock, flags);
+ queue_work(pxp->workqueue, &pxp->work);
+
return IRQ_HANDLED;
}
@@ -1021,27 +958,17 @@ static void pxp_issue_pending(struct dma_chan *chan)
spin_lock_irqsave(&pxp->lock, flags0);
spin_lock_irqsave(&pxp_chan->lock, flags);
+ if (!list_empty(&pxp_chan->active_list))
+ queue_work(pxp->workqueue, &pxp->work);
if (!list_empty(&pxp_chan->queue)) {
pxpdma_dequeue(pxp_chan, &pxp_chan->active_list);
pxp_chan->status = PXP_CHANNEL_READY;
list_add_tail(&pxp_chan->list, &head);
- } else {
- spin_unlock_irqrestore(&pxp_chan->lock, flags);
- spin_unlock_irqrestore(&pxp->lock, flags0);
- return;
+ queue_work(pxp->workqueue, &pxp->work);
}
spin_unlock_irqrestore(&pxp_chan->lock, flags);
spin_unlock_irqrestore(&pxp->lock, flags0);
-
- pxp_clk_enable(pxp);
- if (!wait_event_interruptible_timeout(pxp->done, PXP_WAITCON, 2 * HZ) ||
- signal_pending(current)) {
- pxp_clk_disable(pxp);
- return;
- }
-
- queue_work(pxp->workqueue, &pxp->work);
}
static void __pxp_terminate_all(struct dma_chan *chan)
@@ -1089,6 +1016,11 @@ static int pxp_alloc_chan_resources(struct dma_chan *chan)
if (ret < 0)
goto err_chan;
+ ret = request_irq(pxp_chan->eof_irq, pxp_irq, IRQF_SHARED,
+ "pxp-irq", pxp_chan);
+ if (ret < 0)
+ goto err_irq;
+
pxp_chan->status = PXP_CHANNEL_INITIALIZED;
dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
@@ -1096,6 +1028,8 @@ static int pxp_alloc_chan_resources(struct dma_chan *chan)
return ret;
+err_irq:
+ pxp_uninit_channel(pxp_dma, pxp_chan);
err_chan:
return ret;
}
@@ -1113,6 +1047,8 @@ static void pxp_free_chan_resources(struct dma_chan *chan)
pxp_uninit_channel(pxp_dma, pxp_chan);
+ free_irq(pxp_chan->eof_irq, pxp_chan);
+
mutex_unlock(&pxp_chan->chan_mutex);
}
@@ -1315,7 +1251,7 @@ static int pxp_probe(struct platform_device *pdev)
pxp->irq = irq;
spin_lock_init(&pxp->lock);
- mutex_init(&pxp->mutex_clk);
+ mutex_init(&pxp->mutex);
if (!request_mem_region(res->start, resource_size(res), "pxp-mem")) {
err = -EBUSY;
@@ -1333,26 +1269,19 @@ static int pxp_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to initialize hardware\n");
goto release;
}
- clk_disable(pxp->clk);
- err = request_irq(pxp->irq, pxp_irq, 0, "pxp-irq", pxp);
- if (err)
- goto release;
/* Initialize DMA engine */
err = pxp_dma_init(pxp);
if (err < 0)
goto err_dma_init;
- init_waitqueue_head(&pxp->done);
INIT_WORK(&pxp->work, pxpdma_dostart_work);
pxp->workqueue = create_singlethread_workqueue("pxp_dma");
- init_timer(&pxp->clk_timer);
- pxp->clk_timer.function = pxp_clkoff_timer;
- pxp->clk_timer.data = (unsigned long)pxp;
exit:
return err;
err_dma_init:
free_irq(pxp->irq, pxp);
+ clk_disable(pxp->clk);
release:
release_mem_region(res->start, resource_size(res));
freepxp:
@@ -1366,8 +1295,8 @@ static int __devexit pxp_remove(struct platform_device *pdev)
struct pxps *pxp = platform_get_drvdata(pdev);
cancel_work_sync(&pxp->work);
+ kfree(pxp);
- del_timer_sync(&pxp->clk_timer);
free_irq(pxp->irq, pxp);
clk_disable(pxp->clk);
clk_put(pxp->clk);
@@ -1383,12 +1312,11 @@ static int pxp_suspend(struct platform_device *pdev, pm_message_t state)
{
struct pxps *pxp = platform_get_drvdata(pdev);
- pxp_clk_enable(pxp);
while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
;
__raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
- pxp_clk_disable(pxp);
+ clk_disable(pxp->clk);
return 0;
}
@@ -1397,10 +1325,9 @@ static int pxp_resume(struct platform_device *pdev)
{
struct pxps *pxp = platform_get_drvdata(pdev);
- pxp_clk_enable(pxp);
+ clk_enable(pxp->clk);
/* Pull PxP out of reset */
__raw_writel(0, pxp->base + HW_PXP_CTRL);
- pxp_clk_disable(pxp);
return 0;
}
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index d335086f4a26..0bd85eb99e6e 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -577,7 +577,13 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
- channel = branch;
+
+ /*
+ * According with i5000 datasheet, bit 28 has no significance
+ * for errors M4Err-M12Err and M17Err-M21Err, on FERR_NF_FBD
+ */
+ channel = branch & 2;
+
bank = NREC_BANK(info->nrecmema);
rank = NREC_RANK(info->nrecmema);
rdwr = NREC_RDWR(info->nrecmema);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 76b321bb73f9..e5827da92296 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2180,6 +2180,13 @@ static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
page = payload >> PAGE_SHIFT;
offset = payload & ~PAGE_MASK;
rest = p->payload_length;
+ /*
+ * The controllers I've tested have not worked correctly when
+ * second_req_count is zero. Rather than do something we know won't
+ * work, return an error
+ */
+ if (rest == 0)
+ return -EINVAL;
/* FIXME: make packet-per-buffer/dual-buffer a context option */
while (rest > 0) {
@@ -2233,7 +2240,7 @@ static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
unsigned long payload)
{
struct iso_context *ctx = container_of(base, struct iso_context, base);
- struct descriptor *d = NULL, *pd = NULL;
+ struct descriptor *d, *pd;
struct fw_iso_packet *p = packet;
dma_addr_t d_bus, page_bus;
u32 z, header_z, rest;
@@ -2271,8 +2278,9 @@ static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
rest = payload_per_buffer;
+ pd = d;
for (j = 1; j < z; j++) {
- pd = d + j;
+ pd++;
pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
DESCRIPTOR_INPUT_MORE);
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 39b393d38bb3..012cf1f7b8db 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -82,6 +82,7 @@ config DRM_I830
config DRM_I915
tristate "i915 driver"
depends on AGP_INTEL
+ select SHMEM
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7f2728bbc16c..55fb98d179ef 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -333,6 +333,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
mode->vsync_end = mode->vsync_start + vsync_pulse_width;
mode->vtotal = mode->vdisplay + vblank;
+ /* Some EDIDs have bogus h/vtotal values */
+ if (mode->hsync_end > mode->htotal)
+ mode->htotal = mode->hsync_end + 1;
+ if (mode->vsync_end > mode->vtotal)
+ mode->vtotal = mode->vsync_end + 1;
+
drm_mode_set_name(mode);
if (pt->misc & DRM_EDID_PT_INTERLACED)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index f85aaf21e783..f298434e87c7 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -402,15 +402,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Going from 0->1 means we have to enable interrupts again */
- if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
- !dev->vblank_enabled[crtc]) {
- ret = dev->driver->enable_vblank(dev, crtc);
- DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
- if (ret)
+ if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
+ if (!dev->vblank_enabled[crtc]) {
+ ret = dev->driver->enable_vblank(dev, crtc);
+ DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
+ if (ret)
+ atomic_dec(&dev->vblank_refcount[crtc]);
+ else {
+ dev->vblank_enabled[crtc] = 1;
+ drm_update_vblank_count(dev, crtc);
+ }
+ }
+ } else {
+ if (!dev->vblank_enabled[crtc]) {
atomic_dec(&dev->vblank_refcount[crtc]);
- else {
- dev->vblank_enabled[crtc] = 1;
- drm_update_vblank_count(dev, crtc);
+ ret = -EINVAL;
}
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -437,6 +443,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
}
EXPORT_SYMBOL(drm_vblank_put);
+void drm_vblank_off(struct drm_device *dev, int crtc)
+{
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ DRM_WAKEUP(&dev->vbl_queue[crtc]);
+ dev->vblank_enabled[crtc] = 0;
+ dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+}
+EXPORT_SYMBOL(drm_vblank_off);
+
/**
* drm_vblank_pre_modeset - account for vblanks across mode sets
* @dev: DRM device
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fc4b68aa2d05..c078d995aa91 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -94,8 +94,6 @@ static int i915_resume(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret = 0;
- pci_set_power_state(dev->pdev, PCI_D0);
- pci_restore_state(dev->pdev);
if (pci_enable_device(dev->pdev))
return -1;
pci_set_master(dev->pdev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5b4f87e55621..d3f365d8b6ef 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -264,6 +264,7 @@ typedef struct drm_i915_private {
u32 saveDSPASURF;
u32 saveDSPATILEOFF;
u32 savePFIT_PGM_RATIOS;
+ u32 saveBLC_HIST_CTL;
u32 saveBLC_PWM_CTL;
u32 saveBLC_PWM_CTL2;
u32 saveFPB0;
@@ -837,6 +838,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
#define IS_I855(dev) ((dev)->pci_device == 0x3582)
#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
+#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev))
#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
@@ -854,6 +856,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x2E12 || \
(dev)->pci_device == 0x2E22 || \
(dev)->pci_device == 0x2E32 || \
+ (dev)->pci_device == 0x2E42 || \
(dev)->pci_device == 0x0042 || \
(dev)->pci_device == 0x0046)
@@ -866,6 +869,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x2E12 || \
(dev)->pci_device == 0x2E22 || \
(dev)->pci_device == 0x2E32 || \
+ (dev)->pci_device == 0x2E42 || \
IS_GM45(dev))
#define IS_IGDG(dev) ((dev)->pci_device == 0xa001)
@@ -896,9 +900,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
*/
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
IS_I915GM(dev)))
+#define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_IGD(dev))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev))
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev))
#define SUPPORTS_EDP(dev) (IS_IGDNG_M(dev))
+#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \
+ !IS_IGDNG(dev) && !IS_IGD(dev))
#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
/* dsparb controlled by hw only */
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 80e5ba490dc2..2b7aeeed3990 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1151,27 +1151,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
mutex_lock(&dev->struct_mutex);
if (!obj_priv->gtt_space) {
ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
- return VM_FAULT_SIGBUS;
- }
-
- ret = i915_gem_object_set_to_gtt_domain(obj, write);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
- return VM_FAULT_SIGBUS;
- }
+ if (ret)
+ goto unlock;
list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
+
+ ret = i915_gem_object_set_to_gtt_domain(obj, write);
+ if (ret)
+ goto unlock;
}
/* Need a new fence register? */
if (obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
- return VM_FAULT_SIGBUS;
- }
+ if (ret)
+ goto unlock;
}
pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
@@ -1179,18 +1173,18 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
/* Finally, remap it using the new GTT offset */
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
+unlock:
mutex_unlock(&dev->struct_mutex);
switch (ret) {
+ case 0:
+ case -ERESTARTSYS:
+ return VM_FAULT_NOPAGE;
case -ENOMEM:
case -EAGAIN:
return VM_FAULT_OOM;
- case -EFAULT:
- case -EINVAL:
- return VM_FAULT_SIGBUS;
default:
- return VM_FAULT_NOPAGE;
+ return VM_FAULT_SIGBUS;
}
}
@@ -2506,16 +2500,6 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
if (obj_priv->pages == NULL)
return;
- /* XXX: The 865 in particular appears to be weird in how it handles
- * cache flushing. We haven't figured it out, but the
- * clflush+agp_chipset_flush doesn't appear to successfully get the
- * data visible to the PGU, while wbinvd + agp_chipset_flush does.
- */
- if (IS_I865G(obj->dev)) {
- wbinvd();
- return;
- }
-
drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE);
}
@@ -3007,6 +2991,16 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
return -EINVAL;
}
+ if (reloc->delta >= target_obj->size) {
+ DRM_ERROR("Relocation beyond target object bounds: "
+ "obj %p target %d delta %d size %d.\n",
+ obj, reloc->target_handle,
+ (int) reloc->delta, (int) target_obj->size);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
+ }
+
if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
reloc->read_domains & I915_GEM_DOMAIN_CPU) {
DRM_ERROR("reloc with read/write CPU domains: "
@@ -3837,7 +3831,8 @@ void i915_gem_free_object(struct drm_gem_object *obj)
i915_gem_object_unbind(obj);
- i915_gem_free_mmap_offset(obj);
+ if (obj_priv->mmap_offset)
+ i915_gem_free_mmap_offset(obj);
kfree(obj_priv->page_cpu_valid);
kfree(obj_priv->bit_17);
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index a2d527b22ec4..e774a4a1a503 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -234,7 +234,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
bool need_disable;
- if (!IS_I9XX(dev)) {
+ if (IS_IGDNG(dev)) {
+ /* On IGDNG whatever DRAM config, GPU always do
+ * same swizzling setup.
+ */
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+ swizzle_y = I915_BIT_6_SWIZZLE_9;
+ } else if (!IS_I9XX(dev)) {
/* As far as we know, the 865 doesn't have these bit 6
* swizzling issues.
*/
@@ -317,13 +323,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
}
}
- /* FIXME: check with memory config on IGDNG */
- if (IS_IGDNG(dev)) {
- DRM_ERROR("disable tiling on IGDNG...\n");
- swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
- swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- }
-
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7ebc84c2881e..9431a727a985 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -253,10 +253,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = IRQ_NONE;
- u32 de_iir, gt_iir;
+ u32 de_iir, gt_iir, de_ier;
u32 new_de_iir, new_gt_iir;
struct drm_i915_master_private *master_priv;
+ /* disable master interrupt before clearing iir */
+ de_ier = I915_READ(DEIER);
+ I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
+ (void)I915_READ(DEIER);
+
de_iir = I915_READ(DEIIR);
gt_iir = I915_READ(GTIIR);
@@ -287,6 +292,9 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
gt_iir = new_gt_iir;
}
+ I915_WRITE(DEIER, de_ier);
+ (void)I915_READ(DEIER);
+
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2955083aa471..9917749afb32 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -915,6 +915,8 @@
#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
+#define BLC_HIST_CTL 0x61260
+
/* TV port control */
#define TV_CTL 0x68000
/** Enables the TV encoder */
@@ -1616,6 +1618,11 @@
#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0)
+#define PIPE_BPC_MASK (7 << 5) /* Ironlake */
+#define PIPE_8BPC (0 << 5)
+#define PIPE_10BPC (1 << 5)
+#define PIPE_6BPC (2 << 5)
+#define PIPE_12BPC (3 << 5)
#define DSPARB 0x70030
#define DSPARB_CSTART_MASK (0x7f << 7)
@@ -1733,6 +1740,7 @@
#define DISPPLANE_NO_LINE_DOUBLE 0
#define DISPPLANE_STEREO_POLARITY_FIRST 0
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* IGDNG */
#define DISPPLANE_TILED (1<<10)
#define DSPAADDR 0x70184
#define DSPASTRIDE 0x70188
@@ -1865,8 +1873,15 @@
#define PFA_CTL_1 0x68080
#define PFB_CTL_1 0x68880
#define PF_ENABLE (1<<31)
+#define PF_FILTER_MASK (3<<23)
+#define PF_FILTER_PROGRAMMED (0<<23)
+#define PF_FILTER_MED_3x3 (1<<23)
+#define PF_FILTER_EDGE_ENHANCE (2<<23)
+#define PF_FILTER_EDGE_SOFTEN (3<<23)
#define PFA_WIN_SZ 0x68074
#define PFB_WIN_SZ 0x68874
+#define PFA_WIN_POS 0x68070
+#define PFB_WIN_POS 0x68870
/* legacy palette */
#define LGC_PALETTE_A 0x4a000
@@ -1913,6 +1928,9 @@
#define GTIIR 0x44018
#define GTIER 0x4401c
+#define DISP_ARB_CTL 0x45000
+#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
+
/* PCH */
/* south display engine interrupt */
@@ -1979,11 +1997,11 @@
#define DREF_CPU_SOURCE_OUTPUT_MASK (3<<13)
#define DREF_SSC_SOURCE_DISABLE (0<<11)
#define DREF_SSC_SOURCE_ENABLE (2<<11)
-#define DREF_SSC_SOURCE_MASK (2<<11)
+#define DREF_SSC_SOURCE_MASK (3<<11)
#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9)
#define DREF_NONSPREAD_CK505_ENABLE (1<<9)
#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9)
-#define DREF_NONSPREAD_SOURCE_MASK (2<<9)
+#define DREF_NONSPREAD_SOURCE_MASK (3<<9)
#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7)
#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7)
#define DREF_SSC4_DOWNSPREAD (0<<6)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 1d04e1904ac6..2e4aca658b8b 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -416,6 +416,7 @@ int i915_save_state(struct drm_device *dev)
dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+ dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
if (IS_I965G(dev))
dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
if (IS_MOBILE(dev) && !IS_I830(dev))
@@ -560,6 +561,7 @@ int i915_restore_state(struct drm_device *dev)
I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+ I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL);
I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index f806fcc54e09..698a0edf0ea9 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -217,6 +217,9 @@ parse_general_features(struct drm_i915_private *dev_priv,
if (IS_I85X(dev_priv->dev))
dev_priv->lvds_ssc_freq =
general->ssc_freq ? 66 : 48;
+ else if (IS_IGDNG(dev_priv->dev))
+ dev_priv->lvds_ssc_freq =
+ general->ssc_freq ? 100 : 120;
else
dev_priv->lvds_ssc_freq =
general->ssc_freq ? 100 : 96;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 590f81c8f594..046027fa9731 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -151,13 +151,10 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 adpa, temp;
+ u32 adpa;
bool ret;
- temp = adpa = I915_READ(PCH_ADPA);
-
- adpa &= ~ADPA_DAC_ENABLE;
- I915_WRITE(PCH_ADPA, adpa);
+ adpa = I915_READ(PCH_ADPA);
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
@@ -184,8 +181,6 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
else
ret = false;
- /* restore origin register */
- I915_WRITE(PCH_ADPA, temp);
return ret;
}
@@ -239,8 +234,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
} while (time_after(timeout, jiffies));
}
- if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
- CRT_HOTPLUG_MONITOR_COLOR)
+ if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
+ CRT_HOTPLUG_MONITOR_NONE)
return true;
return false;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 748ed50c55ca..3ac3b7c49869 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -818,7 +818,7 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
refclk, best_clock);
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
- if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+ if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
LVDS_CLKB_POWER_UP)
clock.p2 = limit->p2.p2_fast;
else
@@ -1008,6 +1008,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
dspcntr &= ~DISPPLANE_TILED;
}
+ if (IS_IGDNG(dev))
+ /* must disable */
+ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
@@ -1154,6 +1158,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
+ int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS;
int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
@@ -1177,6 +1182,15 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
DRM_DEBUG("crtc %d dpms on\n", pipe);
+
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+ temp = I915_READ(PCH_LVDS);
+ if ((temp & LVDS_PORT_EN) == 0) {
+ I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
+ POSTING_READ(PCH_LVDS);
+ }
+ }
+
if (HAS_eDP) {
/* enable eDP PLL */
igdng_enable_pll_edp(crtc);
@@ -1205,6 +1219,19 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
}
}
+ /* Enable panel fitting for LVDS */
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+ temp = I915_READ(pf_ctl_reg);
+ I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
+
+ /* currently full aspect */
+ I915_WRITE(pf_win_pos, 0);
+
+ I915_WRITE(pf_win_size,
+ (dev_priv->panel_fixed_mode->hdisplay << 16) |
+ (dev_priv->panel_fixed_mode->vdisplay));
+ }
+
/* Enable CPU pipe */
temp = I915_READ(pipeconf_reg);
if ((temp & PIPEACONF_ENABLE) == 0) {
@@ -1348,8 +1375,6 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_OFF:
DRM_DEBUG("crtc %d dpms off\n", pipe);
- i915_disable_vga(dev);
-
/* Disable display plane */
temp = I915_READ(dspcntr_reg);
if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
@@ -1359,6 +1384,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_READ(dspbase_reg);
}
+ i915_disable_vga(dev);
+
/* disable cpu pipe, disable after all planes disabled */
temp = I915_READ(pipeconf_reg);
if ((temp & PIPEACONF_ENABLE) != 0) {
@@ -1379,9 +1406,15 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
} else
DRM_DEBUG("crtc %d is disabled\n", pipe);
- if (HAS_eDP) {
- igdng_disable_pll_edp(crtc);
+ udelay(100);
+
+ /* Disable PF */
+ temp = I915_READ(pf_ctl_reg);
+ if ((temp & PF_ENABLE) != 0) {
+ I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
+ I915_READ(pf_ctl_reg);
}
+ I915_WRITE(pf_win_size, 0);
/* disable CPU FDI tx and PCH FDI rx */
temp = I915_READ(fdi_tx_reg);
@@ -1407,6 +1440,13 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
udelay(100);
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+ temp = I915_READ(PCH_LVDS);
+ I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
+ I915_READ(PCH_LVDS);
+ udelay(100);
+ }
+
/* disable PCH transcoder */
temp = I915_READ(transconf_reg);
if ((temp & TRANS_ENABLE) != 0) {
@@ -1426,6 +1466,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
}
}
+ udelay(100);
+
/* disable PCH DPLL */
temp = I915_READ(pch_dpll_reg);
if ((temp & DPLL_VCO_ENABLE) != 0) {
@@ -1433,14 +1475,20 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_READ(pch_dpll_reg);
}
- temp = I915_READ(fdi_rx_reg);
- if ((temp & FDI_RX_PLL_ENABLE) != 0) {
- temp &= ~FDI_SEL_PCDCLK;
- temp &= ~FDI_RX_PLL_ENABLE;
- I915_WRITE(fdi_rx_reg, temp);
- I915_READ(fdi_rx_reg);
+ if (HAS_eDP) {
+ igdng_disable_pll_edp(crtc);
}
+ temp = I915_READ(fdi_rx_reg);
+ temp &= ~FDI_SEL_PCDCLK;
+ I915_WRITE(fdi_rx_reg, temp);
+ I915_READ(fdi_rx_reg);
+
+ temp = I915_READ(fdi_rx_reg);
+ temp &= ~FDI_RX_PLL_ENABLE;
+ I915_WRITE(fdi_rx_reg, temp);
+ I915_READ(fdi_rx_reg);
+
/* Disable CPU FDI TX PLL */
temp = I915_READ(fdi_tx_reg);
if ((temp & FDI_TX_PLL_ENABLE) != 0) {
@@ -1449,16 +1497,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
udelay(100);
}
- /* Disable PF */
- temp = I915_READ(pf_ctl_reg);
- if ((temp & PF_ENABLE) != 0) {
- I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
- I915_READ(pf_ctl_reg);
- }
- I915_WRITE(pf_win_size, 0);
-
/* Wait for the clocks to turn off. */
- udelay(150);
+ udelay(100);
break;
}
}
@@ -1522,6 +1562,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
intel_update_watermarks(dev);
/* Give the overlay scaler a chance to disable if it's on this pipe */
//intel_crtc_dpms_video(crtc, FALSE); TODO
+ drm_vblank_off(dev, pipe);
/* Disable the VGA plane that we never use */
i915_disable_vga(dev);
@@ -1746,7 +1787,7 @@ fdi_reduce_ratio(u32 *num, u32 *den)
#define LINK_N 0x80000
static void
-igdng_compute_m_n(int bytes_per_pixel, int nlanes,
+igdng_compute_m_n(int bits_per_pixel, int nlanes,
int pixel_clock, int link_clock,
struct fdi_m_n *m_n)
{
@@ -1756,7 +1797,8 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes,
temp = (u64) DATA_N * pixel_clock;
temp = div_u64(temp, link_clock);
- m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes);
+ m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes);
+ m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
m_n->gmch_n = DATA_N;
fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
@@ -1858,7 +1900,14 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
{
long entries_required, wm_size;
- entries_required = (clock_in_khz * pixel_size * latency_ns) / 1000000;
+ /*
+ * Note: we need to make sure we don't overflow for various clock &
+ * latency values.
+ * clocks go from a few thousand to several hundred thousand.
+ * latency is usually a few thousand
+ */
+ entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
+ 1000;
entries_required /= wm->cacheline_size;
DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required);
@@ -2371,7 +2420,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* FDI link */
if (IS_IGDNG(dev)) {
- int lane, link_bw;
+ int lane, link_bw, bpp;
/* eDP doesn't require FDI link, so just set DP M/N
according to current link config */
if (is_edp) {
@@ -2390,10 +2439,72 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
lane = 4;
link_bw = 270000;
}
- igdng_compute_m_n(3, lane, target_clock,
+
+ /* determine panel color depth */
+ temp = I915_READ(pipeconf_reg);
+
+ switch (temp & PIPE_BPC_MASK) {
+ case PIPE_8BPC:
+ bpp = 24;
+ break;
+ case PIPE_10BPC:
+ bpp = 30;
+ break;
+ case PIPE_6BPC:
+ bpp = 18;
+ break;
+ case PIPE_12BPC:
+ bpp = 36;
+ break;
+ default:
+ DRM_ERROR("unknown pipe bpc value\n");
+ bpp = 24;
+ }
+
+ igdng_compute_m_n(bpp, lane, target_clock,
link_bw, &m_n);
}
+ /* Ironlake: try to setup display ref clock before DPLL
+ * enabling. This is only under driver's control after
+ * PCH B stepping, previous chipset stepping should be
+ * ignoring this setting.
+ */
+ if (IS_IGDNG(dev)) {
+ temp = I915_READ(PCH_DREF_CONTROL);
+ /* Always enable nonspread source */
+ temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+ temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+
+ temp &= ~DREF_SSC_SOURCE_MASK;
+ temp |= DREF_SSC_SOURCE_ENABLE;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+
+ udelay(200);
+
+ if (is_edp) {
+ if (dev_priv->lvds_use_ssc) {
+ temp |= DREF_SSC1_ENABLE;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+
+ udelay(200);
+
+ temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+ temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ } else {
+ temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ }
+ }
+ }
+
if (IS_IGD(dev))
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
else
@@ -2616,6 +2727,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
intel_wait_for_vblank(dev);
+ if (IS_IGDNG(dev)) {
+ /* enable address swizzle for tiling buffer */
+ temp = I915_READ(DISP_ARB_CTL);
+ I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
+ }
+
I915_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */
@@ -3231,7 +3348,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_DP_D) & DP_DETECTED)
intel_dp_init(dev, PCH_DP_D);
- } else if (IS_I9XX(dev)) {
+ } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
bool found = false;
if (I915_READ(SDVOB) & SDVO_DETECTED) {
@@ -3258,10 +3375,10 @@ static void intel_setup_outputs(struct drm_device *dev)
if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
intel_dp_init(dev, DP_D);
- } else
+ } else if (IS_I8XX(dev))
intel_dvo_init(dev);
- if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev))
+ if (SUPPORTS_TV(dev))
intel_tv_init(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 1d30802e773e..75a9b83fd7d3 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -114,7 +114,7 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
struct drm_framebuffer *fb = &intel_fb->base;
int depth;
- if (var->pixclock == -1 || !var->pixclock)
+ if (var->pixclock != 0)
return -EINVAL;
/* Need to resize the fb object !!! */
@@ -205,7 +205,7 @@ static int intelfb_set_par(struct fb_info *info)
DRM_DEBUG("%d %d\n", var->xres, var->pixclock);
- if (var->pixclock != -1) {
+ if (var->pixclock != 0) {
DRM_ERROR("PIXEL CLOCK SET\n");
return -EINVAL;
@@ -692,7 +692,7 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *
par->crtc_count = 1;
if (new_fb) {
- info->var.pixclock = -1;
+ info->var.pixclock = 0;
if (register_framebuffer(info) < 0)
return -EINVAL;
} else
@@ -846,7 +846,7 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
par->crtc_count = crtc_count;
if (new_fb) {
- info->var.pixclock = -1;
+ info->var.pixclock = 0;
if (register_framebuffer(info) < 0)
return -EINVAL;
} else
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 8df02ef89261..b7d091ba8c5c 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -305,6 +305,10 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
goto out;
}
+ /* full screen scale for now */
+ if (IS_IGDNG(dev))
+ goto out;
+
/* 965+ wants fuzzy fitting */
if (IS_I965G(dev))
pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
@@ -332,8 +336,10 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
* to register description and PRM.
* Change the value here to see the borders for debugging
*/
- I915_WRITE(BCLRPAT_A, 0);
- I915_WRITE(BCLRPAT_B, 0);
+ if (!IS_IGDNG(dev)) {
+ I915_WRITE(BCLRPAT_A, 0);
+ I915_WRITE(BCLRPAT_B, 0);
+ }
switch (lvds_priv->fitting_mode) {
case DRM_MODE_SCALE_NO_SCALE:
@@ -582,7 +588,6 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
* settings.
*/
- /* No panel fitting yet, fixme */
if (IS_IGDNG(dev))
return;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d3b74ba62b4a..66dc1a54cbf6 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -114,6 +114,9 @@ struct intel_sdvo_priv {
/* DDC bus used by this SDVO output */
uint8_t ddc_bus;
+ /* Mac mini hack -- use the same DDC as the analog connector */
+ struct i2c_adapter *analog_ddc_bus;
+
int save_sdvo_mult;
u16 save_active_outputs;
struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
@@ -1478,6 +1481,36 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
return (caps > 1);
}
+static struct drm_connector *
+intel_find_analog_connector(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+ struct intel_output *intel_output;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ intel_output = to_intel_output(connector);
+ if (intel_output->type == INTEL_OUTPUT_ANALOG)
+ return connector;
+ }
+ return NULL;
+}
+
+static int
+intel_analog_is_connected(struct drm_device *dev)
+{
+ struct drm_connector *analog_connector;
+ analog_connector = intel_find_analog_connector(dev);
+
+ if (!analog_connector)
+ return false;
+
+ if (analog_connector->funcs->detect(analog_connector) ==
+ connector_status_disconnected)
+ return false;
+
+ return true;
+}
+
enum drm_connector_status
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
{
@@ -1488,6 +1521,15 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
edid = drm_get_edid(&intel_output->base,
intel_output->ddc_bus);
+
+ /* when there is no edid and no monitor is connected with VGA
+ * port, try to use the CRT ddc to read the EDID for DVI-connector
+ */
+ if (edid == NULL &&
+ sdvo_priv->analog_ddc_bus &&
+ !intel_analog_is_connected(intel_output->base.dev))
+ edid = drm_get_edid(&intel_output->base,
+ sdvo_priv->analog_ddc_bus);
if (edid != NULL) {
/* Don't report the output as connected if it's a DVI-I
* connector with a non-digital EDID coming out.
@@ -1540,31 +1582,32 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ int num_modes;
/* set the bus switch and get the modes */
- intel_ddc_get_modes(intel_output);
+ num_modes = intel_ddc_get_modes(intel_output);
-#if 0
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- /* Mac mini hack. On this device, I get DDC through the analog, which
- * load-detects as disconnected. I fail to DDC through the SDVO DDC,
- * but it does load-detect as connected. So, just steal the DDC bits
- * from analog when we fail at finding it the right way.
+ /*
+ * Mac mini hack. On this device, the DVI-I connector shares one DDC
+ * link between analog and digital outputs. So, if the regular SDVO
+ * DDC fails, check to see if the analog output is disconnected, in
+ * which case we'll look there for the digital DDC data.
*/
- crt = xf86_config->output[0];
- intel_output = crt->driver_private;
- if (intel_output->type == I830_OUTPUT_ANALOG &&
- crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
- I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A");
- edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus);
- xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true);
- }
- if (edid_mon) {
- xf86OutputSetEDID(output, edid_mon);
- modes = xf86OutputGetEDIDModes(output);
+ if (num_modes == 0 &&
+ sdvo_priv->analog_ddc_bus &&
+ !intel_analog_is_connected(intel_output->base.dev)) {
+ struct i2c_adapter *digital_ddc_bus;
+
+ /* Switch to the analog ddc bus and try that
+ */
+ digital_ddc_bus = intel_output->ddc_bus;
+ intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
+
+ (void) intel_ddc_get_modes(intel_output);
+
+ intel_output->ddc_bus = digital_ddc_bus;
}
-#endif
}
/**
@@ -1748,6 +1791,8 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
intel_i2c_destroy(intel_output->i2c_bus);
if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus);
+ if (sdvo_priv->analog_ddc_bus)
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
drm_mode_destroy(connector->dev,
@@ -2074,10 +2119,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
}
/* setup the DDC bus. */
- if (output_device == SDVOB)
+ if (output_device == SDVOB) {
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
- else
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVOB/VGA DDC BUS");
+ } else {
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVOC/VGA DDC BUS");
+ }
if (intel_output->ddc_bus == NULL)
goto err_i2c;
@@ -2143,6 +2193,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
return true;
err_i2c:
+ if (sdvo_priv->analog_ddc_bus != NULL)
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
if (intel_output->ddc_bus != NULL)
intel_i2c_destroy(intel_output->ddc_bus);
if (intel_output->i2c_bus != NULL)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 5b1c9e9fdba0..05f6fe40f2e3 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1212,20 +1212,17 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
tv_ctl |= TV_TRILEVEL_SYNC;
if (tv_mode->pal_burst)
tv_ctl |= TV_PAL_BURST;
+
scctl1 = 0;
- /* dda1 implies valid video levels */
- if (tv_mode->dda1_inc) {
+ if (tv_mode->dda1_inc)
scctl1 |= TV_SC_DDA1_EN;
- }
-
if (tv_mode->dda2_inc)
scctl1 |= TV_SC_DDA2_EN;
-
if (tv_mode->dda3_inc)
scctl1 |= TV_SC_DDA3_EN;
-
scctl1 |= tv_mode->sc_reset;
- scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
+ if (video_levels)
+ scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index c75fd3564040..ebf9f63e5d49 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -353,6 +353,11 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
DRM_DEBUG("\n");
+ if (dev->dev_private) {
+ DRM_DEBUG("called when already initialized\n");
+ return -EINVAL;
+ }
+
dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
@@ -649,6 +654,8 @@ int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_pri
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
DRM_DEBUG("while CCE running\n");
return 0;
@@ -671,6 +678,8 @@ int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
/* Flush any pending CCE commands. This ensures any outstanding
* commands are exectuted by the engine before we turn it off.
*/
@@ -708,10 +717,7 @@ int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_pri
LOCK_TEST_WITH_RETURN(dev, file_priv);
- if (!dev_priv) {
- DRM_DEBUG("called before init done\n");
- return -EINVAL;
- }
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
r128_do_cce_reset(dev_priv);
@@ -728,6 +734,8 @@ int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
if (dev_priv->cce_running) {
r128_do_cce_flush(dev_priv);
}
@@ -741,6 +749,8 @@ int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev->dev_private);
+
return r128_do_engine_reset(dev);
}
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 797a26c42dab..3c60829d82e9 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -422,6 +422,14 @@ static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
* Misc helper macros
*/
+#define DEV_INIT_TEST_WITH_RETURN(_dev_priv) \
+do { \
+ if (!_dev_priv) { \
+ DRM_ERROR("called with no initialization\n"); \
+ return -EINVAL; \
+ } \
+} while (0)
+
#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
do { \
drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 026a48c95c8f..af2665cf4718 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1244,14 +1244,18 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_r128_private_t *dev_priv = dev->dev_private;
- drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_sarea_t *sarea_priv;
drm_r128_clear_t *clear = data;
DRM_DEBUG("\n");
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ sarea_priv = dev_priv->sarea_priv;
+
if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
@@ -1312,6 +1316,8 @@ static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *fi
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
RING_SPACE_TEST_WITH_RETURN(dev_priv);
if (!dev_priv->page_flipping)
@@ -1331,6 +1337,8 @@ static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *fi
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
RING_SPACE_TEST_WITH_RETURN(dev_priv);
if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
@@ -1354,10 +1362,7 @@ static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *
LOCK_TEST_WITH_RETURN(dev, file_priv);
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return -EINVAL;
- }
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
@@ -1410,10 +1415,7 @@ static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file
LOCK_TEST_WITH_RETURN(dev, file_priv);
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return -EINVAL;
- }
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
elts->idx, elts->start, elts->end, elts->discard);
@@ -1476,6 +1478,8 @@ static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *fi
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
if (blit->idx < 0 || blit->idx >= dma->buf_count) {
@@ -1501,6 +1505,8 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
RING_SPACE_TEST_WITH_RETURN(dev_priv);
ret = -EINVAL;
@@ -1531,6 +1537,8 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file
LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
+
if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
return -EFAULT;
@@ -1555,10 +1563,7 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file
LOCK_TEST_WITH_RETURN(dev, file_priv);
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return -EINVAL;
- }
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
indirect->idx, indirect->start, indirect->end,
@@ -1620,10 +1625,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
drm_r128_getparam_t *param = data;
int value;
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return -EINVAL;
- }
+ DEV_INIT_TEST_WITH_RETURN(dev_priv);
DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index fcfe5c02d744..7bae834df0ca 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -134,6 +134,14 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
}
}
+ /* HIS X1300 is DVI+VGA, not DVI+DVI */
+ if ((dev->pdev->device == 0x7146) &&
+ (dev->pdev->subsystem_vendor == 0x17af) &&
+ (dev->pdev->subsystem_device == 0x2058)) {
+ if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
+ return false;
+ }
+
/* Funky macbooks */
if ((dev->pdev->device == 0x71C5) &&
(dev->pdev->subsystem_vendor == 0x106b) &&
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index ec383edf5f38..f1d6d3d4519f 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -120,7 +120,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
struct drm_framebuffer *fb = &rfb->base;
int depth;
- if (var->pixclock == -1 || !var->pixclock) {
+ if (var->pixclock != 0) {
return -EINVAL;
}
/* Need to resize the fb object !!! */
@@ -234,7 +234,7 @@ static int radeonfb_set_par(struct fb_info *info)
int ret;
int i;
- if (var->pixclock != -1) {
+ if (var->pixclock != 0) {
DRM_ERROR("PIXEL CLCOK SET\n");
return -EINVAL;
}
@@ -828,7 +828,7 @@ static int radeonfb_single_fb_probe(struct radeon_device *rdev)
rfbdev->crtc_count = crtc_count;
if (new_fb) {
- info->var.pixclock = -1;
+ info->var.pixclock = 0;
if (register_framebuffer(info) < 0)
return -EINVAL;
} else {
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 0da72f18fd3a..ff9c18d07925 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -291,8 +291,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
uint32_t mask;
if (radeon_crtc->crtc_id)
- mask = (RADEON_CRTC2_EN |
- RADEON_CRTC2_DISP_DIS |
+ mask = (RADEON_CRTC2_DISP_DIS |
RADEON_CRTC2_VSYNC_DIS |
RADEON_CRTC2_HSYNC_DIS |
RADEON_CRTC2_DISP_REQ_EN_B);
@@ -304,7 +303,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
switch (mode) {
case DRM_MODE_DPMS_ON:
if (radeon_crtc->crtc_id)
- WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask);
+ WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask));
else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B));
@@ -318,7 +317,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_OFF:
drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
if (radeon_crtc->crtc_id)
- WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
+ WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask));
else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B));
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 303ccce05bb3..637867e94c9c 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -431,6 +431,13 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_ISO_KEYBOARD },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5eb10c2ce665..c0537218d9c1 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1259,6 +1259,9 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_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) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
@@ -1319,7 +1322,6 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
{ }
};
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 630101037921..bee718f8714e 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -88,6 +88,9 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index 1852f27bac51..14f910d3dd9b 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -97,7 +97,7 @@ I2C_CLIENT_INSMOD_1(adt7462);
#define ADT7462_PIN24_SHIFT 6
#define ADT7462_PIN26_VOLT_INPUT 0x08
#define ADT7462_PIN25_VOLT_INPUT 0x20
-#define ADT7462_PIN28_SHIFT 6 /* cfg3 */
+#define ADT7462_PIN28_SHIFT 4 /* cfg3 */
#define ADT7462_PIN28_VOLT 0x5
#define ADT7462_REG_ALARM1 0xB8
@@ -182,7 +182,7 @@ I2C_CLIENT_INSMOD_1(adt7462);
*
* Some, but not all, of these voltages have low/high limits.
*/
-#define ADT7462_VOLT_COUNT 12
+#define ADT7462_VOLT_COUNT 13
#define ADT7462_VENDOR 0x41
#define ADT7462_DEVICE 0x62
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index d39877a7da63..20579fad4a24 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -350,8 +350,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
case FAULT:
/* Note - only for remote1 and remote2 */
- out = data->alarms & (sattr->index ? 0x8000 : 0x4000);
- out = out ? 0 : 1;
+ out = !!(data->alarms & (sattr->index ? 0x8000 : 0x4000));
break;
default:
@@ -1152,7 +1151,7 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
}
/* Limits and settings, should never change update every 60 seconds */
- if (time_after(jiffies, data->limits_updated + HZ * 2) ||
+ if (time_after(jiffies, data->limits_updated + HZ * 60) ||
!data->valid) {
data->config5 = adt7475_read(REG_CONFIG5);
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 93c17223b527..2b8f439794b9 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -191,7 +191,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
if (err) {
dev_warn(dev,
"Unable to access MSR 0xEE, for Tjmax, left"
- " at default");
+ " at default\n");
} else if (eax & 0x40000000) {
tjmax = 85000;
}
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index ea955edde87e..3e51d54b60f4 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -767,6 +767,7 @@ leave:
static int watchdog_open(struct inode *inode, struct file *filp)
{
struct fschmd_data *pos, *data = NULL;
+ int watchdog_is_open;
/* We get called from drivers/char/misc.c with misc_mtx hold, and we
call misc_register() from fschmd_probe() with watchdog_data_mutex
@@ -781,10 +782,12 @@ static int watchdog_open(struct inode *inode, struct file *filp)
}
}
/* Note we can never not have found data, so we don't check for this */
- kref_get(&data->kref);
+ watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
+ if (!watchdog_is_open)
+ kref_get(&data->kref);
mutex_unlock(&watchdog_data_mutex);
- if (test_and_set_bit(0, &data->watchdog_is_open))
+ if (watchdog_is_open)
return -EBUSY;
/* Start the watchdog */
@@ -819,7 +822,7 @@ static int watchdog_release(struct inode *inode, struct file *filp)
static ssize_t watchdog_write(struct file *filp, const char __user *buf,
size_t count, loff_t *offset)
{
- size_t ret;
+ int ret;
struct fschmd_data *data = filp->private_data;
if (count) {
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 9157247fed8e..231a6a5d6d70 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1028,12 +1028,11 @@ static int __init it87_find(unsigned short *address,
chip_type, *address, sio_data->revision);
/* Read GPIO config and VID value from LDN 7 (GPIO) */
- if (chip_type != IT8705F_DEVID) {
+ if (sio_data->type != it87) {
int reg;
superio_select(GPIO);
- if ((chip_type == it8718) ||
- (chip_type == it8720))
+ if (sio_data->type == it8718 || sio_data->type == it8720)
sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
reg = superio_inb(IT87_SIO_PINX2_REG);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index a1787fdf5b9f..2348622b533c 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -870,17 +870,16 @@ static struct lm78_data *lm78_update_device(struct device *dev)
static int __init lm78_isa_found(unsigned short address)
{
int val, save, found = 0;
-
- /* We have to request the region in two parts because some
- boards declare base+4 to base+7 as a PNP device */
- if (!request_region(address, 4, "lm78")) {
- pr_debug("lm78: Failed to request low part of region\n");
- return 0;
- }
- if (!request_region(address + 4, 4, "lm78")) {
- pr_debug("lm78: Failed to request high part of region\n");
- release_region(address, 4);
- return 0;
+ int port;
+
+ /* Some boards declare base+0 to base+7 as a PNP device, some base+4
+ * to base+7 and some base+5 to base+6. So we better request each port
+ * individually for the probing phase. */
+ for (port = address; port < address + LM78_EXTENT; port++) {
+ if (!request_region(port, 1, "lm78")) {
+ pr_debug("lm78: Failed to request port 0x%x\n", port);
+ goto release;
+ }
}
#define REALLY_SLOW_IO
@@ -944,8 +943,8 @@ static int __init lm78_isa_found(unsigned short address)
val & 0x80 ? "LM79" : "LM78", (int)address);
release:
- release_region(address + 4, 4);
- release_region(address, 4);
+ for (port--; port >= address; port--)
+ release_region(port, 1);
return found;
}
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 6290a259456e..e828d17e9318 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -304,7 +304,7 @@ static inline int sht15_calc_temp(struct sht15_data *data)
int d1 = 0;
int i;
- for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++)
+ for (i = 1; i < ARRAY_SIZE(temppoints); i++)
/* Find pointer to interpolate */
if (data->supply_uV > temppoints[i - 1].vdd) {
d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd)
@@ -331,12 +331,12 @@ static inline int sht15_calc_humid(struct sht15_data *data)
const int c1 = -4;
const int c2 = 40500; /* x 10 ^ -6 */
- const int c3 = 2800; /* x10 ^ -9 */
+ const int c3 = -2800; /* x10 ^ -9 */
RHlinear = c1*1000
+ c2 * data->val_humid/1000
+ (data->val_humid * data->val_humid * c3)/1000000;
- return (temp - 25000) * (10000 + 800 * data->val_humid)
+ return (temp - 25000) * (10000 + 80 * data->val_humid)
/ 1000000 + RHlinear;
}
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 0bdab959b736..3c237004b1ca 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1818,17 +1818,17 @@ static int __init
w83781d_isa_found(unsigned short address)
{
int val, save, found = 0;
-
- /* We have to request the region in two parts because some
- boards declare base+4 to base+7 as a PNP device */
- if (!request_region(address, 4, "w83781d")) {
- pr_debug("w83781d: Failed to request low part of region\n");
- return 0;
- }
- if (!request_region(address + 4, 4, "w83781d")) {
- pr_debug("w83781d: Failed to request high part of region\n");
- release_region(address, 4);
- return 0;
+ int port;
+
+ /* Some boards declare base+0 to base+7 as a PNP device, some base+4
+ * to base+7 and some base+5 to base+6. So we better request each port
+ * individually for the probing phase. */
+ for (port = address; port < address + W83781D_EXTENT; port++) {
+ if (!request_region(port, 1, "w83781d")) {
+ pr_debug("w83781d: Failed to request port 0x%x\n",
+ port);
+ goto release;
+ }
}
#define REALLY_SLOW_IO
@@ -1902,8 +1902,8 @@ w83781d_isa_found(unsigned short address)
val == 0x30 ? "W83782D" : "W83781D", (int)address);
release:
- release_region(address + 4, 4);
- release_region(address, 4);
+ for (port--; port >= address; port--)
+ release_region(port, 1);
return found;
}
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index f7d6fe9c49ba..8f0b90ef8c76 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -364,7 +364,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
amd756_driver.name);
if (error)
- return error;
+ return -ENODEV;
if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index a7c59908c457..5b4ad86ca166 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -376,8 +376,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
smbus->size = pci_resource_len(dev, 0);
error = acpi_check_resource_conflict(&dev->resource[0]);
- if (error)
+ if (error) {
+ error = -ENODEV;
goto out_kfree;
+ }
if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
error = -EBUSY;
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 9d2c5adf5d4f..55edcfe5b851 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -732,8 +732,10 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
}
err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
- if (err)
+ if (err) {
+ err = -ENODEV;
goto exit;
+ }
err = pci_request_region(dev, SMBBAR, i801_driver.name);
if (err) {
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index 9f6b8e0f8632..dba6eb053e2f 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -281,7 +281,7 @@ static int __devinit sch_probe(struct pci_dev *dev,
return -ENODEV;
}
if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
- return -EBUSY;
+ return -ENODEV;
if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
sch_smba);
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 8bb795e7d7b2..e3235ff8e551 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -68,19 +68,10 @@ static u8 *i2c_buf_virt;
static void hw_i2c_dmachan_reset(struct mxs_i2c_dev *dev)
{
- mxs_dma_disable(dev->dma_chan);
mxs_dma_reset(dev->dma_chan);
mxs_dma_ack_irq(dev->dma_chan);
}
-static mxs_i2c_reset(struct mxs_i2c_dev *mxs_i2c)
-{
- hw_i2c_dmachan_reset(mxs_i2c);
- mxs_dma_enable_irq(mxs_i2c->dma_chan, 1);
- mxs_reset_block((void __iomem *)mxs_i2c->regbase, 0);
- __raw_writel(0x0000FF00, mxs_i2c->regbase + HW_I2C_CTRL1_SET);
-}
-
static int hw_i2c_dma_init(struct platform_device *pdev)
{
struct mxs_i2c_dev *mxs_i2c = platform_get_drvdata(pdev);
@@ -168,7 +159,7 @@ static void hw_i2c_dma_setup_read(u8 addr, void *buff, int len, int flags)
desc[0]->cmd.cmd.bits.pio_words = 1;
desc[0]->cmd.cmd.bits.wait4end = 1;
desc[0]->cmd.cmd.bits.dec_sem = 1;
- desc[0]->cmd.cmd.bits.irq = 0;
+ desc[0]->cmd.cmd.bits.irq = 1;
desc[0]->cmd.cmd.bits.chain = 1;
desc[0]->cmd.cmd.bits.command = DMA_READ;
desc[0]->cmd.address = i2c_buf_phys;
@@ -328,7 +319,6 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap,
msecs_to_jiffies(1000)
);
if (err <= 0) {
- mxs_i2c_reset(dev);
dev_dbg(dev->dev, "controller is timed out\n");
return -ETIMEDOUT;
}
@@ -375,19 +365,9 @@ static irqreturn_t mxs_i2c_dma_isr(int this_irq, void *dev_id)
mxs_dma_ack_irq(mxs_i2c->dma_chan);
mxs_dma_cooked(mxs_i2c->dma_chan, &list);
- complete(&mxs_i2c->cmd_complete);
-
return IRQ_HANDLED;
}
-static void mxs_i2c_task(struct work_struct *work)
-{
- struct mxs_i2c_dev *mxs_i2c = container_of(work,
- struct mxs_i2c_dev, work);
- mxs_i2c_reset(mxs_i2c);
- complete(&mxs_i2c->cmd_complete);
-}
-
#define I2C_IRQ_MASK 0x000000FF
static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
{
@@ -402,8 +382,20 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
if (stat & BM_I2C_CTRL1_NO_SLAVE_ACK_IRQ) {
mxs_i2c->cmd_err = -EREMOTEIO;
- /* it takes long time to reset i2c */
- schedule_work(&mxs_i2c->work);
+
+ /*
+ * Stop DMA
+ * Clear NAK
+ */
+ __raw_writel(BM_I2C_CTRL1_CLR_GOT_A_NAK,
+ mxs_i2c->regbase + HW_I2C_CTRL1_SET);
+ hw_i2c_dmachan_reset(mxs_i2c);
+ mxs_reset_block((void __iomem *)mxs_i2c->regbase, 1);
+ /* Will catch all error (IRQ mask) */
+ __raw_writel(0x0000FF00, mxs_i2c->regbase + HW_I2C_CTRL1_SET);
+
+ complete(&mxs_i2c->cmd_complete);
+
goto done;
}
@@ -415,10 +407,7 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
complete(&mxs_i2c->cmd_complete);
goto done;
}
-
- if ((stat & done_mask) == done_mask &&
- (mxs_i2c->flags & MXS_I2C_PIOQUEUE_MODE))
-
+ if ((stat & done_mask) == done_mask)
complete(&mxs_i2c->cmd_complete);
done:
@@ -535,8 +524,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
}
- INIT_WORK(&mxs_i2c->work, mxs_i2c_task);
-
return 0;
no_i2c_adapter:
diff --git a/drivers/i2c/busses/i2c-mxs.h b/drivers/i2c/busses/i2c-mxs.h
index 1a35385b793b..4ddca007624a 100644
--- a/drivers/i2c/busses/i2c-mxs.h
+++ b/drivers/i2c/busses/i2c-mxs.h
@@ -37,6 +37,5 @@ struct mxs_i2c_dev {
struct i2c_adapter adapter;
spinlock_t lock;
wait_queue_head_t queue;
- struct work_struct work;
};
#endif
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 0ed68e2ccd22..f7346a9bd95f 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -75,7 +75,7 @@ static int pca_isa_waitforcompletion(void *pd)
unsigned long timeout;
if (irq > -1) {
- ret = wait_event_interruptible_timeout(pca_wait,
+ ret = wait_event_timeout(pca_wait,
pca_isa_readbyte(pd, I2C_PCA_CON)
& I2C_PCA_CON_SI, pca_isa_ops.timeout);
} else {
@@ -96,7 +96,7 @@ static void pca_isa_resetchip(void *pd)
}
static irqreturn_t pca_handler(int this_irq, void *dev_id) {
- wake_up_interruptible(&pca_wait);
+ wake_up(&pca_wait);
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index c4df9d411cd5..5b2213df5ed0 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -84,7 +84,7 @@ static int i2c_pca_pf_waitforcompletion(void *pd)
unsigned long timeout;
if (i2c->irq) {
- ret = wait_event_interruptible_timeout(i2c->wait,
+ ret = wait_event_timeout(i2c->wait,
i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
& I2C_PCA_CON_SI, i2c->adap.timeout);
} else {
@@ -122,7 +122,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
return IRQ_NONE;
- wake_up_interruptible(&i2c->wait);
+ wake_up(&i2c->wait);
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 0249a7d762b9..808e49e6ad4e 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -168,7 +168,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
}
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
- return -EBUSY;
+ return -ENODEV;
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
@@ -259,7 +259,7 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
- return -EBUSY;
+ return -ENODEV;
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 8295885b2fdb..1649963b00dc 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -280,7 +280,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]);
if (retval)
- return retval;
+ return -ENODEV;
/* Everything is happy, let's grab the memory and set things up. */
if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index b1c050ff311d..e29b6d5ba8ef 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/types.h>
/* include interfaces to usb layer */
#include <linux/usb.h>
@@ -31,8 +32,8 @@
#define CMD_I2C_IO_END (1<<1)
/* i2c bit delay, default is 10us -> 100kHz */
-static int delay = 10;
-module_param(delay, int, 0);
+static unsigned short delay = 10;
+module_param(delay, ushort, 0);
MODULE_PARM_DESC(delay, "bit delay in microseconds, "
"e.g. 10 for 100kHz (default is 100kHz)");
@@ -109,7 +110,7 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
static u32 usb_func(struct i2c_adapter *adapter)
{
- u32 func;
+ __le32 func;
/* get functionality from adapter */
if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) !=
@@ -118,7 +119,7 @@ static u32 usb_func(struct i2c_adapter *adapter)
return 0;
}
- return func;
+ return le32_to_cpu(func);
}
/* This is the actual algorithm we define */
@@ -216,8 +217,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface,
"i2c-tiny-usb at bus %03d device %03d",
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
- if (usb_write(&dev->adapter, CMD_SET_DELAY,
- cpu_to_le16(delay), 0, NULL, 0) != 0) {
+ if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) {
dev_err(&dev->adapter.dev,
"failure setting delay to %dus\n", delay);
retval = -EIO;
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 54d810a4d00f..e4b1543015af 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -365,7 +365,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
found:
error = acpi_check_region(vt596_smba, 8, vt596_driver.name);
if (error)
- return error;
+ return -ENODEV;
if (!request_region(vt596_smba, 8, vt596_driver.name)) {
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
index b96f3025e588..ec0a7cab6c8b 100644
--- a/drivers/i2c/chips/tsl2550.c
+++ b/drivers/i2c/chips/tsl2550.c
@@ -277,6 +277,7 @@ static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
{
+ struct tsl2550_data *data = i2c_get_clientdata(client);
u8 ch0, ch1;
int ret;
@@ -296,6 +297,8 @@ static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
ret = tsl2550_calculate_lux(ch0, ch1);
if (ret < 0)
return ret;
+ if (data->operating_mode == 1)
+ ret *= 5;
return sprintf(buf, "%d\n", ret);
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0e45c296d3d2..b67c32c3fa13 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -718,6 +718,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
{
int res = 0;
struct i2c_adapter *found;
+ struct i2c_client *client, *next;
/* First make sure that this adapter was ever added */
mutex_lock(&core_lock);
@@ -737,10 +738,23 @@ int i2c_del_adapter(struct i2c_adapter *adap)
if (res)
return res;
+ /* Remove devices instantiated from sysfs */
+ list_for_each_entry_safe(client, next, &userspace_devices, detected) {
+ if (client->adapter == adap) {
+ dev_dbg(&adap->dev, "Removing %s at 0x%x\n",
+ client->name, client->addr);
+ list_del(&client->detected);
+ i2c_unregister_device(client);
+ }
+ }
+
/* Detach any active clients. This can't fail, thus we do not
checking the returned value. */
res = device_for_each_child(&adap->dev, NULL, __unregister_client);
+ /* device name is gone after device_unregister */
+ dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
+
/* clean up the sysfs representation */
init_completion(&adap->dev_released);
device_unregister(&adap->dev);
@@ -753,8 +767,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
idr_remove(&i2c_adapter_idr, adap->nr);
mutex_unlock(&core_lock);
- dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
-
/* Clear the device structure in case this adapter is ever going to be
added again */
memset(&adap->dev, 0, sizeof(adap->dev));
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 680e5975217f..ca0c46f6580a 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -379,7 +379,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
.host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
- IDE_HFLAG_ABUSE_PREFETCH,
+ IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_SERIALIZE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
@@ -389,7 +390,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd648_port_ops,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .host_flags = IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_SERIALIZE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index e246d3d3fbcc..b05ee089841a 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -162,7 +162,7 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
if (tf->command == ATA_CMD_SET_FEATURES &&
tf->feature == SETFEATURES_XFER &&
tf->nsect >= XFER_SW_DMA_0) {
- xfer_rate = ide_find_dma_mode(drive, XFER_UDMA_6);
+ xfer_rate = ide_find_dma_mode(drive, tf->nsect);
if (xfer_rate != tf->nsect) {
err = -EINVAL;
goto abort;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 1bb106f6221a..ad33db2eacf1 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1035,15 +1035,6 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
if (port_ops && port_ops->init_dev)
port_ops->init_dev(drive);
}
-
- ide_port_for_each_dev(i, drive, hwif) {
- /*
- * default to PIO Mode 0 before we figure out
- * the most suited mode for the attached device
- */
- if (port_ops && port_ops->set_pio_mode)
- port_ops->set_pio_mode(drive, 0);
- }
}
static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index afca22beaadf..3b88eba04c9c 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -2,7 +2,7 @@
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
* Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2007-2009 Bartlomiej Zolnierkiewicz
*
* May be copied or modified under the terms of the GNU General Public License
*
@@ -281,11 +281,13 @@ static void config_drive_art_rwp(ide_drive_t *drive)
pci_read_config_byte(dev, 0x4b, &reg4bh);
+ rw_prefetch = reg4bh & ~(0x11 << drive->dn);
+
if (drive->media == ide_disk)
- rw_prefetch = 0x11 << drive->dn;
+ rw_prefetch |= 0x11 << drive->dn;
- if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch)
- pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
+ if (reg4bh != rw_prefetch)
+ pci_write_config_byte(dev, 0x4b, rw_prefetch);
}
static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
index 9aec78d3bcff..1ccfb40e7215 100644
--- a/drivers/ide/slc90e66.c
+++ b/drivers/ide/slc90e66.c
@@ -91,8 +91,7 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
if (!(reg48 & u_flag))
pci_write_config_word(dev, 0x48, reg48|u_flag);
- /* FIXME: (reg4a & a_speed) ? */
- if ((reg4a & u_speed) != u_speed) {
+ if ((reg4a & a_speed) != u_speed) {
pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
pci_read_config_word(dev, 0x4a, &reg4a);
pci_write_config_word(dev, 0x4a, reg4a|u_speed);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 5598ecb48c5b..1148140d08a1 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -19,9 +19,6 @@
#include <linux/input.h>
#include <linux/major.h>
#include <linux/device.h>
-#ifdef CONFIG_WAKELOCK
-#include <linux/wakelock.h>
-#endif
#include "input-compat.h"
struct evdev {
@@ -45,10 +42,6 @@ struct evdev_client {
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
-#ifdef CONFIG_WAKELOCK
- struct wake_lock wake_lock;
- char name[28];
-#endif
};
static struct evdev *evdev_table[EVDEV_MINORS];
@@ -61,9 +54,6 @@ static void evdev_pass_event(struct evdev_client *client,
* Interrupts are disabled, just acquire the lock
*/
spin_lock(&client->buffer_lock);
-#ifdef CONFIG_WAKELOCK
- wake_lock_timeout(&client->wake_lock, 5 * HZ);
-#endif
client->buffer[client->head++] = *event;
client->head &= EVDEV_BUFFER_SIZE - 1;
spin_unlock(&client->buffer_lock);
@@ -80,15 +70,8 @@ static void evdev_event(struct input_handle *handle,
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
-#ifdef CONFIG_WAKELOCK
- struct timespec ts;
- ktime_get_ts(&ts);
- event.time.tv_sec = ts.tv_sec;
- event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-#else
do_gettimeofday(&event.time);
-#endif
event.type = type;
event.code = code;
event.value = value;
@@ -249,9 +232,6 @@ static int evdev_release(struct inode *inode, struct file *file)
mutex_unlock(&evdev->mutex);
evdev_detach_client(evdev, client);
-#ifdef CONFIG_WAKELOCK
- wake_lock_destroy(&client->wake_lock);
-#endif
kfree(client);
evdev_close_device(evdev);
@@ -288,11 +268,6 @@ static int evdev_open(struct inode *inode, struct file *file)
}
spin_lock_init(&client->buffer_lock);
-#ifdef CONFIG_WAKELOCK
- snprintf(client->name, sizeof(client->name), "%s-%d", dev_name(&evdev->dev),
- task_tgid_vnr(current));
- wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, client->name);
-#endif
client->evdev = evdev;
evdev_attach_client(evdev, client);
@@ -356,10 +331,6 @@ static int evdev_fetch_next_event(struct evdev_client *client,
if (have_event) {
*event = client->buffer[client->tail++];
client->tail &= EVDEV_BUFFER_SIZE - 1;
-#ifdef CONFIG_WAKELOCK
- if (client->head == client->tail)
- wake_unlock(&client->wake_lock);
-#endif
}
spin_unlock_irq(&client->buffer_lock);
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 88e2a24d9cff..fea01a591076 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -31,7 +31,7 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
-obj-$(CONFIG_KEYBOARD_MXC) += mxc_keyb.o mxc_pwrkey.o
+obj-$(CONFIG_KEYBOARD_MXC) += mxc_keyb.o
obj-$(CONFIG_KEYBOARD_MPR084) += mpr084.o
obj-$(CONFIG_KEYBOARD_STMP3XXX) += stmp3xxx-kbd.o
obj-$(CONFIG_KEYBOARD_MXS) += mxs-kbd.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 6c6a09b1c0fe..abc314f93ff3 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1608,6 +1608,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_samsung_forced_release_keys,
},
{
+ .ident = "Samsung R59P/R60P/R61P",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"),
+ },
+ .callback = atkbd_setup_forced_release,
+ .driver_data = atkbd_samsung_forced_release_keys,
+ },
+ {
.ident = "Fujitsu Amilo PA 1510",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
diff --git a/drivers/input/keyboard/mxc_keyb.c b/drivers/input/keyboard/mxc_keyb.c
index bd5ecd8c20f1..033713cbdfdf 100644
--- a/drivers/input/keyboard/mxc_keyb.c
+++ b/drivers/input/keyboard/mxc_keyb.c
@@ -1077,7 +1077,7 @@ static int mxc_kpp_probe(struct platform_device *pdev)
retval = request_irq(irq, mxc_kpp_interrupt, 0, MOD_NAME, MOD_NAME);
if (retval) {
pr_debug("KPP: request_irq(%d) returned error %d\n",
- irq, retval);
+ MXC_INT_KPP, retval);
goto err3;
}
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 5547e2429fbe..b172bef75910 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -5,6 +5,7 @@
* Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
* Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
* Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
*
* ALPS detection, tap switching and status querying info is taken from
* tpconfig utility (by C. Scott Ananian and Bruce Kall).
@@ -35,6 +36,8 @@
#define ALPS_OLDPROTO 0x10
#define ALPS_PASS 0x20
#define ALPS_FW_BK_2 0x40
+#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
+ 6-byte ALPS packet */
static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -55,7 +58,9 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
+ /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
+ { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf,
+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */
};
@@ -66,20 +71,88 @@ static const struct alps_model_info alps_model_data[] = {
*/
/*
- * ALPS abolute Mode - new format
+ * PS/2 packet format
+ *
+ * byte 0: 0 0 YSGN XSGN 1 M R L
+ * byte 1: X7 X6 X5 X4 X3 X2 X1 X0
+ * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ *
+ * Note that the device never signals overflow condition.
+ *
+ * ALPS absolute Mode - new format
*
* byte 0: 1 ? ? ? 1 ? ? ?
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0
- * byte 2: 0 x10 x9 x8 x7 ? fin ges
+ * byte 2: 0 x10 x9 x8 x7 ? fin ges
* byte 3: 0 y9 y8 y7 1 M R L
* byte 4: 0 y6 y5 y4 y3 y2 y1 y0
* byte 5: 0 z6 z5 z4 z3 z2 z1 z0
*
+ * Dualpoint device -- interleaved packet format
+ *
+ * byte 0: 1 1 0 0 1 1 1 1
+ * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
+ * byte 2: 0 x10 x9 x8 x7 0 fin ges
+ * byte 3: 0 0 YSGN XSGN 1 1 1 1
+ * byte 4: X7 X6 X5 X4 X3 X2 X1 X0
+ * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ * byte 6: 0 y9 y8 y7 1 m r l
+ * byte 7: 0 y6 y5 y4 y3 y2 y1 y0
+ * byte 8: 0 z6 z5 z4 z3 z2 z1 z0
+ *
+ * CAPITALS = stick, miniscules = touchpad
+ *
* ?'s can have different meanings on different models,
* such as wheel rotation, extra buttons, stick buttons
* on a dualpoint, etc.
*/
+static bool alps_is_valid_first_byte(const struct alps_model_info *model,
+ unsigned char data)
+{
+ return (data & model->mask0) == model->byte0;
+}
+
+static void alps_report_buttons(struct psmouse *psmouse,
+ struct input_dev *dev1, struct input_dev *dev2,
+ int left, int right, int middle)
+{
+ struct alps_data *priv = psmouse->private;
+ const struct alps_model_info *model = priv->i;
+
+ if (model->flags & ALPS_PS2_INTERLEAVED) {
+ struct input_dev *dev;
+
+ /*
+ * If shared button has already been reported on the
+ * other device (dev2) then this event should be also
+ * sent through that device.
+ */
+ dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1;
+ input_report_key(dev, BTN_LEFT, left);
+
+ dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1;
+ input_report_key(dev, BTN_RIGHT, right);
+
+ dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1;
+ input_report_key(dev, BTN_MIDDLE, middle);
+
+ /*
+ * Sync the _other_ device now, we'll do the first
+ * device later once we report the rest of the events.
+ */
+ input_sync(dev2);
+ } else {
+ /*
+ * For devices with non-interleaved packets we know what
+ * device buttons belong to so we can simply report them.
+ */
+ input_report_key(dev1, BTN_LEFT, left);
+ input_report_key(dev1, BTN_RIGHT, right);
+ input_report_key(dev1, BTN_MIDDLE, middle);
+ }
+}
+
static void alps_process_packet(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
@@ -89,18 +162,6 @@ static void alps_process_packet(struct psmouse *psmouse)
int x, y, z, ges, fin, left, right, middle;
int back = 0, forward = 0;
- if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
- input_report_key(dev2, BTN_LEFT, packet[0] & 1);
- input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
- input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
- input_report_rel(dev2, REL_X,
- packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
- input_report_rel(dev2, REL_Y,
- packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
- input_sync(dev2);
- return;
- }
-
if (priv->i->flags & ALPS_OLDPROTO) {
left = packet[2] & 0x10;
right = packet[2] & 0x08;
@@ -136,18 +197,13 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
- input_report_key(dev2, BTN_LEFT, left);
- input_report_key(dev2, BTN_RIGHT, right);
- input_report_key(dev2, BTN_MIDDLE, middle);
+ alps_report_buttons(psmouse, dev2, dev, left, right, middle);
- input_sync(dev);
input_sync(dev2);
return;
}
- input_report_key(dev, BTN_LEFT, left);
- input_report_key(dev, BTN_RIGHT, right);
- input_report_key(dev, BTN_MIDDLE, middle);
+ alps_report_buttons(psmouse, dev, dev2, left, right, middle);
/* Convert hardware tap to a reasonable Z value */
if (ges && !fin) z = 40;
@@ -188,25 +244,168 @@ static void alps_process_packet(struct psmouse *psmouse)
input_sync(dev);
}
+static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
+ unsigned char packet[],
+ bool report_buttons)
+{
+ struct alps_data *priv = psmouse->private;
+ struct input_dev *dev2 = priv->dev2;
+
+ if (report_buttons)
+ alps_report_buttons(psmouse, dev2, psmouse->dev,
+ packet[0] & 1, packet[0] & 2, packet[0] & 4);
+
+ input_report_rel(dev2, REL_X,
+ packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
+ input_report_rel(dev2, REL_Y,
+ packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
+
+ input_sync(dev2);
+}
+
+static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+
+ if (psmouse->pktcnt < 6)
+ return PSMOUSE_GOOD_DATA;
+
+ if (psmouse->pktcnt == 6) {
+ /*
+ * Start a timer to flush the packet if it ends up last
+ * 6-byte packet in the stream. Timer needs to fire
+ * psmouse core times out itself. 20 ms should be enough
+ * to decide if we are getting more data or not.
+ */
+ mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
+ return PSMOUSE_GOOD_DATA;
+ }
+
+ del_timer(&priv->timer);
+
+ if (psmouse->packet[6] & 0x80) {
+
+ /*
+ * Highest bit is set - that means we either had
+ * complete ALPS packet and this is start of the
+ * next packet or we got garbage.
+ */
+
+ if (((psmouse->packet[3] |
+ psmouse->packet[4] |
+ psmouse->packet[5]) & 0x80) ||
+ (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
+ dbg("refusing packet %x %x %x %x "
+ "(suspected interleaved ps/2)\n",
+ psmouse->packet[3], psmouse->packet[4],
+ psmouse->packet[5], psmouse->packet[6]);
+ return PSMOUSE_BAD_DATA;
+ }
+
+ alps_process_packet(psmouse);
+
+ /* Continue with the next packet */
+ psmouse->packet[0] = psmouse->packet[6];
+ psmouse->pktcnt = 1;
+
+ } else {
+
+ /*
+ * High bit is 0 - that means that we indeed got a PS/2
+ * packet in the middle of ALPS packet.
+ *
+ * There is also possibility that we got 6-byte ALPS
+ * packet followed by 3-byte packet from trackpoint. We
+ * can not distinguish between these 2 scenarios but
+ * becase the latter is unlikely to happen in course of
+ * normal operation (user would need to press all
+ * buttons on the pad and start moving trackpoint
+ * without touching the pad surface) we assume former.
+ * Even if we are wrong the wost thing that would happen
+ * the cursor would jump but we should not get protocol
+ * desynchronization.
+ */
+
+ alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
+ false);
+
+ /*
+ * Continue with the standard ALPS protocol handling,
+ * but make sure we won't process it as an interleaved
+ * packet again, which may happen if all buttons are
+ * pressed. To avoid this let's reset the 4th bit which
+ * is normally 1.
+ */
+ psmouse->packet[3] = psmouse->packet[6] & 0xf7;
+ psmouse->pktcnt = 4;
+ }
+
+ return PSMOUSE_GOOD_DATA;
+}
+
+static void alps_flush_packet(unsigned long data)
+{
+ struct psmouse *psmouse = (struct psmouse *)data;
+
+ serio_pause_rx(psmouse->ps2dev.serio);
+
+ if (psmouse->pktcnt == 6) {
+
+ /*
+ * We did not any more data in reasonable amount of time.
+ * Validate the last 3 bytes and process as a standard
+ * ALPS packet.
+ */
+ if ((psmouse->packet[3] |
+ psmouse->packet[4] |
+ psmouse->packet[5]) & 0x80) {
+ dbg("refusing packet %x %x %x "
+ "(suspected interleaved ps/2)\n",
+ psmouse->packet[3], psmouse->packet[4],
+ psmouse->packet[5]);
+ } else {
+ alps_process_packet(psmouse);
+ }
+ psmouse->pktcnt = 0;
+ }
+
+ serio_continue_rx(psmouse->ps2dev.serio);
+}
+
static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
+ const struct alps_model_info *model = priv->i;
if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
if (psmouse->pktcnt == 3) {
- alps_process_packet(psmouse);
+ alps_report_bare_ps2_packet(psmouse, psmouse->packet,
+ true);
return PSMOUSE_FULL_PACKET;
}
return PSMOUSE_GOOD_DATA;
}
- if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0)
+ /* Check for PS/2 packet stuffed in the middle of ALPS packet. */
+
+ if ((model->flags & ALPS_PS2_INTERLEAVED) &&
+ psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
+ return alps_handle_interleaved_ps2(psmouse);
+ }
+
+ if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
+ dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+ psmouse->packet[0], model->mask0, model->byte0);
return PSMOUSE_BAD_DATA;
+ }
/* Bytes 2 - 6 should have 0 in the highest bit */
if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
- (psmouse->packet[psmouse->pktcnt - 1] & 0x80))
+ (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
+ dbg("refusing packet[%i] = %x\n",
+ psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
return PSMOUSE_BAD_DATA;
+ }
if (psmouse->pktcnt == 6) {
alps_process_packet(psmouse);
@@ -441,6 +640,7 @@ static void alps_disconnect(struct psmouse *psmouse)
struct alps_data *priv = psmouse->private;
psmouse_reset(psmouse);
+ del_timer_sync(&priv->timer);
input_unregister_device(priv->dev2);
kfree(priv);
}
@@ -457,6 +657,8 @@ int alps_init(struct psmouse *psmouse)
goto init_fail;
priv->dev2 = dev2;
+ setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
+
psmouse->private = priv;
if (alps_hw_init(psmouse, &version))
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 4bbddc99962b..4b6024163d3c 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -23,6 +23,7 @@ struct alps_data {
char phys[32]; /* Phys */
const struct alps_model_info *i;/* Info */
int prev_fin; /* Finger bit from previous packet */
+ struct timer_list timer;
};
#ifdef CONFIG_MOUSE_PS2_ALPS
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 19984bf06cad..c65e24510494 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -652,6 +652,16 @@ static const struct dmi_system_id toshiba_dmi_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
},
+
+ },
+ {
+ .ident = "Toshiba Portege M300",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
+ },
+
},
{ }
};
diff --git a/drivers/input/touchscreen/mxc_ts.c b/drivers/input/touchscreen/mxc_ts.c
index 6cce76f1494f..6146b27f01da 100644
--- a/drivers/input/touchscreen/mxc_ts.c
+++ b/drivers/input/touchscreen/mxc_ts.c
@@ -43,9 +43,6 @@
#include <linux/pmic_external.h>
#include <linux/pmic_adc.h>
#include <linux/kthread.h>
-#ifdef CONFIG_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
#define MXC_TS_NAME "mxc_ts"
@@ -63,30 +60,6 @@ static struct task_struct *tstask;
static int calibration[7];
module_param_array(calibration, int, NULL, S_IRUGO | S_IWUSR);
-#ifdef CONFIG_EARLYSUSPEND
-
-static wait_queue_head_t ts_wait;
-static int ts_suspend;
-
-static void stop_ts_early_suspend(struct early_suspend *h)
-{
- ts_suspend = 1;
-}
-
-static void start_ts_late_resume(struct early_suspend *h)
-{
- ts_suspend = 0;
- wake_up_interruptible(&ts_wait);
-}
-
-static struct early_suspend stop_ts_early_suspend_desc = {
- .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
- .suspend = stop_ts_early_suspend,
- .resume = start_ts_late_resume,
-};
-
-#endif
-
static int ts_thread(void *arg)
{
t_touch_screen ts_sample;
@@ -96,9 +69,6 @@ static int ts_thread(void *arg)
int x, y;
static int last_x = -1, last_y = -1, last_press = -1;
-#ifdef CONFIG_EARLYSUSPEND
- wait_event_interruptible(ts_wait, !ts_suspend);
-#endif
memset(&ts_sample, 0, sizeof(t_touch_screen));
/* After 2 consecutive samples with the pen up, enable irq waiting */
@@ -112,7 +82,7 @@ static int ts_thread(void *arg)
}
if (ts_sample.x_position == 0 && ts_sample.y_position == 0 &&
- ts_sample.contact_resistance == 0) {
+ ts_sample.contact_resistance == 0) {
x = last_x;
y = last_y;
} else if (calibration[6] == 0) {
@@ -120,14 +90,14 @@ static int ts_thread(void *arg)
y = ts_sample.y_position;
} else {
x = calibration[0] * (int)ts_sample.x_position +
- calibration[1] * (int)ts_sample.y_position +
- calibration[2];
+ calibration[1] * (int)ts_sample.y_position +
+ calibration[2];
x /= calibration[6];
if (x < 0)
x = 0;
y = calibration[3] * (int)ts_sample.x_position +
- calibration[4] * (int)ts_sample.y_position +
- calibration[5];
+ calibration[4] * (int)ts_sample.y_position +
+ calibration[5];
y /= calibration[6];
if (y < 0)
y = 0;
@@ -156,7 +126,7 @@ static int ts_thread(void *arg)
/* report the BTN_TOUCH */
if (ts_sample.contact_resistance != last_press)
input_event(mxc_inputdev, EV_KEY,
- BTN_TOUCH, ts_sample.contact_resistance);
+ BTN_TOUCH, ts_sample.contact_resistance);
input_sync(mxc_inputdev);
last_press = ts_sample.contact_resistance;
@@ -177,7 +147,8 @@ static int __init mxc_ts_init(void)
mxc_inputdev = input_allocate_device();
if (!mxc_inputdev) {
- printk(KERN_ERR "mxc_ts_init: not enough memory\n");
+ printk(KERN_ERR
+ "mxc_ts_init: not enough memory\n");
return -ENOMEM;
}
@@ -194,14 +165,11 @@ static int __init mxc_ts_init(void)
tstask = kthread_run(ts_thread, NULL, "mxc_ts");
if (IS_ERR(tstask)) {
- printk(KERN_ERR "mxc_ts_init: failed to create kthread");
+ printk(KERN_ERR
+ "mxc_ts_init: failed to create kthread");
tstask = NULL;
return -1;
}
-#ifdef CONFIG_EARLYSUSPEND
- init_waitqueue_head(&ts_wait);
- register_early_suspend(&stop_ts_early_suspend_desc);
-#endif
printk("mxc input touchscreen loaded\n");
return 0;
}
@@ -217,9 +185,6 @@ static void __exit mxc_ts_exit(void)
input_free_device(mxc_inputdev);
mxc_inputdev = NULL;
}
-#ifdef CONFIG_EARLYSUSPEND
- unregister_early_suspend(&stop_ts_early_suspend_desc);
-#endif
}
late_initcall(mxc_ts_init);
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 8ff7e35c7069..f33ac27de643 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -408,33 +408,28 @@ static int if_write_room(struct tty_struct *tty)
return retval;
}
-/* FIXME: This function does not have error returns */
-
static int if_chars_in_buffer(struct tty_struct *tty)
{
struct cardstate *cs;
- int retval = -ENODEV;
+ int retval = 0;
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
pr_err("%s: no cardstate\n", __func__);
- return -ENODEV;
+ return 0;
}
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (mutex_lock_interruptible(&cs->mutex))
- return -ERESTARTSYS; // FIXME -EINTR?
+ mutex_lock(&cs->mutex);
- if (!cs->connected) {
+ if (!cs->connected)
gig_dbg(DEBUG_IF, "not connected");
- retval = -ENODEV;
- } else if (!cs->open_count)
+ else if (!cs->open_count)
dev_warn(cs->dev, "%s: device not opened\n", __func__);
- else if (cs->mstate != MS_LOCKED) {
+ else if (cs->mstate != MS_LOCKED)
dev_warn(cs->dev, "can't write to unlocked device\n");
- retval = -EBUSY;
- } else
+ else
retval = cs->ops->chars_in_buffer(cs);
mutex_unlock(&cs->mutex);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 9de54202c90c..a420b64472e3 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -817,8 +817,8 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
}
/* we have a complete hdlc packet */
if (finish) {
- if ((!fifo->skbuff->data[fifo->skbuff->len - 1])
- && (fifo->skbuff->len > 3)) {
+ if (fifo->skbuff->len > 3 &&
+ !fifo->skbuff->data[fifo->skbuff->len - 1]) {
if (fifon == HFCUSB_D_RX) {
DBG(HFCUSB_DBG_DCHANNEL,
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index aa30b5cb3513..9a9dc3be1c49 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -1535,10 +1535,8 @@ static int isdn_ppp_mp_bundle_array_init(void)
int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
return -ENOMEM;
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
- skb_queue_head_init(&isdn_ppp_bundle_arr[i].frags);
- }
return 0;
}
@@ -1571,7 +1569,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
return -ENOMEM;
lp->next = lp->last = lp; /* nobody else in a queue */
- skb_queue_head_init(&lp->netdev->pb->frags);
+ lp->netdev->pb->frags = NULL;
lp->netdev->pb->frames = 0;
lp->netdev->pb->seq = UINT_MAX;
}
@@ -1583,29 +1581,28 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
static u32 isdn_ppp_mp_get_seq( int short_seq,
struct sk_buff * skb, u32 last_seq );
-static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
- struct sk_buff *to);
-static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
- struct sk_buff *from, struct sk_buff *to,
- u32 lastseq);
-static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb);
+static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
+ struct sk_buff * from, struct sk_buff * to );
+static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+ struct sk_buff * from, struct sk_buff * to );
+static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
- struct sk_buff *newfrag, *frag, *start, *nextf;
- u32 newseq, minseq, thisseq;
- isdn_mppp_stats *stats;
struct ippp_struct *is;
+ isdn_net_local * lpq;
+ ippp_bundle * mp;
+ isdn_mppp_stats * stats;
+ struct sk_buff * newfrag, * frag, * start, *nextf;
+ u32 newseq, minseq, thisseq;
unsigned long flags;
- isdn_net_local *lpq;
- ippp_bundle *mp;
int slot;
spin_lock_irqsave(&net_dev->pb->lock, flags);
- mp = net_dev->pb;
- stats = &mp->stats;
+ mp = net_dev->pb;
+ stats = &mp->stats;
slot = lp->ppp_slot;
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
@@ -1616,19 +1613,20 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
return;
}
is = ippp_table[slot];
- if (++mp->frames > stats->max_queue_len)
+ if( ++mp->frames > stats->max_queue_len )
stats->max_queue_len = mp->frames;
if (is->debug & 0x8)
isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
- skb, is->last_link_seqno);
+ skb, is->last_link_seqno);
+
/* if this packet seq # is less than last already processed one,
* toss it right away, but check for sequence start case first
*/
- if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) {
+ if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
mp->seq = newseq; /* the first packet: required for
* rfc1990 non-compliant clients --
* prevents constant packet toss */
@@ -1659,31 +1657,22 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* packets */
newfrag = skb;
- /* Insert new fragment into the proper sequence slot. */
- skb_queue_walk(&mp->frags, frag) {
- if (MP_SEQ(frag) == newseq) {
- isdn_ppp_mp_free_skb(mp, newfrag);
- newfrag = NULL;
- break;
- }
- if (MP_LT(newseq, MP_SEQ(frag))) {
- __skb_queue_before(&mp->frags, frag, newfrag);
- newfrag = NULL;
- break;
- }
- }
- if (newfrag)
- __skb_queue_tail(&mp->frags, newfrag);
+ /* if this new fragment is before the first one, then enqueue it now. */
+ if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
+ newfrag->next = frag;
+ mp->frags = frag = newfrag;
+ newfrag = NULL;
+ }
- frag = skb_peek(&mp->frags);
- start = ((MP_FLAGS(frag) & MP_BEGIN_FRAG) &&
- (MP_SEQ(frag) == mp->seq)) ? frag : NULL;
- if (!start)
- goto check_overflow;
+ start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
+ MP_SEQ(frag) == mp->seq ? frag : NULL;
- /* main fragment traversing loop
+ /*
+ * main fragment traversing loop
*
* try to accomplish several tasks:
+ * - insert new fragment into the proper sequence slot (once that's done
+ * newfrag will be set to NULL)
* - reassemble any complete fragment sequence (non-null 'start'
* indicates there is a continguous sequence present)
* - discard any incomplete sequences that are below minseq -- due
@@ -1692,46 +1681,71 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* come to complete such sequence and it should be discarded
*
* loop completes when we accomplished the following tasks:
+ * - new fragment is inserted in the proper sequence ('newfrag' is
+ * set to NULL)
* - we hit a gap in the sequence, so no reassembly/processing is
* possible ('start' would be set to NULL)
*
* algorithm for this code is derived from code in the book
* 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
*/
- skb_queue_walk_safe(&mp->frags, frag, nextf) {
- thisseq = MP_SEQ(frag);
-
- /* check for misplaced start */
- if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
- printk(KERN_WARNING"isdn_mppp(seq %d): new "
- "BEGIN flag with no prior END", thisseq);
- stats->seqerrs++;
- stats->frame_drops++;
- isdn_ppp_mp_discard(mp, start, frag);
- start = frag;
- } else if (MP_LE(thisseq, minseq)) {
- if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
+ while (start != NULL || newfrag != NULL) {
+
+ thisseq = MP_SEQ(frag);
+ nextf = frag->next;
+
+ /* drop any duplicate fragments */
+ if (newfrag != NULL && thisseq == newseq) {
+ isdn_ppp_mp_free_skb(mp, newfrag);
+ newfrag = NULL;
+ }
+
+ /* insert new fragment before next element if possible. */
+ if (newfrag != NULL && (nextf == NULL ||
+ MP_LT(newseq, MP_SEQ(nextf)))) {
+ newfrag->next = nextf;
+ frag->next = nextf = newfrag;
+ newfrag = NULL;
+ }
+
+ if (start != NULL) {
+ /* check for misplaced start */
+ if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
+ printk(KERN_WARNING"isdn_mppp(seq %d): new "
+ "BEGIN flag with no prior END", thisseq);
+ stats->seqerrs++;
+ stats->frame_drops++;
+ start = isdn_ppp_mp_discard(mp, start,frag);
+ nextf = frag->next;
+ }
+ } else if (MP_LE(thisseq, minseq)) {
+ if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
start = frag;
- else {
+ else {
if (MP_FLAGS(frag) & MP_END_FRAG)
- stats->frame_drops++;
- __skb_unlink(skb, &mp->frags);
+ stats->frame_drops++;
+ if( mp->frags == frag )
+ mp->frags = nextf;
isdn_ppp_mp_free_skb(mp, frag);
+ frag = nextf;
continue;
- }
+ }
}
- /* if we have end fragment, then we have full reassembly
- * sequence -- reassemble and process packet now
+ /* if start is non-null and we have end fragment, then
+ * we have full reassembly sequence -- reassemble
+ * and process packet now
*/
- if (MP_FLAGS(frag) & MP_END_FRAG) {
- minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
- /* Reassemble the packet then dispatch it */
- isdn_ppp_mp_reassembly(net_dev, lp, start, frag, thisseq);
+ if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
+ minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
+ /* Reassemble the packet then dispatch it */
+ isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
- start = NULL;
- frag = NULL;
- }
+ start = NULL;
+ frag = NULL;
+
+ mp->frags = nextf;
+ }
/* check if need to update start pointer: if we just
* reassembled the packet and sequence is contiguous
@@ -1742,25 +1756,26 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* below low watermark and set start to the next frag or
* clear start ptr.
*/
- if (nextf != (struct sk_buff *)&mp->frags &&
+ if (nextf != NULL &&
((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
- /* if we just reassembled and the next one is here,
- * then start another reassembly.
- */
- if (frag == NULL) {
+ /* if we just reassembled and the next one is here,
+ * then start another reassembly. */
+
+ if (frag == NULL) {
if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
- start = nextf;
- else {
- printk(KERN_WARNING"isdn_mppp(seq %d):"
- " END flag with no following "
- "BEGIN", thisseq);
+ start = nextf;
+ else
+ {
+ printk(KERN_WARNING"isdn_mppp(seq %d):"
+ " END flag with no following "
+ "BEGIN", thisseq);
stats->seqerrs++;
}
}
- } else {
- if (nextf != (struct sk_buff *)&mp->frags &&
- frag != NULL &&
- MP_LT(thisseq, minseq)) {
+
+ } else {
+ if ( nextf != NULL && frag != NULL &&
+ MP_LT(thisseq, minseq)) {
/* we've got a break in the sequence
* and we not at the end yet
* and we did not just reassembled
@@ -1769,39 +1784,41 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* discard all the frames below low watermark
* and start over */
stats->frame_drops++;
- isdn_ppp_mp_discard(mp, start, nextf);
+ mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
}
/* break in the sequence, no reassembly */
- start = NULL;
- }
- if (!start)
- break;
- }
+ start = NULL;
+ }
+
+ frag = nextf;
+ } /* while -- main loop */
+
+ if (mp->frags == NULL)
+ mp->frags = frag;
-check_overflow:
/* rather straighforward way to deal with (not very) possible
- * queue overflow
- */
+ * queue overflow */
if (mp->frames > MP_MAX_QUEUE_LEN) {
stats->overflows++;
- skb_queue_walk_safe(&mp->frags, frag, nextf) {
- if (mp->frames <= MP_MAX_QUEUE_LEN)
- break;
- __skb_unlink(frag, &mp->frags);
- isdn_ppp_mp_free_skb(mp, frag);
+ while (mp->frames > MP_MAX_QUEUE_LEN) {
+ frag = mp->frags->next;
+ isdn_ppp_mp_free_skb(mp, mp->frags);
+ mp->frags = frag;
}
}
spin_unlock_irqrestore(&mp->lock, flags);
}
-static void isdn_ppp_mp_cleanup(isdn_net_local *lp)
+static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
{
- struct sk_buff *skb, *tmp;
-
- skb_queue_walk_safe(&lp->netdev->pb->frags, skb, tmp) {
- __skb_unlink(skb, &lp->netdev->pb->frags);
- isdn_ppp_mp_free_skb(lp->netdev->pb, skb);
- }
+ struct sk_buff * frag = lp->netdev->pb->frags;
+ struct sk_buff * nextfrag;
+ while( frag ) {
+ nextfrag = frag->next;
+ isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
+ frag = nextfrag;
+ }
+ lp->netdev->pb->frags = NULL;
}
static u32 isdn_ppp_mp_get_seq( int short_seq,
@@ -1838,115 +1855,72 @@ static u32 isdn_ppp_mp_get_seq( int short_seq,
return seq;
}
-static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
- struct sk_buff *to)
+struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
+ struct sk_buff * from, struct sk_buff * to )
{
- if (from) {
- struct sk_buff *skb, *tmp;
- int freeing = 0;
-
- skb_queue_walk_safe(&mp->frags, skb, tmp) {
- if (skb == to)
- break;
- if (skb == from)
- freeing = 1;
- if (!freeing)
- continue;
- __skb_unlink(skb, &mp->frags);
- isdn_ppp_mp_free_skb(mp, skb);
+ if( from )
+ while (from != to) {
+ struct sk_buff * next = from->next;
+ isdn_ppp_mp_free_skb(mp, from);
+ from = next;
}
- }
+ return from;
}
-static unsigned int calc_tot_len(struct sk_buff_head *queue,
- struct sk_buff *from, struct sk_buff *to)
+void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+ struct sk_buff * from, struct sk_buff * to )
{
- unsigned int tot_len = 0;
- struct sk_buff *skb;
- int found_start = 0;
-
- skb_queue_walk(queue, skb) {
- if (skb == from)
- found_start = 1;
- if (!found_start)
- continue;
- tot_len += skb->len - MP_HEADER_LEN;
- if (skb == to)
- break;
- }
- return tot_len;
-}
-
-/* Reassemble packet using fragments in the reassembly queue from
- * 'from' until 'to', inclusive.
- */
-static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
- struct sk_buff *from, struct sk_buff *to,
- u32 lastseq)
-{
- ippp_bundle *mp = net_dev->pb;
- unsigned int tot_len;
- struct sk_buff *skb;
+ ippp_bundle * mp = net_dev->pb;
int proto;
+ struct sk_buff * skb;
+ unsigned int tot_len;
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__func__, lp->ppp_slot);
return;
}
-
- tot_len = calc_tot_len(&mp->frags, from, to);
-
- if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) {
- if (ippp_table[lp->ppp_slot]->debug & 0x40)
+ if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
+ if( ippp_table[lp->ppp_slot]->debug & 0x40 )
printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
- "len %d\n", MP_SEQ(from), from->len);
+ "len %d\n", MP_SEQ(from), from->len );
skb = from;
skb_pull(skb, MP_HEADER_LEN);
- __skb_unlink(skb, &mp->frags);
mp->frames--;
} else {
- struct sk_buff *walk, *tmp;
- int found_start = 0;
+ struct sk_buff * frag;
+ int n;
- if (ippp_table[lp->ppp_slot]->debug & 0x40)
- printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
- "to %d, len %d\n", MP_SEQ(from), lastseq,
- tot_len);
+ for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
+ tot_len += frag->len - MP_HEADER_LEN;
- skb = dev_alloc_skb(tot_len);
- if (!skb)
+ if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+ printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
+ "to %d, len %d\n", MP_SEQ(from),
+ (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
+ if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
- "of size %d\n", tot_len);
-
- found_start = 0;
- skb_queue_walk_safe(&mp->frags, walk, tmp) {
- if (walk == from)
- found_start = 1;
- if (!found_start)
- continue;
+ "of size %d\n", tot_len);
+ isdn_ppp_mp_discard(mp, from, to);
+ return;
+ }
- if (skb) {
- unsigned int len = walk->len - MP_HEADER_LEN;
- skb_copy_from_linear_data_offset(walk, MP_HEADER_LEN,
- skb_put(skb, len),
- len);
- }
- __skb_unlink(walk, &mp->frags);
- isdn_ppp_mp_free_skb(mp, walk);
+ while( from != to ) {
+ unsigned int len = from->len - MP_HEADER_LEN;
- if (walk == to)
- break;
+ skb_copy_from_linear_data_offset(from, MP_HEADER_LEN,
+ skb_put(skb,len),
+ len);
+ frag = from->next;
+ isdn_ppp_mp_free_skb(mp, from);
+ from = frag;
}
}
- if (!skb)
- return;
-
proto = isdn_ppp_strip_proto(skb);
isdn_ppp_push_higher(net_dev, lp, skb, proto);
}
-static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb)
+static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
{
dev_kfree_skb(skb);
mp->frames--;
diff --git a/drivers/leds/leds-mxs-pwm.c b/drivers/leds/leds-mxs-pwm.c
index a546900a44d0..c76821770446 100644
--- a/drivers/leds/leds-mxs-pwm.c
+++ b/drivers/leds/leds-mxs-pwm.c
@@ -165,35 +165,10 @@ static int __devexit mxs_pwm_led_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int mxs_led_suspend(struct platform_device *dev, pm_message_t state)
-{
- int i;
-
- for (i = 0; i < leds.led_num; i++)
- led_classdev_suspend(&leds.leds[i].dev);
- return 0;
-}
-
-static int mxs_led_resume(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < leds.led_num; i++)
- led_classdev_resume(&leds.leds[i].dev);
- return 0;
-}
-#else
-#define mxs_led_suspend NULL
-#define mxs_led_resume NULL
-#endif
-
static struct platform_driver mxs_pwm_led_driver = {
.probe = mxs_pwm_led_probe,
.remove = __devexit_p(mxs_pwm_led_remove),
- .suspend = mxs_led_suspend,
- .resume = mxs_led_resume,
.driver = {
.name = "mxs-leds",
},
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index fde377c60cca..386a7972111d 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -79,6 +79,7 @@ struct thermostat {
u8 limits[3];
int last_speed[2];
int last_var[2];
+ int pwm_inv[2];
};
static enum {ADT7460, ADT7467} therm_type;
@@ -124,6 +125,8 @@ read_reg(struct thermostat* th, int reg)
return data;
}
+static struct i2c_driver thermostat_driver;
+
static int
attach_thermostat(struct i2c_adapter *adapter)
{
@@ -148,7 +151,7 @@ attach_thermostat(struct i2c_adapter *adapter)
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
- list_add_tail(&client->detected, &client->driver->clients);
+ list_add_tail(&client->detected, &thermostat_driver.clients);
return 0;
}
@@ -227,19 +230,23 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
if (speed >= 0) {
manual = read_reg(th, MANUAL_MODE[fan]);
+ manual &= ~INVERT_MASK;
write_reg(th, MANUAL_MODE[fan],
- (manual|MANUAL_MASK) & (~INVERT_MASK));
+ manual | MANUAL_MASK | th->pwm_inv[fan]);
write_reg(th, FAN_SPD_SET[fan], speed);
} else {
/* back to automatic */
if(therm_type == ADT7460) {
manual = read_reg(th,
MANUAL_MODE[fan]) & (~MANUAL_MASK);
-
+ manual &= ~INVERT_MASK;
+ manual |= th->pwm_inv[fan];
write_reg(th,
MANUAL_MODE[fan], manual|REM_CONTROL[fan]);
} else {
manual = read_reg(th, MANUAL_MODE[fan]);
+ manual &= ~INVERT_MASK;
+ manual |= th->pwm_inv[fan];
write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK));
}
}
@@ -416,6 +423,10 @@ static int probe_thermostat(struct i2c_client *client,
thermostat = th;
+ /* record invert bit status because fw can corrupt it after suspend */
+ th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
+ th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
+
/* be sure to really write fan speed the first time */
th->last_speed[0] = -2;
th->last_speed[1] = -2;
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index a028598af2d3..ea32c7e5a9af 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -286,6 +286,8 @@ struct fcu_fan_table fcu_fans[] = {
},
};
+static struct i2c_driver therm_pm72_driver;
+
/*
* Utility function to create an i2c_client structure and
* attach it to one of u3 adapters
@@ -318,7 +320,7 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
- list_add_tail(&clt->detected, &clt->driver->clients);
+ list_add_tail(&clt->detected, &therm_pm72_driver.clients);
return clt;
}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index b40fb9b6c862..6f308a4757ee 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -405,7 +405,11 @@ static int __init via_pmu_start(void)
printk(KERN_ERR "via-pmu: can't map interrupt\n");
return -ENODEV;
}
- if (request_irq(irq, via_pmu_interrupt, 0, "VIA-PMU", (void *)0)) {
+ /* We set IRQF_TIMER because we don't want the interrupt to be disabled
+ * between the 2 passes of driver suspend, we control our own disabling
+ * for that one
+ */
+ if (request_irq(irq, via_pmu_interrupt, IRQF_TIMER, "VIA-PMU", (void *)0)) {
printk(KERN_ERR "via-pmu: can't request irq %d\n", irq);
return -ENODEV;
}
@@ -419,7 +423,7 @@ static int __init via_pmu_start(void)
gpio_irq = irq_of_parse_and_map(gpio_node, 0);
if (gpio_irq != NO_IRQ) {
- if (request_irq(gpio_irq, gpio1_interrupt, 0,
+ if (request_irq(gpio_irq, gpio1_interrupt, IRQF_TIMER,
"GPIO1 ADB", (void *)0))
printk(KERN_ERR "pmu: can't get irq %d"
" (GPIO1)\n", gpio_irq);
@@ -925,8 +929,7 @@ proc_write_options(struct file *file, const char __user *buffer,
#ifdef CONFIG_ADB
/* Send an ADB command */
-static int
-pmu_send_request(struct adb_request *req, int sync)
+static int pmu_send_request(struct adb_request *req, int sync)
{
int i, ret;
@@ -1005,16 +1008,11 @@ pmu_send_request(struct adb_request *req, int sync)
}
/* Enable/disable autopolling */
-static int
-pmu_adb_autopoll(int devs)
+static int __pmu_adb_autopoll(int devs)
{
struct adb_request req;
- if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)
- return -ENXIO;
-
if (devs) {
- adb_dev_map = devs;
pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86,
adb_dev_map >> 8, adb_dev_map);
pmu_adb_flags = 2;
@@ -1027,9 +1025,17 @@ pmu_adb_autopoll(int devs)
return 0;
}
+static int pmu_adb_autopoll(int devs)
+{
+ if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)
+ return -ENXIO;
+
+ adb_dev_map = devs;
+ return __pmu_adb_autopoll(devs);
+}
+
/* Reset the ADB bus */
-static int
-pmu_adb_reset_bus(void)
+static int pmu_adb_reset_bus(void)
{
struct adb_request req;
int save_autopoll = adb_dev_map;
@@ -1038,13 +1044,13 @@ pmu_adb_reset_bus(void)
return -ENXIO;
/* anyone got a better idea?? */
- pmu_adb_autopoll(0);
+ __pmu_adb_autopoll(0);
- req.nbytes = 5;
+ req.nbytes = 4;
req.done = NULL;
req.data[0] = PMU_ADB_CMD;
- req.data[1] = 0;
- req.data[2] = ADB_BUSRESET;
+ req.data[1] = ADB_BUSRESET;
+ req.data[2] = 0;
req.data[3] = 0;
req.data[4] = 0;
req.reply_len = 0;
@@ -1056,7 +1062,7 @@ pmu_adb_reset_bus(void)
pmu_wait_complete(&req);
if (save_autopoll != 0)
- pmu_adb_autopoll(save_autopoll);
+ __pmu_adb_autopoll(save_autopoll);
return 0;
}
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 529886c7a826..ed6426a10773 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -115,6 +115,8 @@ static int wf_lm75_probe(struct i2c_client *client,
return rc;
}
+static struct i2c_driver wf_lm75_driver;
+
static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
u8 addr, int ds1775,
const char *loc)
@@ -157,7 +159,7 @@ static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
- list_add_tail(&client->detected, &client->driver->clients);
+ list_add_tail(&client->detected, &wf_lm75_driver.clients);
return client;
fail:
return NULL;
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index e2a55ecda2b2..a67b349319e9 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -88,6 +88,8 @@ static int wf_max6690_probe(struct i2c_client *client,
return rc;
}
+static struct i2c_driver wf_max6690_driver;
+
static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
u8 addr, const char *loc)
{
@@ -119,7 +121,7 @@ static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
- list_add_tail(&client->detected, &client->driver->clients);
+ list_add_tail(&client->detected, &wf_max6690_driver.clients);
return client;
fail:
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 5da729e58f99..e20330a28959 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -194,6 +194,8 @@ static struct wf_sensor_ops wf_sat_ops = {
.owner = THIS_MODULE,
};
+static struct i2c_driver wf_sat_driver;
+
static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
{
struct i2c_board_info info;
@@ -222,7 +224,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
- list_add_tail(&client->detected, &client->driver->clients);
+ list_add_tail(&client->detected, &wf_sat_driver.clients);
}
static int wf_sat_probe(struct i2c_client *client,
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 3319c2fec28e..0aee97a30b80 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1077,23 +1077,31 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
* out to disk
*/
-void bitmap_daemon_work(struct bitmap *bitmap)
+void bitmap_daemon_work(mddev_t *mddev)
{
+ struct bitmap *bitmap;
unsigned long j;
unsigned long flags;
struct page *page = NULL, *lastpage = NULL;
int blocks;
void *paddr;
- if (bitmap == NULL)
+ /* Use a mutex to guard daemon_work against
+ * bitmap_destroy.
+ */
+ mutex_lock(&mddev->bitmap_mutex);
+ bitmap = mddev->bitmap;
+ if (bitmap == NULL) {
+ mutex_unlock(&mddev->bitmap_mutex);
return;
+ }
if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
goto done;
bitmap->daemon_lastrun = jiffies;
if (bitmap->allclean) {
bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
- return;
+ goto done;
}
bitmap->allclean = 1;
@@ -1202,6 +1210,7 @@ void bitmap_daemon_work(struct bitmap *bitmap)
done:
if (bitmap->allclean == 0)
bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ;
+ mutex_unlock(&mddev->bitmap_mutex);
}
static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1538,9 +1547,9 @@ void bitmap_flush(mddev_t *mddev)
*/
sleep = bitmap->daemon_sleep;
bitmap->daemon_sleep = 0;
- bitmap_daemon_work(bitmap);
- bitmap_daemon_work(bitmap);
- bitmap_daemon_work(bitmap);
+ bitmap_daemon_work(mddev);
+ bitmap_daemon_work(mddev);
+ bitmap_daemon_work(mddev);
bitmap->daemon_sleep = sleep;
bitmap_update_sb(bitmap);
}
@@ -1571,6 +1580,7 @@ static void bitmap_free(struct bitmap *bitmap)
kfree(bp);
kfree(bitmap);
}
+
void bitmap_destroy(mddev_t *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
@@ -1578,7 +1588,9 @@ void bitmap_destroy(mddev_t *mddev)
if (!bitmap) /* there was no bitmap */
return;
+ mutex_lock(&mddev->bitmap_mutex);
mddev->bitmap = NULL; /* disconnect from the md device */
+ mutex_unlock(&mddev->bitmap_mutex);
if (mddev->thread)
mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index e98900671ca9..7e38d13ddcac 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -282,7 +282,7 @@ void bitmap_close_sync(struct bitmap *bitmap);
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
void bitmap_unplug(struct bitmap *bitmap);
-void bitmap_daemon_work(struct bitmap *bitmap);
+void bitmap_daemon_work(mddev_t *mddev);
#endif
#endif
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 556acff3952f..932d1b123143 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -155,7 +155,8 @@ static int set_chunk_size(struct dm_exception_store *store,
char *value;
chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10);
- if (*chunk_size_arg == '\0' || *value != '\0') {
+ if (*chunk_size_arg == '\0' || *value != '\0' ||
+ chunk_size_ulong > UINT_MAX) {
*error = "Invalid chunk size";
return -EINVAL;
}
@@ -171,34 +172,35 @@ static int set_chunk_size(struct dm_exception_store *store,
*/
chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9);
- return dm_exception_store_set_chunk_size(store, chunk_size_ulong,
+ return dm_exception_store_set_chunk_size(store,
+ (unsigned) chunk_size_ulong,
error);
}
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned long chunk_size_ulong,
+ unsigned chunk_size,
char **error)
{
/* Check chunk_size is a power of 2 */
- if (!is_power_of_2(chunk_size_ulong)) {
+ if (!is_power_of_2(chunk_size)) {
*error = "Chunk size is not a power of 2";
return -EINVAL;
}
/* Validate the chunk size against the device block size */
- if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
+ if (chunk_size % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
*error = "Chunk size is not a multiple of device blocksize";
return -EINVAL;
}
- if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) {
+ if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
*error = "Chunk size is too high";
return -EINVAL;
}
- store->chunk_size = chunk_size_ulong;
- store->chunk_mask = chunk_size_ulong - 1;
- store->chunk_shift = ffs(chunk_size_ulong) - 1;
+ store->chunk_size = chunk_size;
+ store->chunk_mask = chunk_size - 1;
+ store->chunk_shift = ffs(chunk_size) - 1;
return 0;
}
@@ -251,7 +253,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
r = set_chunk_size(tmp_store, argv[2], &ti->error);
if (r)
- goto bad_cow;
+ goto bad_ctr;
r = type->ctr(tmp_store, 0, NULL);
if (r) {
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index 812c71872ba0..8a223a48802c 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -101,9 +101,9 @@ struct dm_exception_store {
struct dm_dev *cow;
/* Size of data blocks saved - must be a power of 2 */
- chunk_t chunk_size;
- chunk_t chunk_mask;
- chunk_t chunk_shift;
+ unsigned chunk_size;
+ unsigned chunk_mask;
+ unsigned chunk_shift;
void *context;
};
@@ -169,7 +169,7 @@ int dm_exception_store_type_register(struct dm_exception_store_type *type);
int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned long chunk_size_ulong,
+ unsigned chunk_size,
char **error);
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 6e186b1a062d..7ac2c1450d10 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -156,7 +156,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
}
/* The ptr value is sufficient for local unique id */
- lc->luid = (uint64_t)lc;
+ lc->luid = (unsigned long)lc;
lc->ti = ti;
@@ -582,7 +582,7 @@ static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
break;
case STATUSTYPE_TABLE:
sz = 0;
- table_args = strstr(lc->usr_argv_str, " ");
+ table_args = strchr(lc->usr_argv_str, ' ');
BUG_ON(!table_args); /* There will always be a ' ' */
table_args++;
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index ba0edad2d048..54abf9e303b7 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -129,11 +129,13 @@ static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
* This is the connector callback that delivers data
* that was sent from userspace.
*/
-static void cn_ulog_callback(void *data)
+static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
- struct cn_msg *msg = (struct cn_msg *)data;
struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
spin_lock(&receiving_list_lock);
if (msg->len == 0)
fill_pkg(msg, NULL);
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index d5b2e08750d5..0c746420c008 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -284,12 +284,13 @@ static int read_header(struct pstore *ps, int *new_snapshot)
{
int r;
struct disk_header *dh;
- chunk_t chunk_size;
+ unsigned chunk_size;
int chunk_size_supplied = 1;
char *chunk_err;
/*
- * Use default chunk size (or hardsect_size, if larger) if none supplied
+ * Use default chunk size (or logical_block_size, if larger)
+ * if none supplied
*/
if (!ps->store->chunk_size) {
ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
@@ -334,10 +335,9 @@ static int read_header(struct pstore *ps, int *new_snapshot)
return 0;
if (chunk_size_supplied)
- DMWARN("chunk size %llu in device metadata overrides "
- "table chunk size of %llu.",
- (unsigned long long)chunk_size,
- (unsigned long long)ps->store->chunk_size);
+ DMWARN("chunk size %u in device metadata overrides "
+ "table chunk size of %u.",
+ chunk_size, ps->store->chunk_size);
/* We had a bogus chunk_size. Fix stuff up. */
free_area(ps);
@@ -345,8 +345,8 @@ static int read_header(struct pstore *ps, int *new_snapshot)
r = dm_exception_store_set_chunk_size(ps->store, chunk_size,
&chunk_err);
if (r) {
- DMERR("invalid on-disk chunk size %llu: %s.",
- (unsigned long long)chunk_size, chunk_err);
+ DMERR("invalid on-disk chunk size %u: %s.",
+ chunk_size, chunk_err);
return r;
}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 57f1bf7f3b7a..3a3ba46e6d4b 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -296,6 +296,7 @@ static void __insert_origin(struct origin *o)
*/
static int register_snapshot(struct dm_snapshot *snap)
{
+ struct dm_snapshot *l;
struct origin *o, *new_o;
struct block_device *bdev = snap->origin->bdev;
@@ -319,7 +320,11 @@ static int register_snapshot(struct dm_snapshot *snap)
__insert_origin(o);
}
- list_add_tail(&snap->list, &o->snapshots);
+ /* Sort the list according to chunk size, largest-first smallest-last */
+ list_for_each_entry(l, &o->snapshots, list)
+ if (l->store->chunk_size < snap->store->chunk_size)
+ break;
+ list_add_tail(&snap->list, &l->list);
up_write(&_origins_lock);
return 0;
@@ -668,6 +673,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
bio_list_init(&s->queued_bios);
INIT_WORK(&s->queued_bios_work, flush_queued_bios);
+ if (!s->store->chunk_size) {
+ ti->error = "Chunk size not set";
+ goto bad_load_and_register;
+ }
+
/* Add snapshot to the list of snapshots for this origin */
/* Exceptions aren't triggered till snapshot_resume() is called */
if (register_snapshot(s)) {
@@ -951,7 +961,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
src.bdev = bdev;
src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
- src.count = min(s->store->chunk_size, dev_size - src.sector);
+ src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector);
dest.bdev = s->store->cow->bdev;
dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
@@ -1142,6 +1152,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
unsigned sz = 0;
struct dm_snapshot *snap = ti->private;
+ down_write(&snap->lock);
+
switch (type) {
case STATUSTYPE_INFO:
if (!snap->valid)
@@ -1173,6 +1185,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
break;
}
+ up_write(&snap->lock);
+
return 0;
}
@@ -1388,7 +1402,7 @@ static void origin_resume(struct dm_target *ti)
struct dm_dev *dev = ti->private;
struct dm_snapshot *snap;
struct origin *o;
- chunk_t chunk_size = 0;
+ unsigned chunk_size = 0;
down_read(&_origins_lock);
o = __lookup_origin(dev->bdev);
@@ -1465,7 +1479,7 @@ static int __init dm_snapshot_init(void)
r = dm_register_target(&snapshot_target);
if (r) {
DMERR("snapshot target register failed %d", r);
- return r;
+ goto bad_register_snapshot_target;
}
r = dm_register_target(&origin_target);
@@ -1522,6 +1536,9 @@ bad2:
dm_unregister_target(&origin_target);
bad1:
dm_unregister_target(&snapshot_target);
+
+bad_register_snapshot_target:
+ dm_exception_store_exit();
return r;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index b4845b14740d..ae087b0c49f9 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -47,6 +47,7 @@ struct dm_io {
atomic_t io_count;
struct bio *bio;
unsigned long start_time;
+ spinlock_t endio_lock;
};
/*
@@ -576,8 +577,12 @@ static void dec_pending(struct dm_io *io, int error)
struct mapped_device *md = io->md;
/* Push-back supersedes any I/O errors */
- if (error && !(io->error > 0 && __noflush_suspending(md)))
- io->error = error;
+ if (unlikely(error)) {
+ spin_lock_irqsave(&io->endio_lock, flags);
+ if (!(io->error > 0 && __noflush_suspending(md)))
+ io->error = error;
+ spin_unlock_irqrestore(&io->endio_lock, flags);
+ }
if (atomic_dec_and_test(&io->io_count)) {
if (io->error == DM_ENDIO_REQUEUE) {
@@ -1224,6 +1229,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
atomic_set(&ci.io->io_count, 1);
ci.io->bio = bio;
ci.io->md = md;
+ spin_lock_init(&ci.io->endio_lock);
ci.sector = bio->bi_sector;
ci.sector_count = bio_sectors(bio);
if (unlikely(bio_empty_barrier(bio)))
@@ -1819,6 +1825,7 @@ static struct mapped_device *alloc_dev(int minor)
bad_bdev:
destroy_workqueue(md->wq);
bad_thread:
+ del_gendisk(md->disk);
put_disk(md->disk);
bad_disk:
blk_cleanup_queue(md->queue);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9dd872000cec..2938e9ca711e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -276,7 +276,9 @@ static void mddev_put(mddev_t *mddev)
if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
return;
if (!mddev->raid_disks && list_empty(&mddev->disks) &&
- !mddev->hold_active) {
+ mddev->ctime == 0 && !mddev->hold_active) {
+ /* Array is not configured at all, and not held active,
+ * so destroy it */
list_del(&mddev->all_mddevs);
if (mddev->gendisk) {
/* we did a probe so need to clean up.
@@ -361,6 +363,7 @@ static mddev_t * mddev_find(dev_t unit)
mutex_init(&new->open_mutex);
mutex_init(&new->reconfig_mutex);
+ mutex_init(&new->bitmap_mutex);
INIT_LIST_HEAD(&new->disks);
INIT_LIST_HEAD(&new->all_mddevs);
init_timer(&new->safemode_timer);
@@ -5039,6 +5042,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->minor_version = info->minor_version;
mddev->patch_version = info->patch_version;
mddev->persistent = !info->not_persistent;
+ /* ensure mddev_put doesn't delete this now that there
+ * is some minimal configuration.
+ */
+ mddev->ctime = get_seconds();
return 0;
}
mddev->major_version = MD_MAJOR_VERSION;
@@ -6495,8 +6502,9 @@ void md_do_sync(mddev_t *mddev)
skip:
mddev->curr_resync = 0;
mddev->curr_resync_completed = 0;
- mddev->resync_min = 0;
- mddev->resync_max = MaxSector;
+ if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
+ /* We completed so max setting can be forgotten. */
+ mddev->resync_max = MaxSector;
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
wake_up(&resync_wait);
set_bit(MD_RECOVERY_DONE, &mddev->recovery);
@@ -6594,7 +6602,7 @@ void md_check_recovery(mddev_t *mddev)
if (mddev->bitmap)
- bitmap_daemon_work(mddev->bitmap);
+ bitmap_daemon_work(mddev);
if (mddev->ro)
return;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index f8fc188bc762..d7aad830018e 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -289,6 +289,7 @@ struct mddev_s
* hot-adding a bitmap. It should
* eventually be settable by sysfs.
*/
+ struct mutex bitmap_mutex;
struct list_head all_mddevs;
};
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 8726fd7ebce5..d3e492e8781c 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1643,11 +1643,12 @@ static void raid1d(mddev_t *mddev)
r1_bio->sector,
r1_bio->sectors);
unfreeze_array(conf);
- }
+ } else
+ md_error(mddev,
+ conf->mirrors[r1_bio->read_disk].rdev);
bio = r1_bio->bios[r1_bio->read_disk];
- if ((disk=read_balance(conf, r1_bio)) == -1 ||
- disk == r1_bio->read_disk) {
+ if ((disk=read_balance(conf, r1_bio)) == -1) {
printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
" read error for block %llu\n",
bdevname(bio->bi_bdev,b),
@@ -1676,6 +1677,7 @@ static void raid1d(mddev_t *mddev)
generic_make_request(bio);
}
}
+ cond_resched();
}
if (unplug)
unplug_slaves(mddev);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 3d9020cf6f6e..6a5a5fb18b30 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1630,6 +1630,7 @@ static void raid10d(mddev_t *mddev)
generic_make_request(bio);
}
}
+ cond_resched();
}
if (unplug)
unplug_slaves(mddev);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b8a2c5dc67ba..c339c8fdcbd5 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3790,6 +3790,8 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
sector_nr = conf->reshape_progress;
sector_div(sector_nr, new_data_disks);
if (sector_nr) {
+ mddev->curr_resync_completed = sector_nr;
+ sysfs_notify(&mddev->kobj, NULL, "sync_completed");
*skipped = 1;
return sector_nr;
}
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
index 2d02698d4f4f..7eb1bf75cd07 100644
--- a/drivers/media/common/tuners/mxl5007t.c
+++ b/drivers/media/common/tuners/mxl5007t.c
@@ -196,7 +196,7 @@ static void copy_reg_bits(struct reg_pair_t *reg_pair1,
i = j = 0;
while (reg_pair1[i].reg || reg_pair1[i].val) {
- while (reg_pair2[j].reg || reg_pair2[j].reg) {
+ while (reg_pair2[j].reg || reg_pair2[j].val) {
if (reg_pair1[i].reg != reg_pair2[j].reg) {
j++;
continue;
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index b10935630154..f446f9a18ef1 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -595,13 +595,13 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
case RF2:
map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] -
prog_cal[RF1] + prog_tab[RF1]) /
- ((rf_freq[RF2] - rf_freq[RF1]) / 1000);
+ (s32)((rf_freq[RF2] - rf_freq[RF1]) / 1000);
map[i].rf2 = rf_freq[RF2] / 1000;
break;
case RF3:
map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] -
prog_cal[RF2] + prog_tab[RF2]) /
- ((rf_freq[RF3] - rf_freq[RF2]) / 1000);
+ (s32)((rf_freq[RF3] - rf_freq[RF2]) / 1000);
map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2];
map[i].rf3 = rf_freq[RF3] / 1000;
break;
@@ -963,12 +963,12 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
struct tda18271_std_map_item *map;
char *mode;
int ret;
- u32 freq = params->frequency * 62500;
+ u32 freq = params->frequency * 125 *
+ ((params->mode == V4L2_TUNER_RADIO) ? 1 : 1000) / 2;
priv->mode = TDA18271_ANALOG;
if (params->mode == V4L2_TUNER_RADIO) {
- freq = freq / 1000;
map = &std_map->fm_radio;
mode = "fm";
} else if (params->std & V4L2_STD_MN) {
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 26690dfb3260..4d0c8d56047c 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -1266,6 +1266,7 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
{USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
+/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
{0},
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1346,7 +1347,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
{
.name = "KWorld PlusTV Dual DVB-T Stick " \
"(DVB-T 399U)",
- .cold_ids = {&af9015_usb_table[4], NULL},
+ .cold_ids = {&af9015_usb_table[4],
+ &af9015_usb_table[25], NULL},
.warm_ids = {NULL},
},
{
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 406d7fba369d..f32b332ba76d 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -663,6 +663,14 @@ static struct zl10353_config cxusb_zl10353_xc3028_config = {
.parallel_ts = 1,
};
+static struct zl10353_config cxusb_zl10353_xc3028_config_no_i2c_gate = {
+ .demod_address = 0x0f,
+ .if2 = 45600,
+ .no_tuner = 1,
+ .parallel_ts = 1,
+ .disable_i2c_gate_ctrl = 1,
+};
+
static struct mt352_config cxusb_mt352_xc3028_config = {
.demod_address = 0x0f,
.if2 = 4560,
@@ -894,7 +902,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config,
+ &cxusb_zl10353_xc3028_config_no_i2c_gate,
&adap->dev->i2c_adap)) == NULL)
return -EIO;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 9593b7289994..5ace1312c34c 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -103,6 +103,7 @@
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_INTEL_CE9500 0x9500
#define USB_PID_KWORLD_399U 0xe399
+#define USB_PID_KWORLD_399U_2 0xe400
#define USB_PID_KWORLD_395U 0xe396
#define USB_PID_KWORLD_395U_2 0xe39b
#define USB_PID_KWORLD_395U_3 0xe395
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 8217e5b38f47..ac10fff61f3c 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -1344,6 +1344,11 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
if (dib7000p_identify(st) != 0)
goto error;
+ /* FIXME: make sure the dev.parent field is initialized, or else
+ request_firmware() will hit an OOPS (this should be moved somewhere
+ more common) */
+ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+
dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
dib7000p_demod_reset(st);
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index cb8a358b7310..8f88a586b0dd 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -529,6 +529,12 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_SIANO_NICE },
{ USB_DEVICE(0x187f, 0x0301),
.driver_info = SMS1XXX_BOARD_SIANO_VENICE },
+ { USB_DEVICE(0x2040, 0xb900),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0xb910),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0xc000),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ } /* Terminating entry */
};
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index c3f579de6e71..c6cf11661868 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -181,12 +181,10 @@ static void gemtek_pci_mute(struct gemtek_pci *card)
static void gemtek_pci_unmute(struct gemtek_pci *card)
{
- mutex_lock(&card->lock);
if (card->mute) {
gemtek_pci_setfrequency(card, card->current_frequency);
card->mute = false;
}
- mutex_unlock(&card->lock);
}
static int gemtek_pci_getsignal(struct gemtek_pci *card)
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index e7185d1cf281..c64c8d201262 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -592,17 +592,6 @@ config VIDEO_MXS_PXP
To compile this driver as a module, choose M here: the
module will be called pxp.
-config VIDEO_MXC_PXP_V4L2
- tristate "MXC PxP V4L2 driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_MX5
- select VIDEOBUF_DMA_CONTIG
- ---help---
- This is a video4linux driver for the Freescale PxP
- (Pixel Pipeline). This module supports output overlay of
- the MXC framebuffer on a video stream.
-
- To compile this driver as a module, choose M here.
-
config VIDEO_MXC_OPL
tristate
depends on VIDEO_DEV && ARCH_MXC
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index a4de2a151253..49cb18802024 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -94,7 +94,6 @@ obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += mxc/capture/
obj-$(CONFIG_VIDEO_MXC_IPU_OUTPUT) += mxc/output/
obj-$(CONFIG_VIDEO_MXC_IPUV1_WVGA_OUTPUT) += mxc/output/
obj-$(CONFIG_VIDEO_MXC_EMMA_OUTPUT) += mxc/output/
-obj-$(CONFIG_VIDEO_MXC_PXP_V4L2) += mxc/output/
obj-$(CONFIG_VIDEO_MXC_OPL) += mxc/opl/
obj-$(CONFIG_VIDEO_PXP) += pxp.o
obj-$(CONFIG_VIDEO_MXS_PXP) += mxs_pxp.o
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 8cc6dd28d6a7..b8e276c88353 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -1299,7 +1299,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
tvnorm = &bttv_tvnorms[norm];
- if (!memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
+ if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
sizeof (tvnorm->cropcap))) {
bttv_crop_reset(&btv->crop[0], norm);
btv->crop[1] = btv->crop[0]; /* current = default */
@@ -3798,11 +3798,34 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
(item->vb.queue.next != &btv->capture)) {
item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
+ /* Mike Isely <isely@pobox.com> - Only check
+ * and set up the bottom field in the logic
+ * below. Don't ever do the top field. This
+ * of course means that if we set up the
+ * bottom field in the above code that we'll
+ * actually skip a field. But that's OK.
+ * Having processed only a single buffer this
+ * time, then the next time around the first
+ * available buffer should be for a top field.
+ * That will then cause us here to set up a
+ * top then a bottom field in the normal way.
+ * The alternative to this understanding is
+ * that we set up the second available buffer
+ * as a top field, but that's out of order
+ * since this driver always processes the top
+ * field first - the effect will be the two
+ * buffers being returned in the wrong order,
+ * with the second buffer also being delayed
+ * by one field time (owing to the fifo nature
+ * of videobuf). Worse still, we'll be stuck
+ * doing fields out of order now every time
+ * until something else causes a field to be
+ * dropped. By effectively forcing a field to
+ * drop this way then we always get back into
+ * sync within a single frame time. (Out of
+ * order fields can screw up deinterlacing
+ * algorithms.) */
if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
- if (NULL == set->top &&
- V4L2_FIELD_TOP == item->vb.field) {
- set->top = item;
- }
if (NULL == set->bottom &&
V4L2_FIELD_BOTTOM == item->vb.field) {
set->bottom = item;
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 7bd8a70f0a0b..ac947aecb9c3 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -383,6 +383,11 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
{
+ struct em28xx *dev = snd_pcm_substream_chip(substream);
+
+ dev->adev.hwptr_done_capture = 0;
+ dev->adev.capture_transfer_done = 0;
+
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 1c2e544eda73..ffe9306f5bb9 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -2170,8 +2170,6 @@ static int em28xx_hint_board(struct em28xx *dev)
/* ----------------------------------------------------------------------- */
void em28xx_register_i2c_ir(struct em28xx *dev)
{
- struct i2c_board_info info;
- struct IR_i2c_init_data init_data;
const unsigned short addr_list[] = {
0x30, 0x47, I2C_CLIENT_END
};
@@ -2179,9 +2177,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
if (disable_ir)
return;
- memset(&info, 0, sizeof(struct i2c_board_info));
- memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ memset(&dev->info, 0, sizeof(&dev->info));
+ memset(&dev->init_data, 0, sizeof(dev->init_data));
+ strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE);
/* detect & configure */
switch (dev->model) {
@@ -2191,19 +2189,19 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
break;
case (EM2800_BOARD_TERRATEC_CINERGY_200):
case (EM2820_BOARD_TERRATEC_CINERGY_250):
- init_data.ir_codes = ir_codes_em_terratec;
- init_data.get_key = em28xx_get_key_terratec;
- init_data.name = "i2c IR (EM28XX Terratec)";
+ dev->init_data.ir_codes = ir_codes_em_terratec;
+ dev->init_data.get_key = em28xx_get_key_terratec;
+ dev->init_data.name = "i2c IR (EM28XX Terratec)";
break;
case (EM2820_BOARD_PINNACLE_USB_2):
- init_data.ir_codes = ir_codes_pinnacle_grey;
- init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
- init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
+ dev->init_data.ir_codes = ir_codes_pinnacle_grey;
+ dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
+ dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
- init_data.ir_codes = ir_codes_hauppauge_new;
- init_data.get_key = em28xx_get_key_em_haup;
- init_data.name = "i2c IR (EM2840 Hauppauge)";
+ dev->init_data.ir_codes = ir_codes_hauppauge_new;
+ dev->init_data.get_key = em28xx_get_key_em_haup;
+ dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
break;
case (EM2820_BOARD_MSI_VOX_USB_2):
break;
@@ -2215,9 +2213,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
break;
}
- if (init_data.name)
- info.platform_data = &init_data;
- i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
+ if (dev->init_data.name)
+ dev->info.platform_data = &dev->init_data;
+ i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list);
}
void em28xx_card_setup(struct em28xx *dev)
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index d603575431b4..ec1d212f7e3a 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -591,6 +591,7 @@ static int dvb_fini(struct em28xx *dev)
if (dev->dvb) {
unregister_dvb(dev->dvb);
+ kfree(dev->dvb);
dev->dvb = NULL;
}
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index a2add61f7d59..cb2a70a59a0f 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -595,6 +595,10 @@ struct em28xx {
struct delayed_work sbutton_query_work;
struct em28xx_dvb *dvb;
+
+ /* I2C keyboard data */
+ struct i2c_board_info info;
+ struct IR_i2c_init_data init_data;
};
struct em28xx_ops {
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index 0163903d1c0f..3b159e4e69b1 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -35,12 +35,25 @@ static
const
struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
{
+ .ident = "BRUNEINIT",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
+ DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
+ }
+ }, {
.ident = "Fujitsu-Siemens Amilo Xa 2528",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
}
}, {
+ .ident = "Fujitsu-Siemens Amilo Xi 2528",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
+ }
+ }, {
.ident = "Fujitsu-Siemens Amilo Xi 2550",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -51,6 +64,13 @@ static
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+ DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
+ }
+ }, {
+ .ident = "MSI GX700",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
}
}, {
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 2f6e135d94bc..557886522211 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -3364,6 +3364,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x4064),
.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+ {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x4068),
.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
{USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index d6332ab80669..33f4d0a1f6fd 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -727,7 +727,7 @@ static const u8 ov7660_sensor_init[][8] = {
{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
/* Outformat = rawRGB */
{0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
- {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
+ {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
/* GAIN BLUE RED VREF */
{0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
/* COM 1 BAVE GEAVE AECHH */
@@ -783,7 +783,7 @@ static const u8 ov7660_sensor_init[][8] = {
{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
- {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
/****** (some exchanges in the win trace) ******/
{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
/* bits[3..0]reserved */
@@ -1145,17 +1145,12 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
reg_w1(gspca_dev, 0x01, 0x42);
break;
case SENSOR_OV7660:
- reg_w1(gspca_dev, 0x01, 0x61);
- reg_w1(gspca_dev, 0x17, 0x20);
- reg_w1(gspca_dev, 0x01, 0x60);
- reg_w1(gspca_dev, 0x01, 0x40);
- break;
case SENSOR_SP80708:
reg_w1(gspca_dev, 0x01, 0x63);
reg_w1(gspca_dev, 0x17, 0x20);
reg_w1(gspca_dev, 0x01, 0x62);
reg_w1(gspca_dev, 0x01, 0x42);
- mdelay(100);
+ msleep(100);
reg_w1(gspca_dev, 0x02, 0x62);
break;
/* case SENSOR_HV7131R: */
@@ -1624,6 +1619,8 @@ static void setvflip(struct sd *sd)
static void setinfrared(struct sd *sd)
{
+ if (sd->gspca_dev.ctrl_dis & (1 << INFRARED_IDX))
+ return;
/*fixme: different sequence for StarCam Clip and StarCam 370i */
/* Clip */
i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
@@ -1637,16 +1634,19 @@ static void setfreq(struct gspca_dev *gspca_dev)
if (gspca_dev->ctrl_dis & (1 << FREQ_IDX))
return;
if (sd->sensor == SENSOR_OV7660) {
+ u8 com8;
+
+ com8 = 0xdf; /* auto gain/wb/expo */
switch (sd->freq) {
case 0: /* Banding filter disabled */
- i2c_w1(gspca_dev, 0x13, 0xdf);
+ i2c_w1(gspca_dev, 0x13, com8 | 0x20);
break;
case 1: /* 50 hz */
- i2c_w1(gspca_dev, 0x13, 0xff);
+ i2c_w1(gspca_dev, 0x13, com8);
i2c_w1(gspca_dev, 0x3b, 0x0a);
break;
case 2: /* 60 hz */
- i2c_w1(gspca_dev, 0x13, 0xff);
+ i2c_w1(gspca_dev, 0x13, com8);
i2c_w1(gspca_dev, 0x3b, 0x02);
break;
}
@@ -1796,12 +1796,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x99, 0x60);
break;
case SENSOR_OV7660:
- reg_w1(gspca_dev, 0x9a, 0x05);
- if (sd->bridge == BRIDGE_SN9C105)
- reg_w1(gspca_dev, 0x99, 0xff);
- else
- reg_w1(gspca_dev, 0x99, 0x5b);
- break;
case SENSOR_SP80708:
reg_w1(gspca_dev, 0x9a, 0x05);
reg_w1(gspca_dev, 0x99, 0x59);
@@ -2325,18 +2319,19 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
-/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
+/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
- {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
{USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
#endif
{USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/
-/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
+/* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, PO2030N, ??)}, */
+/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x21)}, */
{USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/
{USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/
{USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/
@@ -2352,6 +2347,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
#endif
+/* {USB_DEVICE(0x0c45, 0x6132), BSI(SN9C120, OV7670, 0x21)}, */
{USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
{USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
@@ -2359,7 +2355,9 @@ static const __devinitdata struct usb_device_id device_table[] = {
#endif
{USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
{USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)},
- {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)},
+/* {USB_DEVICE(0x0c45, 0x6142), BSI(SN9C120, PO2030N, ??)}, *sn9c120b*/
+ {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, /*sn9c120b*/
+ {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x21)}, /*sn9c120b*/
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
index be9a988aff2f..0ab131d605a4 100644
--- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
@@ -2244,7 +2244,7 @@ static int mxc_mmap(struct file *file, struct vm_area_struct *vma)
return -EINTR;
size = vma->vm_end - vma->vm_start;
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start,
vma->vm_pgoff, size, vma->vm_page_prot)) {
diff --git a/drivers/media/video/mxc/capture/ov3640.c b/drivers/media/video/mxc/capture/ov3640.c
index 899945b7d071..0169e0553ada 100644
--- a/drivers/media/video/mxc/capture/ov3640.c
+++ b/drivers/media/video/mxc/capture/ov3640.c
@@ -26,7 +26,7 @@
#define OV3640_VOLTAGE_ANALOG 2800000
#define OV3640_VOLTAGE_DIGITAL_CORE 1500000
#define OV3640_VOLTAGE_DIGITAL_IO 1800000
-#define OV3640_VOLTAGE_DIGITAL_GPO 2800000
+
/* Check these values! */
#define MIN_FPS 15
@@ -1317,15 +1317,12 @@ static int ov3640_probe(struct i2c_client *client,
gpo_regulator = regulator_get(&client->dev,
plat_data->gpo_regulator);
if (!IS_ERR(gpo_regulator)) {
- regulator_set_voltage(gpo_regulator,
- OV3640_VOLTAGE_DIGITAL_GPO,
- OV3640_VOLTAGE_DIGITAL_GPO);
if (regulator_enable(gpo_regulator) != 0) {
- pr_err("%s:gpo enable error\n", __func__);
+ pr_err("%s:gpo3 enable error\n", __func__);
goto err4;
} else {
dev_dbg(&client->dev,
- "%s:gpo enable ok\n", __func__);
+ "%s:gpo3 enable ok\n", __func__);
}
} else
gpo_regulator = NULL;
diff --git a/drivers/media/video/mxc/output/Makefile b/drivers/media/video/mxc/output/Makefile
index 500442544902..1713fa3bf3ab 100644
--- a/drivers/media/video/mxc/output/Makefile
+++ b/drivers/media/video/mxc/output/Makefile
@@ -6,9 +6,6 @@ endif
ifeq ($(CONFIG_VIDEO_MXC_IPU_OUTPUT),y)
obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc_v4l2_output.o
endif
-ifeq ($(CONFIG_VIDEO_MXC_PXP_V4L2),y)
- obj-$(CONFIG_VIDEO_MXC_PXP_V4L2) += mxc_pxp_v4l2.o
-endif
ifeq ($(CONFIG_VIDEO_MXC_IPUV1_WVGA_OUTPUT),y)
obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mx31_v4l2_wvga_output.o
endif
diff --git a/drivers/media/video/mxc/output/mxc_v4l2_output.c b/drivers/media/video/mxc/output/mxc_v4l2_output.c
index b7bbfed73019..0567298dcb7e 100644
--- a/drivers/media/video/mxc/output/mxc_v4l2_output.c
+++ b/drivers/media/video/mxc/output/mxc_v4l2_output.c
@@ -245,7 +245,6 @@ static int select_display_buffer(vout_data *vout, int next_buf)
{
int ret = 0;
- vout->disp_buf_num = next_buf;
if (ipu_get_cur_buffer_idx(vout->display_ch, IPU_INPUT_BUFFER)
!= next_buf)
ret = ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER,
@@ -290,9 +289,10 @@ static int finish_previous_frame(vout_data *vout)
mm_segment_t old_fs;
int ret = 0;
- /* make sure buf[vout->disp_buf_num] in showing */
+ /* make sure buf[next_done_ipu_buf] showed */
while (ipu_check_buffer_busy(vout->display_ch,
- IPU_INPUT_BUFFER, vout->disp_buf_num)) {
+ IPU_INPUT_BUFFER, vout->next_done_ipu_buf)) {
+ /* wait for display frame finish */
if (fbi->fbops->fb_ioctl) {
old_fs = get_fs();
set_fs(KERNEL_DS);
@@ -303,7 +303,7 @@ static int finish_previous_frame(vout_data *vout)
if (ret < 0) {
/* ic_bypass need clear display buffer ready for next update*/
ipu_clear_buffer_ready(vout->display_ch, IPU_INPUT_BUFFER,
- vout->disp_buf_num);
+ vout->next_done_ipu_buf);
}
}
}
@@ -318,9 +318,9 @@ static int show_current_frame(vout_data *vout)
mm_segment_t old_fs;
int ret = 0;
- /* make sure buf[vout->disp_buf_num] begin to show */
+ /* make sure buf[next_rdy_ipu_buf] begin to show */
if (ipu_get_cur_buffer_idx(vout->display_ch, IPU_INPUT_BUFFER)
- != vout->disp_buf_num) {
+ != vout->next_rdy_ipu_buf) {
/* wait for display frame finish */
if (fbi->fbops->fb_ioctl) {
old_fs = get_fs();
@@ -334,10 +334,10 @@ static int show_current_frame(vout_data *vout)
return ret;
}
-static void icbypass_work_func(struct work_struct *work)
+static void timer_work_func(struct work_struct *work)
{
vout_data *vout =
- container_of(work, vout_data, icbypass_work);
+ container_of(work, vout_data, timer_work);
int index, ret;
int last_buf;
unsigned long lock_flags = 0;
@@ -346,30 +346,34 @@ static void icbypass_work_func(struct work_struct *work)
spin_lock_irqsave(&g_lock, lock_flags);
- index = dequeue_buf(&vout->ready_q);
- if (index == -1) { /* no buffers ready, should never occur */
- dev_err(&vout->video_dev->dev,
- "mxc_v4l2out: timer - no queued buffers ready\n");
- goto exit;
- }
- g_buf_dq_cnt++;
- vout->frame_count++;
+ if (g_buf_output_cnt == 0) {
+ ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER, 1);
+ } else {
+ index = dequeue_buf(&vout->ready_q);
+ if (index == -1) { /* no buffers ready, should never occur */
+ dev_err(&vout->video_dev->dev,
+ "mxc_v4l2out: timer - no queued buffers ready\n");
+ goto exit;
+ }
+ g_buf_dq_cnt++;
+ vout->frame_count++;
- vout->ipu_buf[vout->next_rdy_ipu_buf] = index;
- ret = ipu_update_channel_buffer(vout->display_ch, IPU_INPUT_BUFFER,
- vout->next_rdy_ipu_buf,
- vout->v4l2_bufs[index].m.offset);
- ret += select_display_buffer(vout, vout->next_rdy_ipu_buf);
- if (ret < 0) {
- dev_err(&vout->video_dev->dev,
- "unable to update buffer %d address rc=%d\n",
- vout->next_rdy_ipu_buf, ret);
- goto exit;
+ vout->ipu_buf[vout->next_rdy_ipu_buf] = index;
+ ret = ipu_update_channel_buffer(vout->display_ch, IPU_INPUT_BUFFER,
+ vout->next_rdy_ipu_buf,
+ vout->v4l2_bufs[index].m.offset);
+ ret += select_display_buffer(vout, vout->next_rdy_ipu_buf);
+ if (ret < 0) {
+ dev_err(&vout->video_dev->dev,
+ "unable to update buffer %d address rc=%d\n",
+ vout->next_rdy_ipu_buf, ret);
+ goto exit;
+ }
+ spin_unlock_irqrestore(&g_lock, lock_flags);
+ show_current_frame(vout);
+ spin_lock_irqsave(&g_lock, lock_flags);
+ vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
}
- spin_unlock_irqrestore(&g_lock, lock_flags);
- show_current_frame(vout);
- spin_lock_irqsave(&g_lock, lock_flags);
- vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
last_buf = vout->ipu_buf[vout->next_done_ipu_buf];
if (last_buf != -1) {
@@ -399,24 +403,6 @@ exit:
spin_unlock_irqrestore(&g_lock, lock_flags);
}
-static int get_cur_fb_blank(vout_data *vout)
-{
- struct fb_info *fbi =
- registered_fb[vout->output_fb_num[vout->cur_disp_output]];
- mm_segment_t old_fs;
- int ret = 0;
-
- if (fbi->fbops->fb_ioctl) {
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_BLANK,
- (unsigned int)(&vout->fb_blank));
- set_fs(old_fs);
- }
-
- return ret;
-}
-
static void mxc_v4l2out_timer_handler(unsigned long arg)
{
int index, ret;
@@ -450,22 +436,12 @@ static void mxc_v4l2out_timer_handler(unsigned long arg)
/* Handle ic bypass mode in work queue */
if (vout->ic_bypass) {
- if (queue_work(vout->v4l_wq, &vout->icbypass_work) == 0) {
- dev_err(&vout->video_dev->dev,
- "ic bypass work was in queue already!\n ");
+ if (queue_work(vout->v4l_wq, &vout->timer_work) == 0) {
+ dev_err(&vout->video_dev->dev, "work was in queue already!\n ");
vout->state = STATE_STREAM_PAUSED;
}
goto exit0;
- } else if (!vout->fb_blank &&
- (ipu_get_cur_buffer_idx(vout->display_ch, IPU_INPUT_BUFFER)
- == vout->next_disp_ipu_buf)) {
- dev_dbg(&vout->video_dev->dev, "IPU disp busy\n");
- get_cur_fb_blank(vout);
- index = peek_next_buf(&vout->ready_q);
- setup_next_buf_timer(vout, index);
- goto exit0;
}
- vout->fb_blank = 0;
/* Dequeue buffer and pass to IPU */
index = dequeue_buf(&vout->ready_q);
@@ -547,13 +523,10 @@ static void mxc_v4l2out_timer_handler(unsigned long arg)
goto exit0;
}
- /* Split mode use buf 0 only, no need swith buf */
+ /* Non IC split action */
if (!vout->pp_split)
vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
- /* Always assume display in double buffers */
- vout->next_disp_ipu_buf = !vout->next_disp_ipu_buf;
-
/* Setup timer for next buffer */
index = peek_next_buf(&vout->ready_q);
if (index != -1)
@@ -655,6 +628,13 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
if (ret < 0)
dev_err(&vout->video_dev->dev,
"unable to set IPU buffer ready\n");
+ vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
+
+ } else {/* last stripe is done, run display refresh */
+ select_display_buffer(vout, disp_buf_num);
+ vout->ipu_buf[vout->next_done_ipu_buf] = -1;
+ vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
+ vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
}
/* offset for next buffer's EBA */
@@ -696,8 +676,11 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
/* next stripe_buffer index 0..7 */
vout->pp_split_buf_num = (vout->pp_split_buf_num + vout->pp_split) & 0x7;
+
+
} else {
- disp_buf_num = vout->next_done_ipu_buf;
+ /* show to display */
+ select_display_buffer(vout, vout->next_done_ipu_buf);
ret += ipu_select_buffer(vout->display_input_ch, IPU_OUTPUT_BUFFER,
vout->next_done_ipu_buf);
}
@@ -705,7 +688,6 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
/* release buffer. For split mode: if second stripe is done */
release_buffer = vout->pp_split ? (!(vout->pp_split_buf_num & 0x3)) : 1;
if (release_buffer) {
- select_display_buffer(vout, disp_buf_num);
g_buf_output_cnt++;
vout->v4l2_bufs[last_buf].flags = V4L2_BUF_FLAG_DONE;
queue_buf(&vout->done_q, last_buf);
@@ -715,9 +697,7 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
vout->ipu_buf_p[vout->next_done_ipu_buf] = -1;
vout->ipu_buf_n[vout->next_done_ipu_buf] = -1;
}
- /* split mode use buf 0 only, no need switch buf */
- if (!vout->pp_split)
- vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
+ vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
}
} /* end of last_buf != -1 */
@@ -950,9 +930,6 @@ static int init_PP(ipu_channel_params_t *params, vout_data *vout,
u32 eba_offset;
u16 x_pos;
u16 y_pos;
- dma_addr_t phy_addr0;
- dma_addr_t phy_addr1;
-
eba_offset = 0;
x_pos = 0;
y_pos = 0;
@@ -1042,12 +1019,6 @@ static int init_PP(ipu_channel_params_t *params, vout_data *vout,
return -EINVAL;
}
- /* always enable double buffer */
- phy_addr0 = vout->v4l2_bufs[vout->ipu_buf[0]].m.offset;
- if (vout->ipu_buf[1] == -1)
- phy_addr1 = phy_addr0;
- else
- phy_addr1 = vout->v4l2_bufs[vout->ipu_buf[1]].m.offset;
if (ipu_init_channel_buffer(vout->post_proc_ch,
IPU_INPUT_BUFFER,
params->mem_pp_mem.in_pixel_fmt,
@@ -1057,8 +1028,8 @@ static int init_PP(ipu_channel_params_t *params, vout_data *vout,
bytes_per_pixel(params->mem_pp_mem.
in_pixel_fmt),
IPU_ROTATE_NONE,
- phy_addr0,
- phy_addr1,
+ vout->v4l2_bufs[vout->ipu_buf[0]].m.offset,
+ vout->v4l2_bufs[vout->ipu_buf[1]].m.offset,
vout->offset.u_offset,
vout->offset.v_offset) != 0) {
dev_err(dev, "Error initializing PP input buffer\n");
@@ -1223,10 +1194,8 @@ static int mxc_v4l2out_streamon(vout_data * vout)
g_irq_cnt = g_buf_output_cnt = g_buf_q_cnt = g_buf_dq_cnt = 0;
out_width = vout->crop_current.width;
out_height = vout->crop_current.height;
- vout->disp_buf_num = 0;
vout->next_done_ipu_buf = 0;
- vout->next_rdy_ipu_buf = vout->next_disp_ipu_buf = 1;
- vout->fb_blank = 0;
+ vout->next_rdy_ipu_buf = 1;
vout->pp_split = 0;
ipu_ic_out_max_height_size = 1024;
#ifdef CONFIG_MXC_IPU_V1
@@ -1241,12 +1210,12 @@ static int mxc_v4l2out_streamon(vout_data * vout)
(out_height > ipu_ic_out_max_height_size))
vout->pp_split = 4;
if (!INTERLACED_CONTENT(vout)) {
+ vout->next_done_ipu_buf = vout->next_rdy_ipu_buf = 0;
vout->ipu_buf[0] = dequeue_buf(&vout->ready_q);
/* split IC by two stripes, the by pass is impossible*/
if ((out_width != vout->v2f.fmt.pix.width ||
out_height != vout->v2f.fmt.pix.height) &&
vout->pp_split) {
- vout->next_done_ipu_buf = vout->next_rdy_ipu_buf = 0;
vout->ipu_buf[1] = vout->ipu_buf[0];
vout->frame_count = 1;
if ((out_width > ipu_ic_out_max_width_size) &&
@@ -1257,8 +1226,8 @@ static int mxc_v4l2out_streamon(vout_data * vout)
else
vout->pp_split = 3; /*2 vertical stripes*/
} else {
- vout->ipu_buf[1] = -1;
- vout->frame_count = 1;
+ vout->ipu_buf[1] = dequeue_buf(&vout->ready_q);
+ vout->frame_count = 2;
}
} else if (!LOAD_3FIELDS(vout)) {
vout->ipu_buf[0] = dequeue_buf(&vout->ready_q);
@@ -1492,8 +1461,13 @@ static int mxc_v4l2out_streamon(vout_data * vout)
ipu_enable_channel(MEM_VDI_PRP_VF_MEM_P);
ipu_enable_channel(MEM_VDI_PRP_VF_MEM_N);
ipu_select_multi_vdi_buffer(0);
- } else
+ } else if (INTERLACED_CONTENT(vout)) {
+ ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0);
+ } else {
ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0);
+ if (!vout->pp_split)
+ ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 1);
+ }
ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 0);
ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 1);
#ifdef CONFIG_MXC_IPU_V1
@@ -1503,6 +1477,9 @@ static int mxc_v4l2out_streamon(vout_data * vout)
ipu_update_channel_buffer(vout->display_ch,
IPU_INPUT_BUFFER,
0, vout->v4l2_bufs[vout->ipu_buf[0]].m.offset);
+ ipu_update_channel_buffer(vout->display_ch,
+ IPU_INPUT_BUFFER,
+ 1, vout->v4l2_bufs[vout->ipu_buf[1]].m.offset);
if (vout->offset.u_offset || vout->offset.v_offset)
/* only update u/v offset */
ipu_update_channel_offset(vout->display_ch,
@@ -1516,7 +1493,7 @@ static int mxc_v4l2out_streamon(vout_data * vout)
0,
0);
ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER, 0);
- queue_work(vout->v4l_wq, &vout->icbypass_work);
+ queue_work(vout->v4l_wq, &vout->timer_work);
}
vout->start_jiffies = jiffies;
@@ -1554,7 +1531,7 @@ static int mxc_v4l2out_streamoff(vout_data * vout)
ipu_free_irq(vout->work_irq, vout);
if (vout->ic_bypass)
- cancel_work_sync(&vout->icbypass_work);
+ cancel_work_sync(&vout->timer_work);
spin_lock_irqsave(&g_lock, lockflag);
@@ -1915,7 +1892,7 @@ static int mxc_v4l2out_open(struct file *file)
goto oops;
}
- INIT_WORK(&vout->icbypass_work, icbypass_work_func);
+ INIT_WORK(&vout->timer_work, timer_work_func);
}
file->private_data = dev;
diff --git a/drivers/media/video/mxc/output/mxc_v4l2_output.h b/drivers/media/video/mxc/output/mxc_v4l2_output.h
index c26194f5ff90..096dc3b17a06 100644
--- a/drivers/media/video/mxc/output/mxc_v4l2_output.h
+++ b/drivers/media/video/mxc/output/mxc_v4l2_output.h
@@ -79,9 +79,7 @@ typedef struct _vout_data {
struct timer_list output_timer;
struct workqueue_struct *v4l_wq;
- struct work_struct icbypass_work;
- int disp_buf_num;
- int fb_blank;
+ struct work_struct timer_work;
unsigned long start_jiffies;
u32 frame_count;
@@ -90,7 +88,6 @@ typedef struct _vout_data {
s8 next_rdy_ipu_buf;
s8 next_done_ipu_buf;
- s8 next_disp_ipu_buf;
s8 ipu_buf[2];
s8 ipu_buf_p[2];
s8 ipu_buf_n[2];
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 0bc2cf573c76..2bed9e22968b 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -5878,7 +5878,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
}
- mutex_lock(&ov->lock);
+ mutex_unlock(&ov->lock);
return 0;
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 50b415e07eda..f7f7e04cf485 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -753,7 +753,7 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
buf[0] = 0xff; /* fixed */
ret = send_control_msg(pdev,
- SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf));
+ SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, 1);
if (!mode && ret >= 0) {
if (value < 0)
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 9e3262c0ba37..2c0bb06cab3b 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -598,11 +598,6 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize)
buf = list_entry(dma_q->active.next,
struct s2255_buffer, vb.queue);
- if (!waitqueue_active(&buf->vb.done)) {
- /* no one active */
- rc = -1;
- goto unlock;
- }
list_del(&buf->vb.queue);
do_gettimeofday(&buf->vb.ts);
dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i);
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 6eebe3ef97d3..52a79b3f8a4a 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -3373,6 +3373,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_config = 3,
.mpeg = SAA7134_MPEG_DVB,
.ts_type = SAA7134_MPEG_TS_SERIAL,
+ .ts_force_val = 1,
.gpiomask = 0x0800100, /* GPIO 21 is an INPUT */
.inputs = {{
.name = name_tv,
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 6e219c2db841..69e48ceee27f 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -684,8 +684,6 @@ void saa7134_input_fini(struct saa7134_dev *dev)
void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
{
- struct i2c_board_info info;
- struct IR_i2c_init_data init_data;
const unsigned short addr_list[] = {
0x7a, 0x47, 0x71, 0x2d,
I2C_CLIENT_END
@@ -705,32 +703,32 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
return;
}
- memset(&info, 0, sizeof(struct i2c_board_info));
- memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ memset(&dev->info, 0, sizeof(dev->info));
+ memset(&dev->init_data, 0, sizeof(dev->init_data));
+ strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE);
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
case SAA7134_BOARD_PINNACLE_PCTV_310i:
- init_data.name = "Pinnacle PCTV";
+ dev->init_data.name = "Pinnacle PCTV";
if (pinnacle_remote == 0) {
- init_data.get_key = get_key_pinnacle_color;
- init_data.ir_codes = ir_codes_pinnacle_color;
+ dev->init_data.get_key = get_key_pinnacle_color;
+ dev->init_data.ir_codes = ir_codes_pinnacle_color;
} else {
- init_data.get_key = get_key_pinnacle_grey;
- init_data.ir_codes = ir_codes_pinnacle_grey;
+ dev->init_data.get_key = get_key_pinnacle_grey;
+ dev->init_data.ir_codes = ir_codes_pinnacle_grey;
}
break;
case SAA7134_BOARD_UPMOST_PURPLE_TV:
- init_data.name = "Purple TV";
- init_data.get_key = get_key_purpletv;
- init_data.ir_codes = ir_codes_purpletv;
+ dev->init_data.name = "Purple TV";
+ dev->init_data.get_key = get_key_purpletv;
+ dev->init_data.ir_codes = ir_codes_purpletv;
break;
case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
- init_data.name = "MSI TV@nywhere Plus";
- init_data.get_key = get_key_msi_tvanywhere_plus;
- init_data.ir_codes = ir_codes_msi_tvanywhere_plus;
- info.addr = 0x30;
+ dev->init_data.name = "MSI TV@nywhere Plus";
+ dev->init_data.get_key = get_key_msi_tvanywhere_plus;
+ dev->init_data.ir_codes = ir_codes_msi_tvanywhere_plus;
+ dev->info.addr = 0x30;
/* MSI TV@nywhere Plus controller doesn't seem to
respond to probes unless we read something from
an existing device. Weird...
@@ -741,9 +739,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
(1 == rc) ? "yes" : "no");
break;
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
- init_data.name = "HVR 1110";
- init_data.get_key = get_key_hvr1110;
- init_data.ir_codes = ir_codes_hauppauge_new;
+ dev->init_data.name = "HVR 1110";
+ dev->init_data.get_key = get_key_hvr1110;
+ dev->init_data.ir_codes = ir_codes_hauppauge_new;
break;
case SAA7134_BOARD_BEHOLD_607FM_MK3:
case SAA7134_BOARD_BEHOLD_607FM_MK5:
@@ -757,26 +755,26 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
case SAA7134_BOARD_BEHOLD_H6:
- init_data.name = "BeholdTV";
- init_data.get_key = get_key_beholdm6xx;
- init_data.ir_codes = ir_codes_behold;
+ dev->init_data.name = "BeholdTV";
+ dev->init_data.get_key = get_key_beholdm6xx;
+ dev->init_data.ir_codes = ir_codes_behold;
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
- info.addr = 0x40;
+ dev->info.addr = 0x40;
break;
}
- if (init_data.name)
- info.platform_data = &init_data;
+ if (dev->init_data.name)
+ dev->info.platform_data = &dev->init_data;
/* No need to probe if address is known */
- if (info.addr) {
- i2c_new_device(&dev->i2c_adap, &info);
+ if (dev->info.addr) {
+ i2c_new_device(&dev->i2c_adap, &dev->info);
return;
}
/* Address not known, fallback to probing */
- i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
+ i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list);
}
static int saa7134_rc5_irq(struct saa7134_dev *dev)
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 3fa652279ac0..03488ba4c99c 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -262,11 +262,13 @@ int saa7134_ts_start(struct saa7134_dev *dev)
switch (saa7134_boards[dev->board].ts_type) {
case SAA7134_MPEG_TS_PARALLEL:
saa_writeb(SAA7134_TS_SERIAL0, 0x40);
- saa_writeb(SAA7134_TS_PARALLEL, 0xec);
+ saa_writeb(SAA7134_TS_PARALLEL, 0xec |
+ (saa7134_boards[dev->board].ts_force_val << 4));
break;
case SAA7134_MPEG_TS_SERIAL:
saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
- saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+ saa_writeb(SAA7134_TS_PARALLEL, 0x6c |
+ (saa7134_boards[dev->board].ts_force_val << 4));
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
saa_writeb(SAA7134_TS_SERIAL1, 0x02);
break;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index fb564f14887c..f50734f39466 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -355,6 +355,7 @@ struct saa7134_board {
enum saa7134_mpeg_type mpeg;
enum saa7134_mpeg_ts_type ts_type;
unsigned int vid_port_opts;
+ unsigned int ts_force_val:1;
};
#define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name)
@@ -584,6 +585,10 @@ struct saa7134_dev {
int nosignal;
unsigned int insuspend;
+ /* I2C keyboard data */
+ struct i2c_board_info info;
+ struct IR_i2c_init_data init_data;
+
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 38a716020d7f..36ee43a9ee95 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -123,8 +123,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
-#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
+#endif
{ }
};
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 04b47832fa0a..5a8a8d1cc9c0 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -46,6 +46,7 @@
unsigned int uvc_no_drop_param;
static unsigned int uvc_quirks_param;
unsigned int uvc_trace_param;
+unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
/* ------------------------------------------------------------------------
* Video formats
@@ -2034,6 +2035,8 @@ module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(quirks, "Forced device quirks");
module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask");
+module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index be99c8797dcc..f2480c35c265 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -130,7 +130,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
- UVC_CTRL_STREAMING_TIMEOUT);
+ uvc_timeout_param);
if ((query == GET_MIN || query == GET_MAX) && ret == 2) {
/* Some cameras, mostly based on Bison Electronics chipsets,
@@ -235,7 +235,7 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video,
ret = __uvc_query_ctrl(video->dev, SET_CUR, 0,
video->streaming->intfnum,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
- UVC_CTRL_STREAMING_TIMEOUT);
+ uvc_timeout_param);
if (ret != size) {
uvc_printk(KERN_ERR, "Failed to set UVC %s control : "
"%d (exp. %u).\n", probe ? "probe" : "commit",
@@ -707,10 +707,6 @@ static void uvc_video_complete(struct urb *urb)
if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
ret);
- if (ret == -ENODEV) {
- uvc_queue_cancel(queue, 1);
- return;
- }
}
}
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 3c78d3c1e4c0..3265fbf3fc96 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -304,7 +304,7 @@ struct uvc_xu_control {
#define UVC_MAX_STATUS_SIZE 16
#define UVC_CTRL_CONTROL_TIMEOUT 300
-#define UVC_CTRL_STREAMING_TIMEOUT 1000
+#define UVC_CTRL_STREAMING_TIMEOUT 3000
/* Devices quirks */
#define UVC_QUIRK_STATUS_INTERVAL 0x00000001
@@ -695,6 +695,7 @@ struct uvc_driver {
extern unsigned int uvc_no_drop_param;
extern unsigned int uvc_trace_param;
+extern unsigned int uvc_timeout_param;
#define uvc_trace(flag, msg...) \
do { \
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 02f2a6d18b45..ec766937aff6 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -565,10 +565,9 @@ static noinline long v4l1_compat_get_input_info(
break;
}
chan->norm = 0;
- err = drv(file, VIDIOC_G_STD, &sid);
- if (err < 0)
- dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %ld\n", err);
- if (err == 0) {
+ /* Note: G_STD might not be present for radio receivers,
+ * so we should ignore any errors. */
+ if (drv(file, VIDIOC_G_STD, &sid) == 0) {
if (sid & V4L2_STD_PAL)
chan->norm = VIDEO_MODE_PAL;
if (sid & V4L2_STD_NTSC)
@@ -777,10 +776,9 @@ static noinline long v4l1_compat_get_tuner(
tun->flags |= VIDEO_TUNER_SECAM;
}
- err = drv(file, VIDIOC_G_STD, &sid);
- if (err < 0)
- dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %ld\n", err);
- if (err == 0) {
+ /* Note: G_STD might not be present for radio receivers,
+ * so we should ignore any errors. */
+ if (drv(file, VIDIOC_G_STD, &sid) == 0) {
if (sid & V4L2_STD_PAL)
tun->mode = VIDEO_MODE_PAL;
if (sid & V4L2_STD_NTSC)
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index dc4f32bbd83d..2ac8c2421ad2 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -319,7 +319,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
- &mem->dma_handle, GFP_DMA);
+ &mem->dma_handle, GFP_KERNEL);
if (!mem->vaddr) {
dev_err(q->dev, "dma_alloc_coherent size %ld failed\n",
mem->size);
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 5d0ba4f5924c..9ad7bb4e721f 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1015,9 +1015,9 @@ mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
{
SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
pSge->Address.Low = cpu_to_le32
- (lower_32_bits((unsigned long)(dma_addr)));
+ (lower_32_bits(dma_addr));
pSge->Address.High = cpu_to_le32
- (upper_32_bits((unsigned long)dma_addr));
+ (upper_32_bits(dma_addr));
pSge->FlagsLength = cpu_to_le32
((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
}
@@ -1038,8 +1038,8 @@ mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
u32 tmp;
pSge->Address.Low = cpu_to_le32
- (lower_32_bits((unsigned long)(dma_addr)));
- tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+ (lower_32_bits(dma_addr));
+ tmp = (u32)(upper_32_bits(dma_addr));
/*
* 1078 errata workaround for the 36GB limitation
@@ -1101,7 +1101,7 @@ mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
pChain->NextChainOffset = next;
pChain->Address.Low = cpu_to_le32(tmp);
- tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+ tmp = (u32)(upper_32_bits(dma_addr));
pChain->Address.High = cpu_to_le32(tmp);
}
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 13e7d7bfe85f..dd8b6b3ff1ea 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -643,7 +643,7 @@ struct ab3100_init_setting {
u8 setting;
};
-static const struct ab3100_init_setting __initdata
+static const struct ab3100_init_setting __initconst
ab3100_init_settings[] = {
{
.abreg = AB3100_MCA,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 72c10192d802..281b61b3b5f3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -13,10 +13,6 @@ menuconfig MISC_DEVICES
if MISC_DEVICES
-config ANDROID_PMEM
- bool "Android pmem allocator"
- default y
-
config ATMEL_PWM
tristate "Atmel AT32/AT91 PWM support"
depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
@@ -242,14 +238,6 @@ config MXS_PERSISTENT
depends on ARCH_MXS
default y
-config UID_STAT
- bool "UID based statistics tracking exported to /proc/uid_stat"
- default n
-
-config FSL_CACHE
- tristate "Freescale Cache manipulate driver"
- default n
-
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c435ec82d664..03dd5ee05ce2 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -21,8 +21,5 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
obj-$(CONFIG_ISL29003) += isl29003.o
obj-$(CONFIG_C2PORT) += c2port/
obj-$(CONFIG_MXS_PERSISTENT) += mxs-persistent.o
-obj-$(CONFIG_ANDROID_PMEM) += pmem.o
-obj-$(CONFIG_UID_STAT) += uid_stat.o
-obj-$(CONFIG_FSL_CACHE) += fsl_cache.o
obj-y += eeprom/
obj-y += cb710/
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 348443bdb23b..8393376b1080 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -362,6 +362,7 @@ static const char *const enclosure_status [] = {
[ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
[ENCLOSURE_STATUS_UNKNOWN] = "unknown",
[ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
+ [ENCLOSURE_STATUS_MAX] = NULL,
};
static const char *const enclosure_type [] = {
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index 9cbf95bedce6..de530d9942d2 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -161,14 +161,15 @@ static int options_show(struct seq_file *s, void *p)
static ssize_t options_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *data)
{
- unsigned long val;
- char buf[80];
+ char buf[20];
- if (strncpy_from_user(buf, userbuf, sizeof(buf) - 1) < 0)
+ if (count >= sizeof(buf))
+ return -EINVAL;
+ if (copy_from_user(buf, userbuf, count))
return -EFAULT;
- buf[count - 1] = '\0';
- if (!strict_strtoul(buf, 10, &val))
- gru_options = val;
+ buf[count] = '\0';
+ if (strict_strtoul(buf, 0, &gru_options))
+ return -EINVAL;
return count;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 2338c761c74f..abcd4392a8e9 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -179,11 +179,11 @@ static int mmc_read_ext_csd(struct mmc_card *card)
err = mmc_send_ext_csd(card, ext_csd);
if (err) {
- /*
- * We all hosts that cannot perform the command
- * to fail more gracefully
- */
- if (err != -EINVAL)
+ /* If the host or the card can't do the switch,
+ * fail more gracefully. */
+ if ((err != -EINVAL)
+ && (err != -ENOSYS)
+ && (err != -EFAULT))
goto out;
/*
@@ -225,10 +225,6 @@ static int mmc_read_ext_csd(struct mmc_card *card)
mmc_card_set_blockaddr(card);
}
- card->ext_csd.boot_info = ext_csd[EXT_CSD_BOOT_INFO];
- card->ext_csd.boot_size_mult = ext_csd[EXT_CSD_BOOT_SIZE_MULT];
- card->ext_csd.boot_config = ext_csd[EXT_CSD_BOOT_CONFIG];
- card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
card->ext_csd.card_type = ext_csd[EXT_CSD_CARD_TYPE];
switch (ext_csd[EXT_CSD_CARD_TYPE]) {
@@ -267,281 +263,6 @@ out:
return err;
}
-/* configure the boot partitions */
-static ssize_t
-setup_boot_partitions(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int err, busy = 0;
- u32 part, new_part;
- u8 *ext_csd, boot_config;
- struct mmc_command cmd;
- struct mmc_card *card = container_of(dev, struct mmc_card, dev);
-
- BUG_ON(!card);
-
- sscanf(buf, "%d\n", &part);
-
- if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
- printk(KERN_ERR "%s: invalid mmc version"
- " mmc version is below version 4!)\n",
- mmc_hostname(card->host));
- return -EINVAL;
- }
-
- /* it's a normal SD/MMC but user request to configure boot partition */
- if (card->ext_csd.boot_size_mult <= 0) {
- printk(KERN_ERR "%s: this is a normal SD/MMC card"
- " but you request to access boot partition!\n",
- mmc_hostname(card->host));
- return -EINVAL;
- }
-
- ext_csd = kmalloc(512, GFP_KERNEL);
- if (!ext_csd) {
- printk(KERN_ERR "%s: could not allocate a buffer to "
- "receive the ext_csd.\n", mmc_hostname(card->host));
- return -ENOMEM;
- }
-
- mmc_claim_host(card->host);
- err = mmc_send_ext_csd(card, ext_csd);
- if (err) {
- printk(KERN_ERR "%s: unable to read EXT_CSD.\n",
- mmc_hostname(card->host));
- goto err_rtn;
- }
-
- /* enable the boot partition in boot mode */
- /* boot enable be -
- * 0x00 - disable boot enable.
- * 0x08 - boot partition 1 is enabled for boot.
- * 0x10 - boot partition 2 is enabled for boot.
- * 0x38 - User area is enabled for boot.
- */
- switch (part & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) {
- case 0:
- boot_config = (ext_csd[EXT_CSD_BOOT_CONFIG]
- & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK
- & ~EXT_CSD_BOOT_ACK_ENABLE);
- break;
- case EXT_CSD_BOOT_PARTITION_PART1:
- boot_config = ((ext_csd[EXT_CSD_BOOT_CONFIG]
- & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
- | EXT_CSD_BOOT_PARTITION_PART1
- | EXT_CSD_BOOT_ACK_ENABLE);
- break;
- case EXT_CSD_BOOT_PARTITION_PART2:
- boot_config = ((ext_csd[EXT_CSD_BOOT_CONFIG]
- & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
- | EXT_CSD_BOOT_PARTITION_PART2
- | EXT_CSD_BOOT_ACK_ENABLE);
- break;
- case EXT_CSD_BOOT_PARTITION_ENABLE_MASK:
- boot_config = ((ext_csd[EXT_CSD_BOOT_CONFIG]
- | EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
- & ~EXT_CSD_BOOT_ACK_ENABLE);
- break;
- default:
- printk(KERN_ERR "%s: wrong boot config parameter"
- " 00 (disable boot), 08 (enable boot1),"
- "16 (enable boot2), 56 (User area)\n",
- mmc_hostname(card->host));
- err = -EINVAL;
- goto err_rtn;
- }
-
- /* switch the partitions that used to be accessed in OS layer */
- /* partition must be -
- * 0 - user area
- * 1 - boot partition 1
- * 2 - boot partition 2
- */
- if ((part & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) > 2) {
- printk(KERN_ERR "%s: wrong partition id"
- " 0 (user area), 1 (boot1), 2 (boot2)\n",
- mmc_hostname(card->host));
- err = -EINVAL;
- goto err_rtn;
- }
-
- /* Send SWITCH command to change partition for access */
- boot_config &= ~EXT_CSD_BOOT_PARTITION_ACCESS_MASK;
- boot_config |= (part & EXT_CSD_BOOT_PARTITION_ACCESS_MASK);
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BOOT_CONFIG, boot_config);
- if (err) {
- printk(KERN_ERR "%s: fail to send SWITCH command"
- " to card to swich partition for access!\n",
- mmc_hostname(card->host));
- goto err_rtn;
- }
-
- /* waiting for the card to finish the busy state */
- do {
- memset(&cmd, 0, sizeof(struct mmc_command));
-
- cmd.opcode = MMC_SEND_STATUS;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
- err = mmc_wait_for_cmd(card->host, &cmd, 0);
- if (err || busy > 100) {
- printk(KERN_ERR "%s: failed to wait for"
- "the busy state to end.\n",
- mmc_hostname(card->host));
- break;
- }
-
- if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
- printk(KERN_INFO "%s: card is in busy state"
- "pls wait for busy state to end.\n",
- mmc_hostname(card->host));
- }
- busy++;
- } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
-
- /* Now check whether it works */
- err = mmc_send_ext_csd(card, ext_csd);
- if (err) {
- printk(KERN_ERR "%s: %d unable to re-read EXT_CSD.\n",
- mmc_hostname(card->host), err);
- goto err_rtn;
- }
-
- new_part = ext_csd[EXT_CSD_BOOT_CONFIG] &
- EXT_CSD_BOOT_PARTITION_ACCESS_MASK;
- if ((part & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) != new_part) {
- printk(KERN_ERR "%s: after SWITCH, current part id %d is not"
- " same as requested partition %d!\n",
- mmc_hostname(card->host), new_part, part);
- goto err_rtn;
- }
- card->ext_csd.boot_config = ext_csd[EXT_CSD_BOOT_CONFIG];
-
-err_rtn:
- mmc_release_host(card->host);
- kfree(ext_csd);
- if (err)
- return err;
- else
- return count;
-}
-
-/* configure the boot bus */
-static ssize_t
-setup_boot_bus(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int err, busy = 0;
- u32 boot_bus, new_bus;
- u8 *ext_csd;
- struct mmc_command cmd;
- struct mmc_card *card = container_of(dev, struct mmc_card, dev);
-
- BUG_ON(!card);
-
- sscanf(buf, "%d\n", &boot_bus);
-
- if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
- printk(KERN_ERR "%s: invalid mmc version"
- " mmc version is below version 4!)\n",
- mmc_hostname(card->host));
- return -EINVAL;
- }
-
- /* it's a normal SD/MMC but user request to configure boot bus */
- if (card->ext_csd.boot_size_mult <= 0) {
- printk(KERN_ERR "%s: this is a normal SD/MMC card"
- " but you request to configure boot bus !\n",
- mmc_hostname(card->host));
- return -EINVAL;
- }
-
- ext_csd = kmalloc(512, GFP_KERNEL);
- if (!ext_csd) {
- printk(KERN_ERR "%s: could not allocate a buffer to "
- "receive the ext_csd.\n", mmc_hostname(card->host));
- return -ENOMEM;
- }
-
- mmc_claim_host(card->host);
- err = mmc_send_ext_csd(card, ext_csd);
- if (err) {
- printk(KERN_ERR "%s: unable to read EXT_CSD.\n",
- mmc_hostname(card->host));
- goto err_rtn;
- }
-
- /* Configure the boot bus width when boot partition is enabled */
- if (((boot_bus & EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK) >> 3) > 2
- || (boot_bus & EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK) > 2
- || (boot_bus & ~EXT_CSD_BOOT_BUS_WIDTH_MASK) > 0) {
- printk(KERN_ERR "%s: Invalid inputs!\n",
- mmc_hostname(card->host));
- err = -EINVAL;
- goto err_rtn;
- }
-
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BOOT_BUS_WIDTH, boot_bus);
- if (err) {
- printk(KERN_ERR "%s: fail to send SWITCH command to "
- "card to swich partition for access!\n",
- mmc_hostname(card->host));
- goto err_rtn;
- }
-
- /* waiting for the card to finish the busy state */
- do {
- memset(&cmd, 0, sizeof(struct mmc_command));
-
- cmd.opcode = MMC_SEND_STATUS;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
- err = mmc_wait_for_cmd(card->host, &cmd, 0);
- if (err || busy > 100) {
- printk(KERN_ERR "%s: failed to wait for"
- "the busy state to end.\n",
- mmc_hostname(card->host));
- break;
- }
-
- if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
- printk(KERN_INFO "%s: card is in busy state"
- "pls wait for busy state to end.\n",
- mmc_hostname(card->host));
- }
- busy++;
- } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
-
- /* Now check whether it works */
- err = mmc_send_ext_csd(card, ext_csd);
- if (err) {
- printk(KERN_ERR "%s: %d unable to re-read EXT_CSD.\n",
- mmc_hostname(card->host), err);
- goto err_rtn;
- }
-
- new_bus = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
- if (boot_bus != new_bus) {
- printk(KERN_ERR "%s: after SWITCH, current boot bus mode %d"
- " is not same as requested bus mode %d!\n",
- mmc_hostname(card->host), new_bus, boot_bus);
- goto err_rtn;
- }
- card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
-
-err_rtn:
- mmc_release_host(card->host);
- kfree(ext_csd);
- if (err)
- return err;
- else
- return count;
-}
-
MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
card->raw_cid[2], card->raw_cid[3]);
MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
@@ -553,12 +274,6 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
-MMC_DEV_ATTR(boot_info, "boot_info:0x%02x; boot_size:%04dKB;"
- " boot_partition:0x%02x; boot_bus:0x%02x\n",
- card->ext_csd.boot_info, card->ext_csd.boot_size_mult * 128,
- card->ext_csd.boot_config, card->ext_csd.boot_bus_width);
-DEVICE_ATTR(boot_config, S_IWUGO, NULL, setup_boot_partitions);
-DEVICE_ATTR(boot_bus_config, S_IWUGO, NULL, setup_boot_bus);
static struct attribute *mmc_std_attrs[] = {
&dev_attr_cid.attr,
@@ -570,9 +285,6 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_name.attr,
&dev_attr_oemid.attr,
&dev_attr_serial.attr,
- &dev_attr_boot_info.attr,
- &dev_attr_boot_config.attr,
- &dev_attr_boot_bus_config.attr,
NULL,
};
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 4a73e34f9200..c2a8cafd8276 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -210,11 +210,11 @@ static int mmc_read_switch(struct mmc_card *card)
err = mmc_sd_switch(card, 0, 0, 1, status);
if (err) {
- /*
- * We all hosts that cannot perform the command
- * to fail more gracefully
- */
- if (err != -EINVAL)
+ /* If the host or the card can't do the switch,
+ * fail more gracefully. */
+ if ((err != -EINVAL)
+ && (err != -ENOSYS)
+ && (err != -EFAULT))
goto out;
printk(KERN_WARNING "%s: problem reading switch "
diff --git a/drivers/mmc/host/mx_sdhci.c b/drivers/mmc/host/mx_sdhci.c
index 732135308eb6..0557d4d337c1 100644
--- a/drivers/mmc/host/mx_sdhci.c
+++ b/drivers/mmc/host/mx_sdhci.c
@@ -814,7 +814,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
host->plat_data->clk_flg = 1;
}
}
-
if (clock == host->clock && !(ios.bus_width & MMC_BUS_WIDTH_DDR))
return;
@@ -854,20 +853,85 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
DBG("prescaler = 0x%x, divider = 0x%x\n", prescaler, div);
clk |= (prescaler << 8) | (div << 4);
- if (host->plat_data->clk_always_on
- | (host->mmc->card && mmc_card_sdio(host->mmc->card)))
- clk |= SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_HLK_EN
- | SDHCI_CLOCK_IPG_EN;
- else
- clk &= ~(SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_HLK_EN
- | SDHCI_CLOCK_IPG_EN);
+ /* Configure the DLL when DDR mode is enabled */
+ if (ios.bus_width & MMC_BUS_WIDTH_DDR) {
+ /* Make sure that the PER, HLK, IPG are all enabled */
+ writel(readl(host->ioaddr + SDHCI_CLOCK_CONTROL)
+ | SDHCI_CLOCK_IPG_EN
+ | SDHCI_CLOCK_HLK_EN
+ | SDHCI_CLOCK_PER_EN,
+ host->ioaddr + SDHCI_CLOCK_CONTROL);
- /* Configure the clock delay line */
- if ((host->plat_data->vendor_ver >= ESDHC_VENDOR_V3)
- && host->plat_data->dll_override_en)
- writel((host->plat_data->dll_delay_cells << 10)
- | DLL_CTRL_SLV_OVERRIDE,
- host->ioaddr + SDHCI_DLL_CONTROL);
+ /* Enable the DLL and delay chain */
+ writel(readl(host->ioaddr + SDHCI_DLL_CONTROL)
+ | DLL_CTRL_ENABLE,
+ host->ioaddr + SDHCI_DLL_CONTROL);
+
+ timeout = 1000000;
+ while (timeout > 0) {
+ timeout--;
+ if (readl(host->ioaddr + SDHCI_DLL_STATUS)
+ & DLL_STS_REF_LOCK)
+ break;
+ else if (timeout == 0)
+ printk(KERN_ERR "DLL REF LOCK Timeout!\n");
+ };
+ DBG("dll stat: 0x%x\n", readl(host->ioaddr + SDHCI_DLL_STATUS));
+
+ writel(readl(host->ioaddr + SDHCI_DLL_CONTROL)
+ | DLL_CTRL_SLV_UP_INT | DLL_CTRL_REF_UP_INT
+ | DLL_CTRL_SLV_DLY_TAR,
+ host->ioaddr + SDHCI_DLL_CONTROL);
+
+ timeout = 1000000;
+ while (timeout > 0) {
+ timeout--;
+ if (readl(host->ioaddr + SDHCI_DLL_STATUS)
+ & DLL_STS_SLV_LOCK)
+ break;
+ else if (timeout == 0)
+ printk(KERN_ERR "DLL SLV LOCK Timeout!\n");
+ };
+
+ writel(readl(host->ioaddr + SDHCI_DLL_CONTROL)
+ | DLL_CTRL_SLV_FORCE_UPD,
+ host->ioaddr + SDHCI_DLL_CONTROL);
+
+ writel(readl(host->ioaddr + SDHCI_DLL_CONTROL)
+ & (~DLL_CTRL_SLV_FORCE_UPD),
+ host->ioaddr + SDHCI_DLL_CONTROL);
+
+ timeout = 1000000;
+ while (timeout > 0) {
+ timeout--;
+ if (readl(host->ioaddr + SDHCI_DLL_STATUS)
+ & DLL_STS_REF_LOCK)
+ break;
+ else if (timeout == 0)
+ printk(KERN_ERR "DLL REF LOCK Timeout!\n");
+ };
+ timeout = 1000000;
+ while (timeout > 0) {
+ timeout--;
+ if (readl(host->ioaddr + SDHCI_DLL_STATUS)
+ & DLL_STS_SLV_LOCK)
+ break;
+ else if (timeout == 0)
+ printk(KERN_ERR "DLL SLV LOCK Timeout!\n");
+ };
+ DBG("dll stat: 0x%x\n", readl(host->ioaddr + SDHCI_DLL_STATUS));
+
+ /* Let the PER, HLK, IPG to be auto-gate */
+ writel(readl(host->ioaddr + SDHCI_CLOCK_CONTROL)
+ & ~(SDHCI_CLOCK_IPG_EN | SDHCI_CLOCK_HLK_EN
+ | SDHCI_CLOCK_PER_EN),
+ host->ioaddr + SDHCI_CLOCK_CONTROL);
+
+ } else if (readl(host->ioaddr + SDHCI_DLL_STATUS) & DLL_STS_SLV_LOCK) {
+ /* reset DLL CTRL */
+ writel(readl(host->ioaddr + SDHCI_DLL_CONTROL) | DLL_CTRL_RESET,
+ host->ioaddr + SDHCI_DLL_CONTROL);
+ }
/* Configure the clock control register */
clk |=
@@ -1093,7 +1157,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct sdhci_host *host;
unsigned long flags;
- u32 ier, prot, present;
+ u32 ier, prot, clk, present;
host = mmc_priv(mmc);
@@ -1106,12 +1170,19 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
if (--(host->sdio_enable))
goto exit_unlock;
}
-
- ier = readl(host->ioaddr + SDHCI_INT_ENABLE);
+ /* Enable the clock */
+ if (!host->plat_data->clk_flg) {
+ clk_enable(host->clk);
+ host->plat_data->clk_flg = 1;
+ }
+ ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
prot = readl(host->ioaddr + SDHCI_HOST_CONTROL);
+ clk = readl(host->ioaddr + SDHCI_CLOCK_CONTROL);
if (enable) {
ier |= SDHCI_INT_CARD_INT;
+ prot |= SDHCI_CTRL_D3CD;
+ clk |= SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_IPG_EN;
present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
if ((present & SDHCI_CARD_INT_MASK) != SDHCI_CARD_INT_ID)
writel(SDHCI_INT_CARD_INT,
@@ -1119,24 +1190,12 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
} else {
ier &= ~SDHCI_INT_CARD_INT;
prot &= ~SDHCI_CTRL_D3CD;
+ clk &= ~(SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_IPG_EN);
}
writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
- writel(ier, host->ioaddr + SDHCI_INT_ENABLE);
writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
-
- /*
- * Using D3CD to manually driver the HW to re-sample the SDIO interrupt
- * on bus one more time to guarantee the SDIO interrupt signal sent
- * from card during the interrupt signal disabled period will not
- * be lost.
- */
- prot |= SDHCI_CTRL_CDSS;
- writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
- prot &= ~SDHCI_CTRL_D3CD;
- writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
- prot |= SDHCI_CTRL_D3CD;
- writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
+ writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
mmiowb();
exit_unlock:
@@ -1262,7 +1321,7 @@ static void sdhci_tasklet_finish(unsigned long param)
* The root cause is that the ROM code don't ensure
* the SD/MMC clk is running when boot system.
* */
- if (req_done && host->plat_data->clk_flg &&
+ if (!machine_is_mx35_3ds() && req_done && host->plat_data->clk_flg &&
!(host->mmc && host->mmc->card && mmc_card_sdio(host->mmc->card))) {
clk_disable(host->clk);
host->plat_data->clk_flg = 0;
@@ -1840,10 +1899,8 @@ static int __devinit sdhci_probe_slot(struct platform_device
/* Get the SDHC clock from clock system APIs */
host->clk = clk_get(&pdev->dev, mmc_plat->clock_mmc);
- if (NULL == host->clk) {
+ if (NULL == host->clk)
printk(KERN_ERR "MXC MMC can't get clock.\n");
- goto out1;
- }
DBG("SDHC:%d clock:%lu\n", pdev->id, clk_get_rate(host->clk));
host->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2057,6 +2114,9 @@ static int __devinit sdhci_probe_slot(struct platform_device
}
mxc_dma_callback_set(host->dma, sdhci_dma_irq, (void *)host);
}
+#ifdef CONFIG_MMC_DEBUG
+ sdhci_dumpregs(host);
+#endif
mmiowb();
diff --git a/drivers/mmc/host/mx_sdhci.h b/drivers/mmc/host/mx_sdhci.h
index 83d02975ecd1..fa36dff0fd9a 100644
--- a/drivers/mmc/host/mx_sdhci.h
+++ b/drivers/mmc/host/mx_sdhci.h
@@ -69,7 +69,6 @@
#define SDHCI_CTRL_4BITBUS 0x00000002
#define SDHCI_CTRL_8BITBUS 0x00000004
#define SDHCI_CTRL_HISPD 0x00000004
-#define SDHCI_CTRL_CDSS 0x80
#define SDHCI_CTRL_DMA_MASK 0x18
#define SDHCI_CTRL_SDMA 0x00
#define SDHCI_CTRL_ADMA1 0x08
@@ -194,7 +193,6 @@
#define DLL_CTRL_ENABLE 0x00000001
#define DLL_CTRL_RESET 0x00000002
#define DLL_CTRL_SLV_FORCE_UPD 0x00000004
-#define DLL_CTRL_SLV_OVERRIDE 0x00000200
#define DLL_CTRL_SLV_DLY_TAR 0x00000000
#define DLL_CTRL_SLV_UP_INT 0x00200000
#define DLL_CTRL_REF_UP_INT 0x20000000
@@ -221,7 +219,6 @@ enum {
#define SDHCI_SPEC_100 0
#define SDHCI_SPEC_200 1
#define ESDHC_VENDOR_V22 0x12
-#define ESDHC_VENDOR_V3 0x13
struct sdhci_chip;
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index b7210b7d7af3..b849e873613b 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -49,7 +49,7 @@
#define MXS_MMC_DETECT_TIMEOUT (HZ/2)
/* Max value supported for XFER_COUNT */
-#define SSP_BUFFER_SIZE (65535)
+#define SSP_BUFFER_SIZE (65536)
#ifndef BF
#define BF(value, field) (((value) << BP_##field) & BM_##field)
@@ -93,9 +93,6 @@
#define BF_SSP_BLOCK_SIZE_BLOCK_SIZE(v) \
(((v) << 16) & BM_SSP_BLOCK_SIZE_BLOCK_SIZE)
#endif
-#ifndef BM_SSP_CMD0_DBL_DATA_RATE_EN
-#define BM_SSP_CMD0_DBL_DATA_RATE_EN 0x02000000
-#endif
struct mxs_mmc_host {
struct device *dev;
@@ -162,7 +159,6 @@ static inline int mxs_mmc_is_plugged(struct mxs_mmc_host *host)
return !(status & BM_SSP_STATUS_CARD_DETECT);
}
-static void mxs_mmc_reset(struct mxs_mmc_host *host);
/* Card detection polling function */
static void mxs_mmc_detect_poll(unsigned long arg)
{
@@ -171,8 +167,6 @@ static void mxs_mmc_detect_poll(unsigned long arg)
card_status = mxs_mmc_is_plugged(host);
if (card_status != host->present) {
- /* Reset MMC block */
- mxs_mmc_reset(host);
host->present = card_status;
mmc_detect_change(host->mmc, 0);
}
@@ -558,9 +552,6 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
dev_dbg(host->dev, "%s blksz is 0x%x.\n", __func__, log2_block_size);
if (ssp_ver_major > 3) {
- /* Configure the CMD0 */
- ssp_cmd0 = BF(cmd->opcode, SSP_CMD0_CMD);
-
/* Configure the BLOCK SIZE and BLOCK COUNT */
if ((1<<log2_block_size) != cmd->data->blksz) {
BUG_ON(cmd->data->blocks > 1);
@@ -569,13 +560,9 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
val = BF(log2_block_size, SSP_BLOCK_SIZE_BLOCK_SIZE) |
BF(cmd->data->blocks - 1, SSP_BLOCK_SIZE_BLOCK_COUNT);
__raw_writel(val, host->ssp_base + HW_SSP_BLOCK_SIZE);
- if (host->mmc->ios.bus_width & MMC_BUS_WIDTH_DDR)
- /* Enable the DDR mode */
- ssp_cmd0 |= BM_SSP_CMD0_DBL_DATA_RATE_EN;
- else
- ssp_cmd0 &= ~BM_SSP_CMD0_DBL_DATA_RATE_EN;
-
}
+ /* Configure the CMD0 */
+ ssp_cmd0 = BF(cmd->opcode, SSP_CMD0_CMD);
} else {
if ((1<<log2_block_size) != cmd->data->blksz) {
BUG_ON(cmd->data->blocks > 1);
@@ -818,9 +805,9 @@ static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
dev_warn(host->dev,
"Platform does not support CMD pin pullup control\n");
- if ((ios->bus_width & ~MMC_BUS_WIDTH_DDR) == MMC_BUS_WIDTH_8)
+ if (ios->bus_width == MMC_BUS_WIDTH_8)
host->bus_width = 2;
- else if ((ios->bus_width & ~MMC_BUS_WIDTH_DDR) == MMC_BUS_WIDTH_4)
+ else if (ios->bus_width == MMC_BUS_WIDTH_4)
host->bus_width = 1;
else
host->bus_width = 0;
@@ -892,6 +879,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
/* Configure SSP Control Register 1 */
ssp_ctrl1 =
BM_SSP_CTRL1_DMA_ENABLE |
+ BM_SSP_CTRL1_POLARITY |
BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index e55ac792d68c..c8c0a7e4f0af 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -694,14 +694,14 @@ static int pxamci_remove(struct platform_device *pdev)
if (mmc) {
struct pxamci_host *host = mmc_priv(mmc);
+ mmc_remove_host(mmc);
+
if (host->vcc)
regulator_put(host->vcc);
if (host->pdata && host->pdata->exit)
host->pdata->exit(&pdev->dev, mmc);
- mmc_remove_host(mmc);
-
pxamci_stop_clock(host);
writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 61ea833e0908..94bb61e19047 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -282,16 +282,6 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
}
}
-static void fixup_M29W128G_write_buffer(struct mtd_info *mtd, void *param)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- if (cfi->cfiq->BufWriteTimeoutTyp) {
- pr_warning("Don't use write buffer on ST flash M29W128G\n");
- cfi->cfiq->BufWriteTimeoutTyp = 0;
- }
-}
-
static struct cfi_fixup cfi_fixup_table[] = {
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
#ifdef AMD_BOOTLOC_BUG
@@ -308,7 +298,6 @@ static struct cfi_fixup cfi_fixup_table[] = {
{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
- { CFI_MFR_ST, 0x227E, fixup_M29W128G_write_buffer, NULL, },
#if !FORCE_WORD_WRITE
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
#endif
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index 34d40e25d312..c5a84fda5410 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -81,6 +81,10 @@ void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
{
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);
+ /* M29W128G flashes require an additional reset command
+ when exit qry mode */
+ if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
}
EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1a85f6d5543b..3fe91622b400 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -436,7 +436,7 @@ config MXC_NAND_LOW_LEVEL_ERASE
config MTD_NAND_GPMI_NFC
tristate "GPMI NAND Flash Controller driver"
- depends on MTD_NAND && (ARCH_MX23 || ARCH_MX28 || ARCH_MX50)
+ depends on MTD_NAND && (ARCH_MX23 || ARCH_MX28)
help
Enables NAND Flash support.
diff --git a/drivers/mtd/nand/gpmi-nfc/Makefile b/drivers/mtd/nand/gpmi-nfc/Makefile
index 9df1b6454e90..e3d5660735b6 100644
--- a/drivers/mtd/nand/gpmi-nfc/Makefile
+++ b/drivers/mtd/nand/gpmi-nfc/Makefile
@@ -4,7 +4,6 @@ gpmi-nfc-objs += gpmi-nfc-event-reporting.o
gpmi-nfc-objs += gpmi-nfc-hal-common.o
gpmi-nfc-objs += gpmi-nfc-hal-v0.o
gpmi-nfc-objs += gpmi-nfc-hal-v1.o
-gpmi-nfc-objs += gpmi-nfc-hal-v2.o
gpmi-nfc-objs += gpmi-nfc-rom-common.o
gpmi-nfc-objs += gpmi-nfc-rom-v0.o
gpmi-nfc-objs += gpmi-nfc-rom-v1.o
diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-main.c b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-main.c
index 54df1f084509..0143f1c358ff 100644
--- a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-main.c
+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-main.c
@@ -42,12 +42,8 @@ static struct gpmi_nfc_timing safe_timing = {
*/
static struct nfc_hal *(nfc_hals[]) = {
- /* i.mx23 */
&gpmi_nfc_hal_v0,
- /* i.mx28 */
&gpmi_nfc_hal_v1,
- /* i.mx50 */
- &gpmi_nfc_hal_v2,
};
/*
@@ -1255,54 +1251,40 @@ static void release_register_block(struct gpmi_nfc_data *this,
* @resource_name: The name of the resource.
* @interrupt_handler: A pointer to the function that will handle interrupts
* from this interrupt number.
- * @lno: A pointer to a variable that will receive the acquired
- * interrupt number(low part).
- * @hno: A pointer to a variable that will receive the acquired
- * interrupt number(high part).
+ * @interrupt_number: A pointer to a variable that will receive the acquired
+ * interrupt number.
*/
static int acquire_interrupt(
struct gpmi_nfc_data *this, const char *resource_name,
- irq_handler_t interrupt_handler, int *lno, int *hno)
+ irq_handler_t interrupt_handler, int *interrupt_number)
{
struct platform_device *pdev = this->pdev;
struct device *dev = this->dev;
int error = 0;
- struct resource *r;
int i;
/* Attempt to get information about the given resource. */
- r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, resource_name);
+ i = platform_get_irq_byname(pdev, resource_name);
- if (!r) {
+ if (i < 0) {
dev_err(dev, "Can't get resource information for '%s'\n",
resource_name);
return -ENXIO;
}
/* Attempt to own the interrupt. */
- for (i = r->start; i <= r->end; i++) {
- error = request_irq(i, interrupt_handler, 0,
- resource_name, this);
-
- if (error) {
- dev_err(dev, "Can't own %s\n", resource_name);
- /* Free all the irq's we've already acquired. */
+ error = request_irq(i, interrupt_handler, 0, resource_name, this);
- while ((i - r->start) >= 0) {
- free_irq(i, this);
- i--;
- }
-
- return -EIO;
- }
+ if (error) {
+ dev_err(dev, "Can't own %s\n", resource_name);
+ return -EIO;
}
/* If control arrives here, everything went fine. */
- *lno = r->start;
- *hno = r->end;
+ *interrupt_number = i;
return 0;
@@ -1314,12 +1296,9 @@ static int acquire_interrupt(
* @this: Per-device data.
* @interrupt_number: The interrupt number.
*/
-static void release_interrupt(struct gpmi_nfc_data *this,
- int low_interrupt_number, int high_interrupt_number)
+static void release_interrupt(struct gpmi_nfc_data *this, int interrupt_number)
{
- int i;
- for (i = low_interrupt_number; i <= high_interrupt_number; i++)
- free_irq(i, this);
+ free_irq(interrupt_number, this);
}
/**
@@ -1488,9 +1467,7 @@ static int acquire_resources(struct gpmi_nfc_data *this)
error = acquire_interrupt(this,
GPMI_NFC_BCH_INTERRUPT_RES_NAME,
- gpmi_nfc_bch_isr,
- &(resources->bch_low_interrupt),
- &(resources->bch_high_interrupt));
+ gpmi_nfc_bch_isr, &(resources->bch_interrupt));
if (error)
goto exit_bch_interrupt;
@@ -1508,9 +1485,7 @@ static int acquire_resources(struct gpmi_nfc_data *this)
error = acquire_interrupt(this,
GPMI_NFC_DMA_INTERRUPT_RES_NAME,
- gpmi_nfc_dma_isr,
- &(resources->dma_low_interrupt),
- &(resources->dma_high_interrupt));
+ gpmi_nfc_dma_isr, &(resources->dma_interrupt));
if (error)
goto exit_dma_interrupt;
@@ -1529,14 +1504,12 @@ static int acquire_resources(struct gpmi_nfc_data *this)
/* Control arrives here if something went wrong. */
exit_clock:
- release_interrupt(this,
- resources->dma_low_interrupt, resources->dma_high_interrupt);
+ release_interrupt(this, resources->dma_interrupt);
exit_dma_interrupt:
release_dma_channels(this,
resources->dma_low_channel, resources->dma_high_channel);
exit_dma_channels:
- release_interrupt(this,
- resources->bch_low_interrupt, resources->bch_high_interrupt);
+ release_interrupt(this, resources->bch_interrupt);
exit_bch_interrupt:
release_register_block(this, resources->bch_regs);
exit_bch_regs:
@@ -1559,12 +1532,10 @@ static void release_resources(struct gpmi_nfc_data *this)
release_clock(this, resources->clock);
release_register_block(this, resources->gpmi_regs);
release_register_block(this, resources->bch_regs);
- release_interrupt(this,
- resources->bch_low_interrupt, resources->bch_low_interrupt);
+ release_interrupt(this, resources->bch_interrupt);
release_dma_channels(this,
resources->dma_low_channel, resources->dma_high_channel);
- release_interrupt(this,
- resources->dma_low_interrupt, resources->dma_high_interrupt);
+ release_interrupt(this, resources->dma_interrupt);
}
/**
diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-mil.c b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-mil.c
index 50ba771853a4..34505b8e6546 100644
--- a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-mil.c
+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-mil.c
@@ -172,8 +172,8 @@ static int mil_incoming_buffer_dma_begin(struct gpmi_nfc_data *this,
* If we can, we want to use the caller's buffer directly for DMA. Check
* if the system will let us map them.
*/
- if (map_io_buffers && virt_addr_valid(destination) &&
- !((int)destination & 0x3) && 0)
+
+ if (map_io_buffers && virt_addr_valid(destination))
destination_phys =
dma_map_single(dev,
(void *) destination, length, DMA_FROM_DEVICE);
@@ -385,7 +385,6 @@ static void mil_select_chip(struct mtd_info *mtd, int chip)
gpmi_nfc_add_event("< mil_select_chip", -1);
} else if ((mil->current_chip >= 0) && (chip < 0)) {
gpmi_nfc_add_event("> mil_select_chip", 1);
- gpmi_nfc_add_event("> not disable clk", 1);
clk_disable(clock);
nfc->end(this);
gpmi_nfc_stop_event_trace("< mil_select_chip");
@@ -422,6 +421,7 @@ static void mil_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
gpmi_nfc_add_event("> mil_read_buf", 1);
/* Set up DMA. */
+
error = mil_incoming_buffer_dma_begin(this, buf, len,
mil->payload_virt, mil->payload_phys,
nfc_geo->payload_size_in_bytes,
@@ -1413,12 +1413,6 @@ static int mil_set_geometry(struct gpmi_nfc_data *this)
struct nfc_geometry *nfc_geo = &this->nfc_geometry;
struct mil *mil = &this->mil;
-
- /* Free the memory for read ID case */
- if (mil->page_buffer_virt && virt_addr_valid(mil->page_buffer_virt))
- dma_free_coherent(dev, nfc_geo->payload_size_in_bytes,
- mil->page_buffer_virt, mil->page_buffer_phys);
-
/* Set up the various layers of geometry, in this specific order. */
if (mil_set_physical_geometry(this))
@@ -2505,27 +2499,8 @@ int gpmi_nfc_mil_init(struct gpmi_nfc_data *this)
dma_alloc_coherent(dev,
MIL_COMMAND_BUFFER_SIZE, &mil->cmd_phys, GFP_DMA);
- if (!mil->cmd_virt) {
- error = -ENOMEM;
+ if (!mil->cmd_virt)
goto exit_cmd_allocation;
- }
-
-
- /* Allocate buf read ID case */
- this->nfc_geometry.payload_size_in_bytes = 1024;
- mil->page_buffer_virt =
- dma_alloc_coherent(dev,
- this->nfc_geometry.payload_size_in_bytes,
- &mil->page_buffer_phys, GFP_DMA);
-
- if (!mil->page_buffer_virt) {
- error = -ENOMEM;
- goto exit_buf_allocation;
- }
-
- /* Slice up the page buffer. */
- mil->payload_virt = mil->page_buffer_virt;
- mil->payload_phys = mil->page_buffer_phys;
/*
* Ask the NAND Flash system to scan for chips.
@@ -2574,14 +2549,8 @@ int gpmi_nfc_mil_init(struct gpmi_nfc_data *this)
exit_partitions:
nand_release(&mil->mtd);
exit_nand_scan:
- dma_free_coherent(dev,
- this->nfc_geometry.payload_size_in_bytes,
- mil->page_buffer_virt, mil->page_buffer_phys);
- mil->page_buffer_virt = 0;
- mil->page_buffer_phys = ~0;
-exit_buf_allocation:
dma_free_coherent(dev, MIL_COMMAND_BUFFER_SIZE,
- mil->cmd_virt, mil->cmd_phys);
+ mil->cmd_virt, mil->cmd_phys);
mil->cmd_virt = 0;
mil->cmd_phys = ~0;
exit_cmd_allocation:
diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
index 9b0074532917..6f14b73dd93d 100644
--- a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
@@ -44,6 +44,7 @@
#include <mach/system.h>
#include <mach/dmaengine.h>
+#include <mach/device.h>
#include <mach/clock.h>
/* Driver header files. */
@@ -85,12 +86,10 @@
struct resources {
void *gpmi_regs;
void *bch_regs;
- unsigned int bch_low_interrupt;
- unsigned int bch_high_interrupt;
+ unsigned int bch_interrupt;
unsigned int dma_low_channel;
unsigned int dma_high_channel;
- unsigned int dma_low_interrupt;
- unsigned int dma_high_interrupt;
+ unsigned int dma_interrupt;
struct clk *clock;
};
@@ -626,7 +625,6 @@ extern int gpmi_nfc_compute_hardware_timing(struct gpmi_nfc_data *this,
extern struct nfc_hal gpmi_nfc_hal_v0;
extern struct nfc_hal gpmi_nfc_hal_v1;
-extern struct nfc_hal gpmi_nfc_hal_v2;
/* Boot ROM Helper Common Services */
diff --git a/drivers/mtd/nand/mxc_nd2.c b/drivers/mtd/nand/mxc_nd2.c
index 80533ac42e9c..5ace73501cbb 100644
--- a/drivers/mtd/nand/mxc_nd2.c
+++ b/drivers/mtd/nand/mxc_nd2.c
@@ -32,7 +32,6 @@
/* Global address Variables */
static void __iomem *nfc_axi_base, *nfc_ip_base;
-static int nfc_irq;
struct mxc_mtd_s {
struct mtd_info mtd;
@@ -40,7 +39,6 @@ struct mxc_mtd_s {
struct mtd_partition *parts;
struct device *dev;
int disable_bi_swap; /* disable bi swap */
- int clk_active;
};
static struct mxc_mtd_s *mxc_nand_data;
@@ -842,30 +840,6 @@ static int mxc_nand_verify_buf(struct mtd_info *mtd, const u_char * buf,
}
/*!
- * This function will enable NFC clock
- *
- */
-static inline void mxc_nand_clk_enable(void)
-{
- if (!mxc_nand_data->clk_active) {
- clk_enable(nfc_clk);
- mxc_nand_data->clk_active = 1;
- }
-}
-
-/*!
- * This function will disable NFC clock
- *
- */
-static inline void mxc_nand_clk_disable(void)
-{
- if (mxc_nand_data->clk_active) {
- clk_disable(nfc_clk);
- mxc_nand_data->clk_active = 0;
- }
-}
-
-/*!
* This function is used by upper layer for select and deselect of the NAND
* chip
*
@@ -878,14 +852,13 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
switch (chip) {
case -1:
/* Disable the NFC clock */
- mxc_nand_clk_disable();
-
+ clk_disable(nfc_clk);
break;
- case 0 ... NFC_GET_MAXCHIP_SP():
+ case 0 ... 7:
/* Enable the NFC clock */
- mxc_nand_clk_enable();
- NFC_SET_NFC_ACTIVE_CS(chip);
+ clk_enable(nfc_clk);
+ NFC_SET_NFC_ACTIVE_CS(chip);
break;
default:
@@ -1257,10 +1230,9 @@ static int mxc_get_resources(struct platform_device *pdev)
error = -ENXIO;
goto out_2;
}
- nfc_irq = r->start;
init_waitqueue_head(&irq_waitq);
- error = request_irq(nfc_irq, mxc_nfc_irq, 0, "mxc_nd", NULL);
+ error = request_irq(r->start, mxc_nfc_irq, 0, "mxc_nd", NULL);
if (error)
goto out_3;
@@ -1526,7 +1498,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
nfc_clk = clk_get(&pdev->dev, "nfc_clk");
clk_enable(nfc_clk);
- mxc_nand_data->clk_active = 1;
if (hardware_ecc) {
this->ecc.read_page = mxc_nand_read_page;
@@ -1622,13 +1593,13 @@ static int __exit mxcnd_remove(struct platform_device *pdev)
manage_sysfs_files(false);
mxc_free_buf();
- mxc_nand_clk_disable();
+ clk_disable(nfc_clk);
clk_put(nfc_clk);
platform_set_drvdata(pdev, NULL);
if (mxc_nand_data) {
nand_release(mtd);
- free_irq(nfc_irq, NULL);
+ free_irq(MXC_INT_NANDFC, NULL);
kfree(mxc_nand_data);
}
@@ -1653,7 +1624,7 @@ static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2 : NAND suspend\n");
/* Disable the NFC clock */
- mxc_nand_clk_disable();
+ clk_disable(nfc_clk);
return 0;
}
@@ -1672,7 +1643,7 @@ static int mxcnd_resume(struct platform_device *pdev)
DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2 : NAND resume\n");
/* Enable the NFC clock */
- mxc_nand_clk_enable();
+ clk_enable(nfc_clk);
return 0;
}
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 89bf85af642c..40b5658bdbe6 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -102,8 +102,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
wmb();
ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
/* The NDFC uses Smart Media (SMC) bytes order */
- ecc_code[0] = p[2];
- ecc_code[1] = p[1];
+ ecc_code[0] = p[1];
+ ecc_code[1] = p[2];
ecc_code[2] = p[3];
return 0;
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 3e164f0c9295..62d6a78c4eee 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -46,21 +46,12 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
const u32 *reg;
int len;
- /* check if this is a partition node */
- partname = of_get_property(pp, "name", &len);
- if (strcmp(partname, "partition") != 0) {
+ reg = of_get_property(pp, "reg", &len);
+ if (!reg) {
nr_parts--;
continue;
}
- reg = of_get_property(pp, "reg", &len);
- if (!reg || (len != 2 * sizeof(u32))) {
- of_node_put(pp);
- dev_err(dev, "Invalid 'reg' on %s\n", node->full_name);
- kfree(*pparts);
- *pparts = NULL;
- return -EINVAL;
- }
(*pparts)[i].offset = reg[0];
(*pparts)[i].size = reg[1];
@@ -75,6 +66,14 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
i++;
}
+ if (!i) {
+ of_node_put(pp);
+ dev_err(dev, "No valid partition found on %s\n", node->full_name);
+ kfree(*pparts);
+ *pparts = NULL;
+ return -EINVAL;
+ }
+
return nr_parts;
}
EXPORT_SYMBOL(of_mtd_parse_partitions);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index f237ddbb2713..111ea41c4ecd 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -853,7 +853,6 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
break;
}
- req.name[req.name_len] = '\0';
err = verify_mkvol_req(ubi, &req);
if (err)
break;
diff --git a/drivers/mxc/amd-gpu/Kconfig b/drivers/mxc/amd-gpu/Kconfig
index 629d8cbbc989..f4f442787deb 100644
--- a/drivers/mxc/amd-gpu/Kconfig
+++ b/drivers/mxc/amd-gpu/Kconfig
@@ -6,7 +6,7 @@ menu "MXC GPU support"
config MXC_AMD_GPU
tristate "MXC GPU support"
- depends on ARCH_MX35 || ARCH_MX51 || ARCH_MX53 || ARCH_MX50
+ depends on ARCH_MX35 || ARCH_MX51 || ARCH_MX53
---help---
Say Y to get the GPU driver support.
diff --git a/drivers/mxc/amd-gpu/Makefile b/drivers/mxc/amd-gpu/Makefile
index 84cf02e5b3a3..a661de4d6a76 100644
--- a/drivers/mxc/amd-gpu/Makefile
+++ b/drivers/mxc/amd-gpu/Makefile
@@ -25,7 +25,25 @@ gpu-objs += common/gsl_cmdstream.o \
common/gsl_yamato.o \
platform/hal/linux/gsl_linux_map.o \
platform/hal/linux/gsl_kmod.o \
- platform/hal/linux/gsl_hal.o \
platform/hal/linux/gsl_kmod_cleanup.o \
platform/hal/linux/misc.o \
os/kernel/src/linux/kos_lib.o
+ifeq ($(CONFIG_ARCH_MX5),y)
+EXTRA_CFLAGS += -DMX51=1 \
+ -I$(obj)/platform/hal/MX51 \
+ -I$(obj)/platform/hal/MX51/linux \
+ -I$(obj)/platform/hal/MX51/memcfg
+
+gpu-objs += platform/hal/MX51/linux/gsl_hal.o \
+ platform/hal/MX51/memcfg/gsl_memcfg.o
+endif
+
+ifeq ($(CONFIG_ARCH_MX35),y)
+EXTRA_CFLAGS += -DMX35=1 \
+ -I$(obj)/platform/hal/MX35 \
+ -I$(obj)/platform/hal/MX35/linux \
+ -I$(obj)/platform/hal/MX35/memcfg
+
+gpu-objs += platform/hal/MX35/linux/gsl_hal.o \
+ platform/hal/MX35/memcfg/gsl_memcfg.o
+endif
diff --git a/drivers/mxc/amd-gpu/common/gsl_device.c b/drivers/mxc/amd-gpu/common/gsl_device.c
index 537b277918c4..bcb557e69d6d 100644
--- a/drivers/mxc/amd-gpu/common/gsl_device.c
+++ b/drivers/mxc/amd-gpu/common/gsl_device.c
@@ -15,7 +15,7 @@
* 02110-1301, USA.
*
*/
-
+
#include "gsl.h"
#include "gsl_hal.h"
#ifdef _LINUX
@@ -55,19 +55,10 @@ kgsl_device_init(gsl_device_t *device, gsl_deviceid_t device_id)
{
int status = GSL_SUCCESS;
gsl_devconfig_t config;
- gsl_hal_t *hal = (gsl_hal_t *)gsl_driver.hal;
kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE,
"--> int kgsl_device_init(gsl_device_t *device=0x%08x, gsl_deviceid_t device_id=%D )\n", device, device_id );
- if ((GSL_DEVICE_YAMATO == device_id) && !(hal->has_z430)) {
- return GSL_FAILURE_NOTSUPPORTED;
- }
-
- if ((GSL_DEVICE_G12 == device_id) && !(hal->has_z160)) {
- return GSL_FAILURE_NOTSUPPORTED;
- }
-
if (device->flags & GSL_FLAGS_INITIALIZED)
{
kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_init. Return value %B\n", GSL_SUCCESS );
@@ -135,7 +126,7 @@ kgsl_device_init(gsl_device_t *device, gsl_deviceid_t device_id)
return (status);
}
-#ifndef _LINUX
+#ifndef _LINUX
// Create timestamp event
device->timestamp_event = kos_event_create(0);
if( !device->timestamp_event )
@@ -146,7 +137,7 @@ kgsl_device_init(gsl_device_t *device, gsl_deviceid_t device_id)
#else
// Create timestamp wait queue
init_waitqueue_head(&device->timestamp_waitq);
-#endif
+#endif
//
// Read the chip ID after the device has been initialized.
@@ -170,10 +161,6 @@ kgsl_device_close(gsl_device_t *device)
kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE,
"--> int kgsl_device_close(gsl_device_t *device=0x%08x )\n", device );
- if (!(device->flags & GSL_FLAGS_INITIALIZED)) {
- return status;
- }
-
/* make sure the device is stopped before close
kgsl_device_close is only called for last running caller process
*/
@@ -187,8 +174,12 @@ kgsl_device_close(gsl_device_t *device)
status = kgsl_cmdstream_close(device);
if( status != GSL_SUCCESS ) return status;
- if (device->ftbl.device_close) {
- status = device->ftbl.device_close(device);
+ if (device->flags & GSL_FLAGS_INITIALIZED)
+ {
+ if (device->ftbl.device_close)
+ {
+ status = device->ftbl.device_close(device);
+ }
}
// DumpX allocates memstore from MMU aperture
@@ -198,7 +189,7 @@ kgsl_device_close(gsl_device_t *device)
kgsl_sharedmem_free0(&device->memstore, GSL_CALLER_PROCESSID_GET());
}
-#ifndef _LINUX
+#ifndef _LINUX
// destroy timestamp event
if(device->timestamp_event)
{
@@ -208,10 +199,10 @@ kgsl_device_close(gsl_device_t *device)
}
#else
wake_up_interruptible_all(&(device->timestamp_waitq));
-#endif
+#endif
kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_close. Return value %B\n", status );
-
+
return (status);
}
@@ -434,27 +425,16 @@ kgsl_device_start(gsl_deviceid_t device_id, gsl_flags_t flags)
{
int status = GSL_FAILURE_NOTINITIALIZED;
gsl_device_t *device;
- gsl_hal_t *hal = (gsl_hal_t *)gsl_driver.hal;
kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE,
"--> int kgsl_device_start(gsl_deviceid_t device_id=%D, gsl_flags_t flags=%d)\n", device_id, flags );
GSL_API_MUTEX_LOCK();
- if ((GSL_DEVICE_G12 == device_id) && !(hal->has_z160)) {
- GSL_API_MUTEX_UNLOCK();
- return GSL_FAILURE_NOTSUPPORTED;
- }
-
- if ((GSL_DEVICE_YAMATO == device_id) && !(hal->has_z430)) {
- GSL_API_MUTEX_UNLOCK();
- return GSL_FAILURE_NOTSUPPORTED;
- }
-
device = &gsl_driver.device[device_id-1]; // device_id is 1 based
-
+
kgsl_device_active(device);
-
+
if (!(device->flags & GSL_FLAGS_INITIALIZED))
{
GSL_API_MUTEX_UNLOCK();
@@ -549,7 +529,7 @@ kgsl_device_idle(gsl_deviceid_t device_id, unsigned int timeout)
device = &gsl_driver.device[device_id-1]; // device_id is 1 based
kgsl_device_active(device);
-
+
if (device->ftbl.device_idle)
{
status = device->ftbl.device_idle(device, timeout);
diff --git a/drivers/mxc/amd-gpu/common/gsl_driver.c b/drivers/mxc/amd-gpu/common/gsl_driver.c
index b8c5170a1425..fd4bcc0df96a 100644
--- a/drivers/mxc/amd-gpu/common/gsl_driver.c
+++ b/drivers/mxc/amd-gpu/common/gsl_driver.c
@@ -198,12 +198,13 @@ kgsl_driver_entry(gsl_flags_t flags)
if (status == GSL_SUCCESS)
{
// init devices
- status = GSL_FAILURE;
for (i = 0; i < GSL_DEVICE_MAX; i++)
{
- if (kgsl_device_init(&gsl_driver.device[i], (gsl_deviceid_t)(i + 1)) == GSL_SUCCESS) {
- status = GSL_SUCCESS;
- }
+ status = kgsl_device_init(&gsl_driver.device[i], (gsl_deviceid_t)(i + 1));
+ if (status != GSL_SUCCESS)
+ {
+ break;
+ }
}
}
diff --git a/drivers/mxc/amd-gpu/common/gsl_g12.c b/drivers/mxc/amd-gpu/common/gsl_g12.c
index 14cfdb61b6a1..513f6728a842 100644
--- a/drivers/mxc/amd-gpu/common/gsl_g12.c
+++ b/drivers/mxc/amd-gpu/common/gsl_g12.c
@@ -91,8 +91,6 @@ typedef struct
static gsl_z1xx_t g_z1xx = {0};
-extern int z160_version;
-
//----------------------------------------------------------------------------
@@ -465,10 +463,6 @@ kgsl_g12_getproperty(gsl_device_t *device, gsl_property_type_t type, void *value
#ifndef GSL_NO_MMU
devinfo->mmu_enabled = kgsl_mmu_isenabled(&device->mmu);
#endif
- if (z160_version == 1)
- devinfo->high_precision = 1;
- else
- devinfo->high_precision = 0;
status = GSL_SUCCESS;
}
diff --git a/drivers/mxc/amd-gpu/common/gsl_yamato.c b/drivers/mxc/amd-gpu/common/gsl_yamato.c
index e52d4274c6a6..d74c9efe2f36 100644
--- a/drivers/mxc/amd-gpu/common/gsl_yamato.c
+++ b/drivers/mxc/amd-gpu/common/gsl_yamato.c
@@ -541,7 +541,6 @@ kgsl_yamato_getproperty(gsl_device_t *device, gsl_property_type_t type, void *va
devinfo->gmem_hostbaseaddr = device->gmemspace.mmio_virt_base;
devinfo->gmem_gpubaseaddr = device->gmemspace.gpu_base;
devinfo->gmem_sizebytes = device->gmemspace.sizebytes;
- devinfo->high_precision = 0;
status = GSL_SUCCESS;
}
diff --git a/drivers/mxc/amd-gpu/include/api/gsl_types.h b/drivers/mxc/amd-gpu/include/api/gsl_types.h
index 310c1a9f5d00..99f389deee84 100644
--- a/drivers/mxc/amd-gpu/include/api/gsl_types.h
+++ b/drivers/mxc/amd-gpu/include/api/gsl_types.h
@@ -267,7 +267,6 @@ typedef struct _gsl_devinfo_t {
unsigned int gmem_gpubaseaddr;
void * gmem_hostbaseaddr; // if gmem_hostbaseaddr is NULL, we would know its not mapped into mmio space
unsigned int gmem_sizebytes;
- unsigned int high_precision; /* mx50 z160 has higher gradient/texture precision */
} gsl_devinfo_t;
diff --git a/drivers/mxc/amd-gpu/include/gsl_driver.h b/drivers/mxc/amd-gpu/include/gsl_driver.h
index 42dff457dc49..1e1d43da431d 100644
--- a/drivers/mxc/amd-gpu/include/gsl_driver.h
+++ b/drivers/mxc/amd-gpu/include/gsl_driver.h
@@ -72,7 +72,6 @@ typedef struct _gsl_driver_t {
gsl_flags_t dmi_mode; // single, double, or triple buffering
int dmi_frame; // set to -1 when DMI is enabled
int dmi_max_frame; // indicates the maximum frame # that we will support
- int enable_mmu;
} gsl_driver_t;
diff --git a/drivers/mxc/amd-gpu/include/gsl_hal.h b/drivers/mxc/amd-gpu/include/gsl_hal.h
index fcf9f0891f16..8a8a10cfb862 100644
--- a/drivers/mxc/amd-gpu/include/gsl_hal.h
+++ b/drivers/mxc/amd-gpu/include/gsl_hal.h
@@ -122,15 +122,6 @@ typedef struct _gsl_shmemconfig_t
gsl_apertureconfig_t apertures[GSL_SHMEM_MAX_APERTURES];
} gsl_shmemconfig_t;
-typedef struct _gsl_hal_t {
- gsl_memregion_t z160_regspace;
- gsl_memregion_t z430_regspace;
- gsl_memregion_t memchunk;
- gsl_memregion_t memspace[GSL_SHMEM_MAX_APERTURES];
- unsigned int has_z160;
- unsigned int has_z430;
-} gsl_hal_t;
-
//////////////////////////////////////////////////////////////////////////////
// HAL API
@@ -141,6 +132,7 @@ KGSLHAL_API int kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config);
KGSLHAL_API int kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config);
KGSLHAL_API int kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value);
KGSLHAL_API gsl_chipid_t kgsl_hal_getchipid(gsl_deviceid_t device_id);
+KGSLHAL_API int kgsl_hal_getplatformtype(char *platform);
KGSLHAL_API int kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[]);
KGSLHAL_API int kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[]);
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h
new file mode 100644
index 000000000000..9cfe9fe5b3b8
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_buildconfig.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef __GSL__BUILDCONFIG_H
+#define __GSL__BUILDCONFIG_H
+
+#define GSL_BLD_G12
+
+#define GSL_LOCKING_COURSEGRAIN
+#define GSL_MMU_TRANSLATION_ENABLED
+//#define GSL_MMU_PAGETABLE_PERPROCESS
+
+#if defined(_WIN32_WCE) && (_WIN32_WCE >= 600)
+#define GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
+#endif
+
+//#define GSL_LOG
+
+#define GSL_STATS_MEM
+#define GSL_STATS_RINGBUFFER
+#define GSL_STATS_MMU
+
+#define GSL_RB_USE_MEM_RPTR
+#define GSL_RB_USE_MEM_TIMESTAMP
+//#define GSL_RB_USE_WPTR_POLLING
+
+
+#define GSL_CALLER_PROCESS_MAX 10
+#define GSL_SHMEM_MAX_APERTURES 3
+
+#ifdef _WIN32
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#endif // _WIN32
+
+#endif // __GSL__BUILDCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h
new file mode 100644
index 000000000000..58a38c608de9
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_config.h
@@ -0,0 +1,195 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef __GSL__CONFIG_H
+#define __GSL__CONFIG_H
+
+
+// ---------------------
+// G12 MH arbiter config
+// ---------------------
+static const REG_MH_ARBITER_CONFIG gsl_cfg_g12_mharb =
+{
+ 0x10, // SAME_PAGE_LIMIT
+ 0, // SAME_PAGE_GRANULARITY
+ 1, // L1_ARB_ENABLE
+ 1, // L1_ARB_HOLD_ENABLE
+ 0, // L2_ARB_CONTROL
+ 1, // PAGE_SIZE
+ 1, // TC_REORDER_ENABLE
+ 1, // TC_ARB_HOLD_ENABLE
+ 0, // IN_FLIGHT_LIMIT_ENABLE
+ 0x8, // IN_FLIGHT_LIMIT
+ 1, // CP_CLNT_ENABLE
+ 1, // VGT_CLNT_ENABLE
+ 1, // TC_CLNT_ENABLE
+ 1, // RB_CLNT_ENABLE
+ 1, // PA_CLNT_ENABLE
+};
+
+// -----------------------------
+// interrupt block register data
+// -----------------------------
+static const gsl_intrblock_reg_t gsl_cfg_intrblock_reg[GSL_INTR_BLOCK_COUNT] =
+{
+ { // Yamato MH
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // Yamato CP
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // Yamato RBBM
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // Yamato SQ
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { // G12
+ GSL_INTR_BLOCK_G12,
+ GSL_INTR_G12_MH,
+#ifndef _Z180
+ GSL_INTR_G12_FBC,
+#else
+ GSL_INTR_G12_FIFO,
+#endif //_Z180
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQENABLE >> 2)
+ },
+ { // G12 MH
+ GSL_INTR_BLOCK_G12_MH,
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ ADDR_MH_INTERRUPT_STATUS, // G12 MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_INTERRUPT_CLEAR,
+ ADDR_MH_INTERRUPT_MASK
+ },
+};
+
+// -----------------------
+// interrupt mask bit data
+// -----------------------
+static const int gsl_cfg_intr_mask[GSL_INTR_COUNT] =
+{
+ 0,
+ 0,
+ 0,
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+
+ 0,
+ 0,
+ 0,
+
+ 0,
+ 0,
+
+ (1 << VGC_IRQENABLE_MH_FSHIFT),
+ (1 << VGC_IRQENABLE_G2D_FSHIFT),
+ (1 << VGC_IRQENABLE_FIFO_FSHIFT),
+#ifndef _Z180
+ (1 << VGC_IRQENABLE_FBC_FSHIFT),
+#endif
+ 0,
+ 0,
+ 0,
+};
+
+// -----------------
+// mmu register data
+// -----------------
+static const gsl_mmu_reg_t gsl_cfg_mmu_reg[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+ { // G12 - MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_MMU_CONFIG,
+ ADDR_MH_MMU_MPU_BASE,
+ ADDR_MH_MMU_MPU_END,
+ ADDR_MH_MMU_VA_RANGE,
+ ADDR_MH_MMU_PT_BASE,
+ ADDR_MH_MMU_PAGE_FAULT,
+ ADDR_MH_MMU_TRAN_ERROR,
+ ADDR_MH_MMU_INVALIDATE,
+ }
+};
+
+// -----------------
+// mh interrupt data
+// -----------------
+static const gsl_mh_intr_t gsl_cfg_mh_intr[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ 0,
+ 0,
+ 0,
+ },
+ { // G12
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_AXI_WRITE_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ }
+};
+
+#endif // __GSL__CONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h
new file mode 100644
index 000000000000..011041236013
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/gsl_halconfig.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef __GSL_HALCONFIG_H
+#define __GSL_HALCONFIG_H
+
+
+
+#define GSL_HAL_PLATFORM "i.MX35G"
+
+
+#define GSL_HAL_GPUBASE_GMEM 0x00100000 // 1MB
+#define GSL_HAL_GPUBASE_GMEM_PHYS 0x20000000 // 1MB
+
+#define GSL_HAL_GPUBASE_REG_YDX 0x30000000
+#define GSL_HAL_GPUBASE_REG_G12 0x20000000
+
+#define GSL_HAL_SIZE_REG_YDX 0x00020000 // 128KB
+#define GSL_HAL_SIZE_REG_G12 0x00001000 // 4KB
+#define GSL_HAL_SIZE_GMEM 0x00040000 // 256KB - 0 to 384KB in 128KB increments
+
+#if defined(_LINUX) && defined(GSL_MMU_TRANSLATION_ENABLED)
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x02400000 // 36MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00400000 // 4MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00400000 // 4MB
+#elif defined(_LINUX) //MX35 Linux can able to allocate only 4MB
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x00400000 // 4MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00200000 // 2MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00200000 // 2MB
+#else //Not possible to allocate 24 MB on WinCE
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x00D00000 // 13MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00200000 // 2MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00100000 // 1MB
+#endif
+
+#define MX35_G12_INTERRUPT 16
+
+#endif // __GSL_HALCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c b/drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c
new file mode 100644
index 000000000000..294cd9eb5af9
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/linux/gsl_hal.c
@@ -0,0 +1,524 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. 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 and
+ * only 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl_hal.h"
+#include "gsl_halconfig.h"
+#include "gsl_linux_map.h"
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// constants
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
+// defines
+//////////////////////////////////////////////////////////////////////////////
+
+#define GSL_HAL_MEM1 0
+#define GSL_HAL_MEM2 1
+#define GSL_HAL_MEM3 2
+
+//#define GSL_HAL_DEBUG
+//////////////////////////////////////////////////////////////////////////////
+// types
+//////////////////////////////////////////////////////////////////////////////
+
+typedef struct _gsl_hal_t {
+ gsl_memregion_t z160_regspace;
+#if 0
+ gsl_memregion_t z430_regspace;
+#endif
+ gsl_memregion_t memchunk;
+ gsl_memregion_t memspace[GSL_SHMEM_MAX_APERTURES];
+} gsl_hal_t;
+
+//////////////////////////////////////////////////////////////////////////////
+// functions
+//////////////////////////////////////////////////////////////////////////////
+
+KGSLHAL_API int
+kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // allocate physically contiguous memory
+ //
+
+ int i;
+ void *va;
+
+ va = (void*)gsl_linux_map_alloc(virtaddr, numpages*PAGE_SIZE);
+
+ if (!va)
+ return (GSL_FAILURE_OUTOFMEM);
+
+ for(i = 0; i < numpages; i++)
+ {
+ scattergatterlist[i] = page_to_phys(vmalloc_to_page(va));
+ va += PAGE_SIZE;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+// ---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // free physical memory
+ //
+
+ gsl_linux_map_free(virtaddr);
+
+ return(GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_init(void)
+{
+ gsl_hal_t *hal;
+ unsigned long totalsize, mem1size;
+ unsigned int va, pa;
+
+ if (gsl_driver.hal)
+ {
+ return (GSL_FAILURE_ALREADYINITIALIZED);
+ }
+
+ gsl_driver.hal = (void *)kos_malloc(sizeof(gsl_hal_t));
+
+ if (!gsl_driver.hal)
+ {
+ return (GSL_FAILURE_OUTOFMEM);
+ }
+
+ kos_memset(gsl_driver.hal, 0, sizeof(gsl_hal_t));
+
+
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+#if 0
+ // setup register space
+ hal->z430_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_YDX;
+ hal->z430_regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+ hal->z430_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z430_regspace.mmio_phys_base, hal->z430_regspace.sizebytes);
+
+ if (hal->z430_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.sizebytes = 0x%08x\n", __func__, hal->z430_regspace.sizebytes);
+#endif
+#endif
+
+ hal->z160_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_G12;
+ hal->z160_regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+ hal->z160_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z160_regspace.mmio_phys_base, hal->z160_regspace.sizebytes);
+
+ if (hal->z160_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.sizebytes = 0x%08x\n", __func__, hal->z160_regspace.sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ mem1size = GSL_HAL_SHMEM_SIZE_EMEM1;
+#else
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM1 + GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ mem1size = GSL_HAL_SHMEM_SIZE_EMEM1;
+#endif
+
+ // allocate a single chunk of physical memory
+ va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL);
+
+ if (va)
+ {
+ kos_memset((void *)va, 0, totalsize);
+
+ hal->memchunk.mmio_virt_base = (void *)va;
+ hal->memchunk.mmio_phys_base = pa;
+ hal->memchunk.sizebytes = totalsize;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memchunk.mmio_phys_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->memchunk.mmio_virt_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memchunk.sizebytes = 0x%08x\n", __func__, hal->memchunk.sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM2].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM2].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM2].sizebytes = GSL_HAL_SHMEM_SIZE_EMEM2;
+ va += GSL_HAL_SHMEM_SIZE_EMEM2;
+ pa += GSL_HAL_SHMEM_SIZE_EMEM2;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM2].sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM3].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM3].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM3].sizebytes = GSL_HAL_SHMEM_SIZE_PHYS;
+ va += GSL_HAL_SHMEM_SIZE_PHYS;
+ pa += GSL_HAL_SHMEM_SIZE_PHYS;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM3].sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_init();
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *)GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#else
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#endif
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM1].sizebytes);
+#endif
+ }
+ else
+ {
+ kgsl_hal_close();
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+ return GSL_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_close(void)
+{
+ gsl_hal_t *hal;
+
+ if (gsl_driver.hal)
+ {
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+ // unmap registers
+#if 0
+ if (hal->z430_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z430_regspace.mmio_virt_base);
+ }
+#endif
+ if (hal->z160_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z160_regspace.mmio_virt_base);
+ }
+
+ // free physical block
+ if (hal->memchunk.mmio_virt_base)
+ {
+ dma_free_coherent(0, hal->memchunk.sizebytes, hal->memchunk.mmio_virt_base, hal->memchunk.mmio_phys_base);
+ }
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_destroy();
+#endif
+
+ // release hal struct
+ kos_memset(hal, 0, sizeof(gsl_hal_t));
+ kos_free(gsl_driver.hal);
+ gsl_driver.hal = NULL;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_shmemconfig_t));
+
+ if (hal)
+ {
+ config->numapertures = GSL_SHMEM_MAX_APERTURES;
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->apertures[0].id = GSL_APERTURE_MMU;
+#else
+ config->apertures[0].id = GSL_APERTURE_EMEM;
+#endif
+ config->apertures[0].channel = GSL_CHANNEL_1;
+ config->apertures[0].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM1].mmio_virt_base;
+ config->apertures[0].gpubase = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->apertures[0].sizebytes = hal->memspace[GSL_HAL_MEM1].sizebytes;
+
+ config->apertures[1].id = GSL_APERTURE_EMEM;
+ config->apertures[1].channel = GSL_CHANNEL_2;
+ config->apertures[1].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM2].mmio_virt_base;
+ config->apertures[1].gpubase = hal->memspace[GSL_HAL_MEM2].gpu_base;
+ config->apertures[1].sizebytes = hal->memspace[GSL_HAL_MEM2].sizebytes;
+
+ config->apertures[2].id = GSL_APERTURE_PHYS;
+ config->apertures[2].channel = GSL_CHANNEL_1;
+ config->apertures[2].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM3].mmio_virt_base;
+ config->apertures[2].gpubase = hal->memspace[GSL_HAL_MEM3].gpu_base;
+ config->apertures[2].sizebytes = hal->memspace[GSL_HAL_MEM3].sizebytes;
+
+ status = GSL_SUCCESS;
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_devconfig_t));
+
+ if (hal)
+ {
+ switch (device_id)
+ {
+ case GSL_DEVICE_YAMATO:
+ {
+#if 0
+ mh_mmu_config_u mmu_config = {0};
+
+ config->gmemspace.gpu_base = 0;
+ config->gmemspace.mmio_virt_base = 0;
+ config->gmemspace.mmio_phys_base = 0;
+ config->gmemspace.sizebytes = GSL_HAL_SIZE_GMEM;
+
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z430_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z430_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+
+ mmu_config.f.mmu_enable = 1;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ mmu_config.f.split_mode_enable = 0;
+ mmu_config.f.rb_w_clnt_behavior = 1;
+ mmu_config.f.cp_w_clnt_behavior = 1;
+ mmu_config.f.cp_r0_clnt_behavior = 1;
+ mmu_config.f.cp_r1_clnt_behavior = 1;
+ mmu_config.f.cp_r2_clnt_behavior = 1;
+ mmu_config.f.cp_r3_clnt_behavior = 1;
+ mmu_config.f.cp_r4_clnt_behavior = 1;
+ mmu_config.f.vgt_r0_clnt_behavior = 1;
+ mmu_config.f.vgt_r1_clnt_behavior = 1;
+ mmu_config.f.tc_r_clnt_behavior = 1;
+ mmu_config.f.pa_w_clnt_behavior = 1;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mmu_config = mmu_config.val;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ // turn off memory protection unit by setting acceptable physical address range to include all pages
+ config->mpu_base = 0x00000000; // hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; // hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+#endif
+ break;
+ }
+
+ case GSL_DEVICE_G12:
+ {
+#ifndef GSL_MMU_TRANSLATION_ENABLED
+ unsigned int mmu_config = {0};
+#endif
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z160_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z160_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+
+
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->mmu_config = 0x00555551;
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->mmu_config = mmu_config;
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mpu_base = 0x00000000; //(unsigned int) hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; //hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+ break;
+ }
+
+ default:
+
+ break;
+ }
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+//
+// kgsl_hal_getchipid
+//
+// The proper platform method, build from RBBM_PERIPHIDx and RBBM_PATCH_RELEASE
+//
+KGSLHAL_API gsl_chipid_t
+kgsl_hal_getchipid(gsl_deviceid_t device_id)
+{
+ return (0);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getplatformtype(char *platform)
+{
+ if (gsl_driver.hal)
+ {
+ kos_strcpy(platform, GSL_HAL_PLATFORM);
+ return (GSL_SUCCESS);
+ }
+ else
+ {
+ return (GSL_FAILURE_NOTINITIALIZED);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value)
+{
+ gsl_device_t *device = &gsl_driver.device[device_id-1]; // device_id is 1 based
+ struct clk *gpu_clk = 0;
+
+ // unreferenced formal parameters
+ (void) value;
+
+ switch (device_id)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ default:
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (!gpu_clk)
+ return (GSL_FAILURE_DEVICEERROR);
+
+ switch (state)
+ {
+ case GSL_PWRFLAGS_CLK_ON:
+ break;
+ case GSL_PWRFLAGS_POWER_ON:
+ clk_enable(gpu_clk);
+ kgsl_device_autogate_init(&gsl_driver.device[device_id-1]);
+ break;
+ case GSL_PWRFLAGS_CLK_OFF:
+ break;
+ case GSL_PWRFLAGS_POWER_OFF:
+ if (device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT) != GSL_SUCCESS)
+ {
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+ kgsl_device_autogate_exit(&gsl_driver.device[device_id-1]);
+ clk_disable(gpu_clk);
+ break;
+ default:
+ break;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+KGSLHAL_API int kgsl_clock(gsl_deviceid_t dev, int enable)
+{
+ struct clk *gpu_clk = 0;
+
+ switch (dev)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ default:
+ printk(KERN_ERR "GPU device %d is invalid!\n", dev);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (IS_ERR(gpu_clk)) {
+ printk(KERN_ERR "%s: GPU clock get failed!\n", __func__);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (enable)
+ clk_enable(gpu_clk);
+ else
+ clk_disable(gpu_clk);
+
+ return (GSL_SUCCESS);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c
new file mode 100644
index 000000000000..f3ca6191d7c2
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. 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 and
+ * only 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "kos_libapi.h"
+
+//
+// Return the maximum amount of memory that can be allocated to the Z160. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z160_memory_amount(void)
+{
+ return(0);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h
new file mode 100644
index 000000000000..164a17c925c4
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX35/memcfg/gsl_memcfg.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef GSL_MEMCFG_H
+#define GSL_MEMCFG_H
+
+//
+// Return the maximum amount of memory that can be allocated to the Z430. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z160_memory_amount(void);
+
+#endif
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h
new file mode 100644
index 000000000000..82824f511d5e
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_buildconfig.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef __GSL__BUILDCONFIG_H
+#define __GSL__BUILDCONFIG_H
+
+#define GSL_BLD_YAMATO
+#define GSL_BLD_G12
+
+#define GSL_LOCKING_COURSEGRAIN
+
+#define GSL_STATS_MEM
+#define GSL_STATS_RINGBUFFER
+#define GSL_STATS_MMU
+
+#define GSL_RB_USE_MEM_RPTR
+#define GSL_RB_USE_MEM_TIMESTAMP
+#define GSL_RB_TIMESTAMP_INTERUPT
+//#define GSL_RB_USE_WPTR_POLLING
+
+#if defined(_WIN32_WCE) && (_WIN32_WCE >= 600)
+#define GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
+#endif
+
+//#define GSL_MMU_TRANSLATION_ENABLED
+//#define GSL_MMU_PAGETABLE_PERPROCESS
+
+#define GSL_CALLER_PROCESS_MAX 10
+#define GSL_SHMEM_MAX_APERTURES 3
+
+#ifdef _WIN32
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#endif // _WIN32
+
+#endif // __GSL__BUILDCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h
new file mode 100644
index 000000000000..6fad1d01277f
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_config.h
@@ -0,0 +1,222 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef __GSL__CONFIG_H
+#define __GSL__CONFIG_H
+
+// ------------------------
+// Yamato ringbuffer config
+// ------------------------
+static const unsigned int gsl_cfg_rb_sizelog2quadwords = GSL_RB_SIZE_32K;
+static const unsigned int gsl_cfg_rb_blksizequadwords = GSL_RB_SIZE_16;
+
+// ------------------------
+// Yamato MH arbiter config
+// ------------------------
+static const mh_arbiter_config_t gsl_cfg_yamato_mharb =
+{
+ 0x10, // same_page_limit
+ 0, // same_page_granularity
+ 1, // l1_arb_enable
+ 1, // l1_arb_hold_enable
+ 0, // l2_arb_control
+ 1, // page_size
+ 1, // tc_reorder_enable
+ 1, // tc_arb_hold_enable
+ 1, // in_flight_limit_enable
+ 0x8, // in_flight_limit
+ 1, // cp_clnt_enable
+ 1, // vgt_clnt_enable
+ 1, // tc_clnt_enable
+ 1, // rb_clnt_enable
+ 1, // pa_clnt_enable
+};
+
+// ---------------------
+// G12 MH arbiter config
+// ---------------------
+static const REG_MH_ARBITER_CONFIG gsl_cfg_g12_mharb =
+{
+ 0x10, // SAME_PAGE_LIMIT
+ 0, // SAME_PAGE_GRANULARITY
+ 1, // L1_ARB_ENABLE
+ 1, // L1_ARB_HOLD_ENABLE
+ 0, // L2_ARB_CONTROL
+ 1, // PAGE_SIZE
+ 1, // TC_REORDER_ENABLE
+ 1, // TC_ARB_HOLD_ENABLE
+ 0, // IN_FLIGHT_LIMIT_ENABLE
+ 0x8, // IN_FLIGHT_LIMIT
+ 1, // CP_CLNT_ENABLE
+ 1, // VGT_CLNT_ENABLE
+ 1, // TC_CLNT_ENABLE
+ 1, // RB_CLNT_ENABLE
+ 1, // PA_CLNT_ENABLE
+};
+
+// -----------------------------
+// interrupt block register data
+// -----------------------------
+static const gsl_intrblock_reg_t gsl_cfg_intrblock_reg[GSL_INTR_BLOCK_COUNT] =
+{
+ { // Yamato MH
+ GSL_INTR_BLOCK_YDX_MH,
+ GSL_INTR_YDX_MH_AXI_READ_ERROR,
+ GSL_INTR_YDX_MH_MMU_PAGE_FAULT,
+ mmMH_INTERRUPT_STATUS,
+ mmMH_INTERRUPT_CLEAR,
+ mmMH_INTERRUPT_MASK
+ },
+ { // Yamato CP
+ GSL_INTR_BLOCK_YDX_CP,
+ GSL_INTR_YDX_CP_SW_INT,
+ GSL_INTR_YDX_CP_RING_BUFFER,
+ mmCP_INT_STATUS,
+ mmCP_INT_ACK,
+ mmCP_INT_CNTL
+ },
+ { // Yamato RBBM
+ GSL_INTR_BLOCK_YDX_RBBM,
+ GSL_INTR_YDX_RBBM_READ_ERROR,
+ GSL_INTR_YDX_RBBM_GUI_IDLE,
+ mmRBBM_INT_STATUS,
+ mmRBBM_INT_ACK,
+ mmRBBM_INT_CNTL
+ },
+ { // Yamato SQ
+ GSL_INTR_BLOCK_YDX_SQ,
+ GSL_INTR_YDX_SQ_PS_WATCHDOG,
+ GSL_INTR_YDX_SQ_VS_WATCHDOG,
+ mmSQ_INT_STATUS,
+ mmSQ_INT_ACK,
+ mmSQ_INT_CNTL
+ },
+ { // G12
+ GSL_INTR_BLOCK_G12,
+ GSL_INTR_G12_MH,
+#ifndef _Z180
+ GSL_INTR_G12_FBC,
+#else
+ GSL_INTR_G12_FIFO,
+#endif //_Z180
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQSTATUS >> 2),
+ (ADDR_VGC_IRQENABLE >> 2)
+ },
+ { // G12 MH
+ GSL_INTR_BLOCK_G12_MH,
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ ADDR_MH_INTERRUPT_STATUS, // G12 MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_INTERRUPT_CLEAR,
+ ADDR_MH_INTERRUPT_MASK
+ },
+};
+
+// -----------------------
+// interrupt mask bit data
+// -----------------------
+static const int gsl_cfg_intr_mask[GSL_INTR_COUNT] =
+{
+ MH_INTERRUPT_MASK__AXI_READ_ERROR,
+ MH_INTERRUPT_MASK__AXI_WRITE_ERROR,
+ MH_INTERRUPT_MASK__MMU_PAGE_FAULT,
+
+ CP_INT_CNTL__SW_INT_MASK,
+ CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
+ CP_INT_CNTL__OPCODE_ERROR_MASK,
+ CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
+ CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
+ CP_INT_CNTL__IB_ERROR_MASK,
+ CP_INT_CNTL__IB2_INT_MASK,
+ CP_INT_CNTL__IB1_INT_MASK,
+ CP_INT_CNTL__RB_INT_MASK,
+
+ RBBM_INT_CNTL__RDERR_INT_MASK,
+ RBBM_INT_CNTL__DISPLAY_UPDATE_INT_MASK,
+ RBBM_INT_CNTL__GUI_IDLE_INT_MASK,
+
+ SQ_INT_CNTL__PS_WATCHDOG_MASK,
+ SQ_INT_CNTL__VS_WATCHDOG_MASK,
+
+ (1 << VGC_IRQENABLE_MH_FSHIFT),
+ (1 << VGC_IRQENABLE_G2D_FSHIFT),
+ (1 << VGC_IRQENABLE_FIFO_FSHIFT),
+#ifndef _Z180
+ (1 << VGC_IRQENABLE_FBC_FSHIFT),
+#endif
+ (1 << MH_INTERRUPT_MASK_AXI_READ_ERROR_FSHIFT),
+ (1 << MH_INTERRUPT_MASK_AXI_WRITE_ERROR_FSHIFT),
+ (1 << MH_INTERRUPT_MASK_MMU_PAGE_FAULT_FSHIFT),
+};
+
+// -----------------
+// mmu register data
+// -----------------
+static const gsl_mmu_reg_t gsl_cfg_mmu_reg[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ mmMH_MMU_CONFIG,
+ mmMH_MMU_MPU_BASE,
+ mmMH_MMU_MPU_END,
+ mmMH_MMU_VA_RANGE,
+ mmMH_MMU_PT_BASE,
+ mmMH_MMU_PAGE_FAULT,
+ mmMH_MMU_TRAN_ERROR,
+ mmMH_MMU_INVALIDATE,
+ },
+ { // G12 - MH offsets are considered to be dword based, therefore no down shift
+ ADDR_MH_MMU_CONFIG,
+ ADDR_MH_MMU_MPU_BASE,
+ ADDR_MH_MMU_MPU_END,
+ ADDR_MH_MMU_VA_RANGE,
+ ADDR_MH_MMU_PT_BASE,
+ ADDR_MH_MMU_PAGE_FAULT,
+ ADDR_MH_MMU_TRAN_ERROR,
+ ADDR_MH_MMU_INVALIDATE,
+ }
+};
+
+// -----------------
+// mh interrupt data
+// -----------------
+static const gsl_mh_intr_t gsl_cfg_mh_intr[GSL_DEVICE_MAX] =
+{
+ { // Yamato
+ GSL_INTR_YDX_MH_AXI_READ_ERROR,
+ GSL_INTR_YDX_MH_AXI_WRITE_ERROR,
+ GSL_INTR_YDX_MH_MMU_PAGE_FAULT,
+ },
+ { // G12
+ GSL_INTR_G12_MH_AXI_READ_ERROR,
+ GSL_INTR_G12_MH_AXI_WRITE_ERROR,
+ GSL_INTR_G12_MH_MMU_PAGE_FAULT,
+ }
+};
+
+#endif // __GSL__CONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h
new file mode 100644
index 000000000000..589c56fa9bfa
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/gsl_halconfig.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef __GSL_HALCONFIG_H
+#define __GSL_HALCONFIG_H
+
+
+#define GSL_HAL_PLATFORM "i.MX51"
+
+#define GSL_HAL_GPUBASE_GMEM 0x00100000 // 1MB
+#define GSL_HAL_GPUBASE_GMEM_PHYS 0x20000000 // 1MB
+
+#define GSL_HAL_GPUBASE_REG_YDX 0x30000000
+#define GSL_HAL_GPUBASE_REG_G12 0xD0000000
+
+#define GSL_HAL_SIZE_REG_YDX 0x00020000 // 128KB
+#define GSL_HAL_SIZE_REG_G12 0x00001000 // 4KB
+#define GSL_HAL_SIZE_GMEM 0x00020000 // 128KB - 0 to 384KB in 128KB increments
+
+#if defined(GSL_MMU_TRANSLATION_ENABLED)
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x02400000 // 36MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00400000 // 4MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00400000 // 4MB
+#else
+#define GSL_HAL_SHMEM_SIZE_EMEM1 0x00D00000 // 13MB
+#define GSL_HAL_SHMEM_SIZE_EMEM2 0x00200000 // 2MB
+#define GSL_HAL_SHMEM_SIZE_PHYS 0x00100000 // 1MB
+#endif
+
+#define MX51_G12_INTERRUPT 84 // Interrupt line taken from Reference Manual
+#define MX51_YDX_INTERRUPT 12 // Interrupt line taken from Reference Manual
+
+#endif // __GSL_HALCONFIG_H
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c b/drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c
new file mode 100644
index 000000000000..965416b59ec1
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/linux/gsl_hal.c
@@ -0,0 +1,598 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. 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 and
+ * only 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl_hal.h"
+#include "gsl_halconfig.h"
+#include "gsl_memcfg.h"
+#include "gsl_linux_map.h"
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// constants
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
+// defines
+//////////////////////////////////////////////////////////////////////////////
+
+#define GSL_HAL_MEM1 0
+#define GSL_HAL_MEM2 1
+#define GSL_HAL_MEM3 2
+
+//#define GSL_HAL_DEBUG
+
+//////////////////////////////////////////////////////////////////////////////
+// types
+//////////////////////////////////////////////////////////////////////////////
+
+typedef struct _gsl_hal_t {
+ gsl_memregion_t z160_regspace;
+ gsl_memregion_t z430_regspace;
+ gsl_memregion_t memchunk;
+ gsl_memregion_t memspace[GSL_SHMEM_MAX_APERTURES];
+} gsl_hal_t;
+
+extern phys_addr_t gpu_2d_regbase;
+extern int gpu_2d_regsize;
+extern phys_addr_t gpu_3d_regbase;
+extern int gpu_3d_regsize;
+extern int gmem_size;
+extern phys_addr_t gpu_reserved_mem;
+extern int gpu_reserved_mem_size;
+
+//////////////////////////////////////////////////////////////////////////////
+// functions
+//////////////////////////////////////////////////////////////////////////////
+
+KGSLHAL_API int
+kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // allocate physically contiguous memory
+ //
+
+ int i;
+ void *va;
+
+ va = gsl_linux_map_alloc(virtaddr, numpages*PAGE_SIZE);
+
+ if (!va)
+ return (GSL_FAILURE_OUTOFMEM);
+
+ for(i = 0; i < numpages; i++)
+ {
+ scattergatterlist[i] = page_to_phys(vmalloc_to_page(va));
+ va += PAGE_SIZE;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+// ---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[])
+{
+ //
+ // free physical memory
+ //
+
+ gsl_linux_map_free(virtaddr);
+
+ return(GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_init(void)
+{
+ gsl_hal_t *hal;
+ unsigned long totalsize, mem1size;
+ unsigned int va, pa;
+
+ if (gsl_driver.hal)
+ {
+ return (GSL_FAILURE_ALREADYINITIALIZED);
+ }
+
+ gsl_driver.hal = (void *)kos_malloc(sizeof(gsl_hal_t));
+
+ if (!gsl_driver.hal)
+ {
+ return (GSL_FAILURE_OUTOFMEM);
+ }
+
+ kos_memset(gsl_driver.hal, 0, sizeof(gsl_hal_t));
+
+
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+ // setup register space
+ if(gpu_3d_regbase && gpu_3d_regsize){
+ hal->z430_regspace.mmio_phys_base = gpu_3d_regbase;
+ hal->z430_regspace.sizebytes = gpu_3d_regsize;
+ }else{
+ hal->z430_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_YDX;
+ hal->z430_regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+ }
+ hal->z430_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z430_regspace.mmio_phys_base, hal->z430_regspace.sizebytes);
+
+ if (hal->z430_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z430_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z430_regspace.sizebytes = 0x%08x\n", __func__, hal->z430_regspace.sizebytes);
+#endif
+
+ if(gpu_2d_regbase && gpu_2d_regsize){
+ hal->z160_regspace.mmio_phys_base = gpu_2d_regbase;
+ hal->z160_regspace.sizebytes = gpu_2d_regsize;
+ }else{
+ hal->z160_regspace.mmio_phys_base = GSL_HAL_GPUBASE_REG_G12;
+ hal->z160_regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+ }
+ hal->z160_regspace.mmio_virt_base = (unsigned char*)ioremap(hal->z160_regspace.mmio_phys_base, hal->z160_regspace.sizebytes);
+
+ if (hal->z160_regspace.mmio_virt_base == NULL)
+ {
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_phys_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.mmio_virt_base = 0x%p\n", __func__, (void*)hal->z160_regspace.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->z160_regspace.sizebytes = 0x%08x\n", __func__, hal->z160_regspace.sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ mem1size = GSL_HAL_SHMEM_SIZE_EMEM1;
+ if (gpu_reserved_mem && gpu_reserved_mem_size >= totalsize)
+ {
+ pa = gpu_reserved_mem;
+ va = (unsigned int)ioremap(gpu_reserved_mem, totalsize);
+ }
+ else
+ {
+ va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL);
+ }
+#else
+ if(gpu_reserved_mem && gpu_reserved_mem_size >= SZ_8M){
+ totalsize = gpu_reserved_mem_size;
+ pa = gpu_reserved_mem;
+ va = (unsigned int)ioremap(gpu_reserved_mem, gpu_reserved_mem_size);
+ }else{
+ gpu_reserved_mem = 0;
+ totalsize = GSL_HAL_SHMEM_SIZE_EMEM1 + GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS;
+ va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL);
+ }
+ mem1size = totalsize - (GSL_HAL_SHMEM_SIZE_EMEM2 + GSL_HAL_SHMEM_SIZE_PHYS);
+#endif
+
+ if (va)
+ {
+ kos_memset((void *)va, 0, totalsize);
+
+ hal->memchunk.mmio_virt_base = (void *)va;
+ hal->memchunk.mmio_phys_base = pa;
+ hal->memchunk.sizebytes = totalsize;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memchunk.mmio_phys_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_phys_base);
+ printk(KERN_INFO "%s: hal->memchunk.mmio_virt_base = 0x%p\n", __func__, (void*)hal->memchunk.mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memchunk.sizebytes = 0x%08x\n", __func__, hal->memchunk.sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM2].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM2].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM2].sizebytes = GSL_HAL_SHMEM_SIZE_EMEM2;
+ va += GSL_HAL_SHMEM_SIZE_EMEM2;
+ pa += GSL_HAL_SHMEM_SIZE_EMEM2;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM2].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM2].sizebytes);
+#endif
+
+ hal->memspace[GSL_HAL_MEM3].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM3].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM3].sizebytes = GSL_HAL_SHMEM_SIZE_PHYS;
+ va += GSL_HAL_SHMEM_SIZE_PHYS;
+ pa += GSL_HAL_SHMEM_SIZE_PHYS;
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM3].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM3].sizebytes);
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_init();
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *)GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = GSL_LINUX_MAP_RANGE_START;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#else
+ hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *) va;
+ hal->memspace[GSL_HAL_MEM1].gpu_base = pa;
+ hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size;
+#endif
+
+#ifdef GSL_HAL_DEBUG
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].gpu_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].gpu_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].mmio_virt_base = 0x%p\n", __func__, (void*)hal->memspace[GSL_HAL_MEM1].mmio_virt_base);
+ printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM1].sizebytes);
+#endif
+ }
+ else
+ {
+ kgsl_hal_close();
+ return (GSL_FAILURE_SYSTEMERROR);
+ }
+
+ return GSL_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_close(void)
+{
+ gsl_hal_t *hal;
+
+ if (gsl_driver.hal)
+ {
+ // overlay structure on hal memory
+ hal = (gsl_hal_t *) gsl_driver.hal;
+
+ // unmap registers
+ if (hal->z430_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z430_regspace.mmio_virt_base);
+ }
+ if (hal->z160_regspace.mmio_virt_base)
+ {
+ iounmap(hal->z160_regspace.mmio_virt_base);
+ }
+
+ // free physical block
+ if (hal->memchunk.mmio_virt_base && gpu_reserved_mem)
+ {
+ iounmap(hal->memchunk.mmio_virt_base);
+ }
+ else
+ {
+ dma_free_coherent(0, hal->memchunk.sizebytes, hal->memchunk.mmio_virt_base, hal->memchunk.mmio_phys_base);
+ }
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ gsl_linux_map_destroy();
+#endif
+
+ // release hal struct
+ kos_memset(hal, 0, sizeof(gsl_hal_t));
+ kos_free(gsl_driver.hal);
+ gsl_driver.hal = NULL;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_shmemconfig_t));
+
+ if (hal)
+ {
+ config->numapertures = GSL_SHMEM_MAX_APERTURES;
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->apertures[0].id = GSL_APERTURE_MMU;
+#else
+ config->apertures[0].id = GSL_APERTURE_EMEM;
+#endif
+ config->apertures[0].channel = GSL_CHANNEL_1;
+ config->apertures[0].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM1].mmio_virt_base;
+ config->apertures[0].gpubase = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->apertures[0].sizebytes = hal->memspace[GSL_HAL_MEM1].sizebytes;
+
+ config->apertures[1].id = GSL_APERTURE_EMEM;
+ config->apertures[1].channel = GSL_CHANNEL_2;
+ config->apertures[1].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM2].mmio_virt_base;
+ config->apertures[1].gpubase = hal->memspace[GSL_HAL_MEM2].gpu_base;
+ config->apertures[1].sizebytes = hal->memspace[GSL_HAL_MEM2].sizebytes;
+
+ config->apertures[2].id = GSL_APERTURE_PHYS;
+ config->apertures[2].channel = GSL_CHANNEL_1;
+ config->apertures[2].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM3].mmio_virt_base;
+ config->apertures[2].gpubase = hal->memspace[GSL_HAL_MEM3].gpu_base;
+ config->apertures[2].sizebytes = hal->memspace[GSL_HAL_MEM3].sizebytes;
+
+ status = GSL_SUCCESS;
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config)
+{
+ int status = GSL_FAILURE_DEVICEERROR;
+ gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal;
+
+ kos_memset(config, 0, sizeof(gsl_devconfig_t));
+
+ if (hal)
+ {
+ switch (device_id)
+ {
+ case GSL_DEVICE_YAMATO:
+ {
+ mh_mmu_config_u mmu_config = {0};
+
+ config->gmemspace.gpu_base = 0;
+ config->gmemspace.mmio_virt_base = 0;
+ config->gmemspace.mmio_phys_base = 0;
+ if(gmem_size){
+ config->gmemspace.sizebytes = gmem_size;
+ }else{
+ config->gmemspace.sizebytes = GSL_HAL_SIZE_GMEM;
+ }
+
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z430_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z430_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_YDX;
+
+ mmu_config.f.mmu_enable = 1;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ mmu_config.f.split_mode_enable = 0;
+ mmu_config.f.rb_w_clnt_behavior = 1;
+ mmu_config.f.cp_w_clnt_behavior = 1;
+ mmu_config.f.cp_r0_clnt_behavior = 1;
+ mmu_config.f.cp_r1_clnt_behavior = 1;
+ mmu_config.f.cp_r2_clnt_behavior = 1;
+ mmu_config.f.cp_r3_clnt_behavior = 1;
+ mmu_config.f.cp_r4_clnt_behavior = 1;
+ mmu_config.f.vgt_r0_clnt_behavior = 1;
+ mmu_config.f.vgt_r1_clnt_behavior = 1;
+ mmu_config.f.tc_r_clnt_behavior = 1;
+ mmu_config.f.pa_w_clnt_behavior = 1;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mmu_config = mmu_config.val;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ // turn off memory protection unit by setting acceptable physical address range to include all pages
+ config->mpu_base = 0x00000000; // hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; // hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+ break;
+ }
+
+ case GSL_DEVICE_G12:
+ {
+ mh_mmu_config_u mmu_config = {0};
+
+ config->regspace.gpu_base = 0;
+ config->regspace.mmio_virt_base = (unsigned char *)hal->z160_regspace.mmio_virt_base;
+ config->regspace.mmio_phys_base = (unsigned int) hal->z160_regspace.mmio_phys_base;
+ config->regspace.sizebytes = GSL_HAL_SIZE_REG_G12;
+
+ mmu_config.f.mmu_enable = 1;
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ config->mmu_config = 0x00555551;
+ config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base;
+ config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes;
+#else
+ config->mmu_config = mmu_config.val;
+ config->va_base = 0x00000000;
+ config->va_range = 0x00000000;
+#endif // GSL_MMU_TRANSLATION_ENABLED
+
+ config->mpu_base = 0x00000000; //(unsigned int) hal->memchunk.mmio_virt_base;
+ config->mpu_range = 0xFFFFF000; //hal->memchunk.sizebytes;
+
+ status = GSL_SUCCESS;
+ break;
+ }
+
+ default:
+
+ break;
+ }
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+//
+// kgsl_hal_getchipid
+//
+// The proper platform method, build from RBBM_PERIPHIDx and RBBM_PATCH_RELEASE
+//
+KGSLHAL_API gsl_chipid_t
+kgsl_hal_getchipid(gsl_deviceid_t device_id)
+{
+ gsl_device_t *device = &gsl_driver.device[device_id-1];
+ gsl_chipid_t chipid;
+ unsigned int coreid, majorid, minorid, patchid, revid;
+
+ // YDX
+ device->ftbl.device_regread(device, mmRBBM_PERIPHID1, &coreid);
+ coreid &= 0xF;
+
+ // 2.
+ device->ftbl.device_regread(device, mmRBBM_PERIPHID2, &majorid);
+ majorid = (majorid >> 4) & 0xF;
+
+ device->ftbl.device_regread(device, mmRBBM_PATCH_RELEASE, &revid);
+
+ // 2.
+ minorid = ((revid >> 0) & 0xFF); // this is a 16bit field, but extremely unlikely it would ever get this high
+
+ // 1
+ patchid = ((revid >> 16) & 0xFF);
+
+ chipid = ((coreid << 24) | (majorid << 16) | (minorid << 8) | (patchid << 0));
+
+ return (chipid);
+}
+
+//----------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_getplatformtype(char *platform)
+{
+ if (gsl_driver.hal)
+ {
+ kos_strcpy(platform, GSL_HAL_PLATFORM);
+ return (GSL_SUCCESS);
+ }
+ else
+ {
+ return (GSL_FAILURE_NOTINITIALIZED);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+KGSLHAL_API int
+kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value)
+{
+ gsl_device_t *device = &gsl_driver.device[device_id-1];
+ struct clk *gpu_clk = 0;
+ struct clk *garb_clk = clk_get(0, "garb_clk");
+ struct clk *emi_garb_clk = clk_get(0, "emi_garb_clk");
+
+ // unreferenced formal parameters
+ (void) value;
+
+ switch (device_id)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ case GSL_DEVICE_YAMATO:
+ gpu_clk = clk_get(0, "gpu3d_clk");
+ break;
+ default:
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (!gpu_clk)
+ return (GSL_FAILURE_DEVICEERROR);
+
+ switch (state)
+ {
+ case GSL_PWRFLAGS_CLK_ON:
+ break;
+ case GSL_PWRFLAGS_POWER_ON:
+ clk_enable(gpu_clk);
+ clk_enable(garb_clk);
+ clk_enable(emi_garb_clk);
+ kgsl_device_autogate_init(&gsl_driver.device[device_id-1]);
+ break;
+ case GSL_PWRFLAGS_CLK_OFF:
+ break;
+ case GSL_PWRFLAGS_POWER_OFF:
+ if (device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT) != GSL_SUCCESS)
+ {
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+ kgsl_device_autogate_exit(&gsl_driver.device[device_id-1]);
+ clk_disable(gpu_clk);
+ clk_disable(garb_clk);
+ clk_disable(emi_garb_clk);
+ break;
+ default:
+ break;
+ }
+
+ return (GSL_SUCCESS);
+}
+
+KGSLHAL_API int kgsl_clock(gsl_deviceid_t dev, int enable)
+{
+ struct clk *gpu_clk;
+ struct clk *garb_clk = clk_get(0, "garb_clk");
+ struct clk *emi_garb_clk = clk_get(0, "emi_garb_clk");
+
+ switch (dev)
+ {
+ case GSL_DEVICE_G12:
+ gpu_clk = clk_get(0, "gpu2d_clk");
+ break;
+ case GSL_DEVICE_YAMATO:
+ gpu_clk = clk_get(0, "gpu3d_clk");
+ break;
+ default:
+ printk(KERN_ERR "GPU device %d is invalid!\n", dev);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (IS_ERR(gpu_clk)) {
+ printk(KERN_ERR "%s: GPU clock get failed!\n", __func__);
+ return (GSL_FAILURE_DEVICEERROR);
+ }
+
+ if (enable) {
+ clk_enable(gpu_clk);
+ clk_enable(garb_clk);
+ clk_enable(emi_garb_clk);
+ } else {
+ clk_disable(gpu_clk);
+ clk_disable(garb_clk);
+ clk_disable(emi_garb_clk);
+ }
+
+ return (GSL_SUCCESS);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c
new file mode 100644
index 000000000000..93fab327a830
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. 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 and
+ * only 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "kos_libapi.h"
+
+//
+// Return the maximum amount of memory that can be allocated to the Z430. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z430_memory_amount(void)
+{
+ return(0);
+}
diff --git a/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h
new file mode 100644
index 000000000000..e68387f1609a
--- /dev/null
+++ b/drivers/mxc/amd-gpu/platform/hal/MX51/memcfg/gsl_memcfg.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved.
+ *
+ * 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.
+ * * Neither the name of Advanced Micro Devices nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ */
+
+#ifndef GSL_MEMCFG_H
+#define GSL_MEMCFG_H
+
+//
+// Return the maximum amount of memory that can be allocated to the Z430. This number
+// will be constrained to 2MB as a minimum and the original hardcoded value for the caller
+// as a maximum. If the return value is outside of this range, then the original value in
+// the caller will be used. For this reason, returning 0 is used to signify to use the
+// original value as the default.
+//
+KOS_DLLEXPORT unsigned long kgsl_get_z430_memory_amount(void);
+#endif
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h
index 305b2ee9066d..65eadb1e79cf 100644
--- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h
@@ -40,9 +40,14 @@
OSINLINE void
kgsl_hwaccess_memread(void *dst, unsigned int gpubase, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace)
{
- if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) {
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if(gpubase >= GSL_LINUX_MAP_RANGE_START && gpubase < GSL_LINUX_MAP_RANGE_END)
+ {
gsl_linux_map_read(dst, gpubase+gpuoffset, sizebytes, touserspace);
- } else {
+ }
+ else
+#endif
+ {
mb();
dsb();
if (touserspace)
@@ -66,9 +71,14 @@ kgsl_hwaccess_memread(void *dst, unsigned int gpubase, unsigned int gpuoffset, u
OSINLINE void
kgsl_hwaccess_memwrite(unsigned int gpubase, unsigned int gpuoffset, void *src, unsigned int sizebytes, unsigned int fromuserspace)
{
- if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) {
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if(gpubase >= GSL_LINUX_MAP_RANGE_START && gpubase < GSL_LINUX_MAP_RANGE_END)
+ {
gsl_linux_map_write(src, gpubase+gpuoffset, sizebytes, fromuserspace);
- } else {
+ }
+ else
+#endif
+ {
mb();
dsb();
if (fromuserspace)
@@ -92,9 +102,12 @@ kgsl_hwaccess_memwrite(unsigned int gpubase, unsigned int gpuoffset, void *src,
OSINLINE void
kgsl_hwaccess_memset(unsigned int gpubase, unsigned int gpuoffset, unsigned int value, unsigned int sizebytes)
{
- if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) {
- gsl_linux_map_set(gpuoffset+gpubase, value, sizebytes);
- } else {
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if(gpubase >= GSL_LINUX_MAP_RANGE_START && gpubase < GSL_LINUX_MAP_RANGE_END)
+ gsl_linux_map_set(gpuoffset+gpubase, value, sizebytes);
+ else
+#endif
+ {
mb();
dsb();
kos_memset((void *)(gpubase + gpuoffset), value, sizebytes);
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c
index bef8684ad131..30f783e1cf12 100644
--- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c
@@ -39,7 +39,7 @@
#include <linux/platform_device.h>
#include <linux/vmalloc.h>
-int gpu_2d_irq, gpu_3d_irq;
+static int gpu_2d_irq, gpu_3d_irq;
phys_addr_t gpu_2d_regbase;
int gpu_2d_regsize;
@@ -48,7 +48,6 @@ int gpu_3d_regsize;
int gmem_size;
phys_addr_t gpu_reserved_mem;
int gpu_reserved_mem_size;
-int z160_version;
static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr);
static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr);
@@ -58,7 +57,9 @@ static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
static int gsl_kmod_open(struct inode *inode, struct file *fd);
static int gsl_kmod_release(struct inode *inode, struct file *fd);
static irqreturn_t z160_irq_handler(int irq, void *dev_id);
+#if defined(MX51)
static irqreturn_t z430_irq_handler(int irq, void *dev_id);
+#endif
static int gsl_kmod_major;
static struct class *gsl_kmod_class;
@@ -633,24 +634,34 @@ static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma)
unsigned long pfn = vma->vm_pgoff;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long prot = pgprot_writecombine(vma->vm_page_prot);
- unsigned long addr = vma->vm_pgoff << PAGE_SHIFT;
- void *va = NULL;
-
- if (gsl_driver.enable_mmu && (addr < GSL_LINUX_MAP_RANGE_END) && (addr >= GSL_LINUX_MAP_RANGE_START)) {
- va = gsl_linux_map_find(addr);
- while (size > 0) {
- if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot)) {
- return -EAGAIN;
- }
- start += PAGE_SIZE;
- va += PAGE_SIZE;
- size -= PAGE_SIZE;
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ unsigned long addr = vma->vm_pgoff << PAGE_SHIFT;
+ void *va;
+#endif
+
+#ifdef GSL_MMU_TRANSLATION_ENABLED
+ if (addr < GSL_LINUX_MAP_RANGE_END && addr >= GSL_LINUX_MAP_RANGE_START)
+ {
+ va = gsl_linux_map_find(addr);
+ while (size > 0)
+ {
+ if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot))
+ {
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ va += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
}
- } else {
- if (remap_pfn_range(vma, start, pfn, size, prot)) {
- status = -EAGAIN;
+ else
+#endif
+ {
+ if (remap_pfn_range(vma, start, pfn, size, prot))
+ {
+ status = -EAGAIN;
+ }
}
- }
vma->vm_ops = &gsl_kmod_vmops;
@@ -742,11 +753,13 @@ static irqreturn_t z160_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#if defined(MX51)
static irqreturn_t z430_irq_handler(int irq, void *dev_id)
{
kgsl_intr_isr();
return IRQ_HANDLED;
}
+#endif
static int gpu_probe(struct platform_device *pdev)
{
@@ -754,11 +767,6 @@ static int gpu_probe(struct platform_device *pdev)
struct resource *res;
struct device *dev;
- if (pdev->dev.platform_data)
- z160_version = *((int *)(pdev->dev.platform_data));
- else
- z160_version = 0;
-
for(i = 0; i < 2; i++){
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
if (!res) {
@@ -803,26 +811,24 @@ static int gpu_probe(struct platform_device *pdev)
}
}
- if (gpu_3d_irq > 0)
+ if (kgsl_driver_init() != GSL_SUCCESS)
{
- if (request_irq(gpu_3d_irq, z430_irq_handler, 0, "ydx", NULL) < 0) {
- printk(KERN_ERR "%s: request_irq error\n", __func__);
- gpu_3d_irq = 0;
- goto request_irq_error;
- }
+ printk(KERN_ERR "%s: kgsl_driver_init error\n", __func__);
+ goto kgsl_driver_init_error;
}
- if (gpu_2d_irq > 0)
+#if defined(MX51)
+ if (request_irq(gpu_3d_irq, z430_irq_handler, 0, "ydx", NULL) < 0)
{
- if (request_irq(gpu_2d_irq, z160_irq_handler, 0, "g12", NULL) < 0) {
- printk(KERN_ERR "2D Acceleration Enabled, OpenVG Disabled!\n");
- gpu_2d_irq = 0;
- }
+ printk(KERN_ERR "%s: request_irq error\n", __func__);
+ goto request_irq_error;
}
+#endif
- if (kgsl_driver_init() != GSL_SUCCESS) {
- printk(KERN_ERR "%s: kgsl_driver_init error\n", __func__);
- goto kgsl_driver_init_error;
+ if (request_irq(gpu_2d_irq, z160_irq_handler, 0, "g12", NULL) < 0)
+ {
+ printk(KERN_ERR "2D Acceleration Enabled, OpenVG Disabled!\n");
+ gpu_2d_irq = 0;
}
gsl_kmod_major = register_chrdev(0, "gsl_kmod", &gsl_kmod_fops);
@@ -862,15 +868,9 @@ class_create_error:
register_chrdev_error:
unregister_chrdev(gsl_kmod_major, "gsl_kmod");
+request_irq_error:
kgsl_driver_init_error:
kgsl_driver_close();
- if (gpu_2d_irq > 0) {
- free_irq(gpu_2d_irq, NULL);
- }
- if (gpu_3d_irq > 0) {
- free_irq(gpu_3d_irq, NULL);
- }
-request_irq_error:
return 0; // TODO: return proper error code
}
@@ -879,7 +879,7 @@ static int gpu_remove(struct platform_device *pdev)
device_destroy(gsl_kmod_class, MKDEV(gsl_kmod_major, 0));
class_destroy(gsl_kmod_class);
unregister_chrdev(gsl_kmod_major, "gsl_kmod");
-
+#if defined(MX51)
if (gpu_3d_irq)
{
free_irq(gpu_3d_irq, NULL);
@@ -889,7 +889,12 @@ static int gpu_remove(struct platform_device *pdev)
{
free_irq(gpu_2d_irq, NULL);
}
-
+#elif defined(MX35)
+ if (gpu_2d_irq)
+ {
+ free_irq(gpu_2d_irq, NULL);
+ }
+#endif
kgsl_driver_close();
return 0;
}
@@ -960,5 +965,9 @@ static void __exit gsl_kmod_exit(void)
module_init(gsl_kmod_init);
module_exit(gsl_kmod_exit);
MODULE_AUTHOR("Advanced Micro Devices");
-MODULE_DESCRIPTION("AMD graphics core driver for i.MX");
+#if defined(MX51)
+MODULE_DESCRIPTION("AMD 2D/3D graphics core driver for i.MX51");
+#elif defined(MX35)
+MODULE_DESCRIPTION("AMD 2D graphics core driver for i.MX35");
+#endif
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h
index ebbe94a75e10..0469d2b912be 100644
--- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h
+++ b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h
@@ -32,7 +32,7 @@
#include "gsl_halconfig.h"
#define GSL_LINUX_MAP_RANGE_START (1024*1024)
-#define GSL_LINUX_MAP_RANGE_END (GSL_LINUX_MAP_RANGE_START+GSL_HAL_SHMEM_SIZE_EMEM1_MMU)
+#define GSL_LINUX_MAP_RANGE_END (GSL_LINUX_MAP_RANGE_START+GSL_HAL_SHMEM_SIZE_EMEM1)
int gsl_linux_map_init(void);
void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size);
diff --git a/drivers/mxc/ipu3/ipu_capture.c b/drivers/mxc/ipu3/ipu_capture.c
index b9967135eac1..e801705f8fe9 100644
--- a/drivers/mxc/ipu3/ipu_capture.c
+++ b/drivers/mxc/ipu3/ipu_capture.c
@@ -26,7 +26,6 @@
#include <linux/delay.h>
#include <linux/ipu.h>
#include <linux/clk.h>
-#include <mach/mxc_dvfs.h>
#include "ipu_prv.h"
#include "ipu_regs.h"
@@ -94,12 +93,6 @@ ipu_csi_init_interface(uint16_t width, uint16_t height, uint32_t pixel_fmt,
cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
__raw_writel(data, CSI_SENS_CONF(csi));
@@ -185,13 +178,36 @@ int _ipu_csi_mclk_set(uint32_t pixel_clk, uint32_t csi)
*/
int ipu_csi_enable_mclk(int csi, bool flag, bool wait)
{
+ struct clk *clk;
if (flag) {
- clk_enable(g_csi_clk[csi]);
+ if (cpu_is_mx53()) {
+ if (csi == 0) {
+ clk = clk_get(NULL, "ssi_ext1_clk");
+ clk_enable(clk);
+ clk_put(clk);
+ } else {
+ pr_err("invalid csi num %d\n", csi);
+ return -EINVAL;
+ }
+ } else
+ // CCWMX51 - Both CSIs from master clock 0
+ clk_enable(g_csi_clk[0]);
if (wait == true)
msleep(10);
} else {
- clk_disable(g_csi_clk[csi]);
+ if (cpu_is_mx53()) {
+ if (csi == 0) {
+ clk = clk_get(NULL, "ssi_ext1_clk");
+ clk_disable(clk);
+ clk_put(clk);
+ } else {
+ pr_err("invalid csi num %d\n", csi);
+ return -EINVAL;
+ }
+ } else
+ // CCWMX51 - Both CSIs from master clock 0
+ clk_disable(g_csi_clk[0]);
}
return 0;
@@ -210,12 +226,6 @@ void ipu_csi_get_window_size(uint32_t *width, uint32_t *height, uint32_t csi)
uint32_t reg;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
reg = __raw_readl(CSI_ACT_FRM_SIZE(csi));
@@ -237,12 +247,6 @@ void ipu_csi_set_window_size(uint32_t width, uint32_t height, uint32_t csi)
{
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
__raw_writel((width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE(csi));
@@ -263,12 +267,6 @@ void ipu_csi_set_window_pos(uint32_t left, uint32_t top, uint32_t csi)
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_OUT_FRM_CTRL(csi));
@@ -291,12 +289,6 @@ void _ipu_csi_horizontal_downsize_enable(uint32_t csi)
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_OUT_FRM_CTRL(csi));
@@ -317,12 +309,6 @@ void _ipu_csi_horizontal_downsize_disable(uint32_t csi)
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_OUT_FRM_CTRL(csi));
@@ -343,12 +329,6 @@ void _ipu_csi_vertical_downsize_enable(uint32_t csi)
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_OUT_FRM_CTRL(csi));
@@ -369,12 +349,6 @@ void _ipu_csi_vertical_downsize_disable(uint32_t csi)
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_OUT_FRM_CTRL(csi));
@@ -401,12 +375,6 @@ void ipu_csi_set_test_generator(bool active, uint32_t r_value,
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_TST_CTRL(csi));
@@ -442,12 +410,6 @@ void _ipu_csi_ccir_err_detection_enable(uint32_t csi)
{
uint32_t temp;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
temp = __raw_readl(CSI_CCIR_CODE_1(csi));
temp |= CSI_CCIR_ERR_DET_EN;
__raw_writel(temp, CSI_CCIR_CODE_1(csi));
@@ -464,12 +426,6 @@ void _ipu_csi_ccir_err_detection_disable(uint32_t csi)
{
uint32_t temp;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
temp = __raw_readl(CSI_CCIR_CODE_1(csi));
temp &= ~CSI_CCIR_ERR_DET_EN;
__raw_writel(temp, CSI_CCIR_CODE_1(csi));
@@ -495,12 +451,6 @@ int _ipu_csi_set_mipi_di(uint32_t num, uint32_t di_val, uint32_t csi)
goto err;
}
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_MIPI_DI(csi));
@@ -558,12 +508,6 @@ int _ipu_csi_set_skip_isp(uint32_t skip, uint32_t max_ratio, uint32_t csi)
goto err;
}
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_SKIP(csi));
@@ -601,12 +545,6 @@ int _ipu_csi_set_skip_smfc(uint32_t skip, uint32_t max_ratio,
goto err;
}
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(CSI_SKIP(csi));
@@ -674,12 +612,6 @@ void _ipu_smfc_set_wmc(ipu_channel_t channel, bool set, uint32_t level)
uint32_t temp;
unsigned long lock_flags;
- if (g_ipu_clk_enabled == false) {
- stop_dvfs_per();
- g_ipu_clk_enabled = true;
- clk_enable(g_ipu_clk);
- }
-
spin_lock_irqsave(&ipu_lock, lock_flags);
temp = __raw_readl(SMFC_WMC);
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index b1b8a8b39ae1..eae3b549d765 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -354,8 +354,8 @@ static int ipu_probe(struct platform_device *pdev)
g_di_clk[0] = plat_data->di_clk[0];
g_di_clk[1] = plat_data->di_clk[1];
- g_csi_clk[0] = plat_data->csi_clk[0];
- g_csi_clk[1] = plat_data->csi_clk[1];
+ g_csi_clk[0] = clk_get(&pdev->dev, "csi_mclk1");
+ g_csi_clk[1] = clk_get(&pdev->dev, "csi_mclk2");
__raw_writel(0x807FFFFF, IPU_MEM_RST);
while (__raw_readl(IPU_MEM_RST) & 0x80000000) ;
@@ -1883,29 +1883,29 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
(channel == MEM_DC_SYNC)) {
- if (channel == MEM_FG_SYNC)
- ipu_disp_set_window_pos(channel, 0, 0);
+ int timeout = 50;
+ int irq;
_ipu_dp_dc_disable(channel, false);
/*
- * wait for BG channel EOF then disable FG-IDMAC,
- * it avoid FG NFB4EOF error.
+ * wait for display channel EOF then disable IDMAC,
+ * it avoid NFB4EOF error.
*/
- if (channel == MEM_FG_SYNC) {
- int timeout = 50;
-
- __raw_writel(IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF),
- IPUIRQ_2_STATREG(IPU_IRQ_BG_SYNC_EOF));
- while ((__raw_readl(IPUIRQ_2_STATREG(IPU_IRQ_BG_SYNC_EOF)) &
- IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF)) == 0) {
- msleep(10);
- timeout -= 10;
- if (timeout <= 0) {
- dev_err(g_ipu_dev, "warning: wait for bg sync eof timeout\n");
- break;
- }
- }
+ if (channel == MEM_BG_SYNC)
+ irq = IPU_IRQ_BG_SYNC_EOF;
+ if (channel == MEM_FG_SYNC)
+ irq = IPU_IRQ_FG_SYNC_EOF;
+ else
+ irq = IPU_IRQ_DC_SYNC_EOF;
+ __raw_writel(IPUIRQ_2_MASK(irq),
+ IPUIRQ_2_STATREG(irq));
+ while ((__raw_readl(IPUIRQ_2_STATREG(irq)) &
+ IPUIRQ_2_MASK(irq)) == 0) {
+ msleep(10);
+ timeout -= 10;
+ if (timeout <= 0)
+ break;
}
} else if (wait_for_stop) {
while (idma_is_set(IDMAC_CHA_BUSY, in_dma) ||
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c
index 14dde404990b..7ce04d8bca9e 100644
--- a/drivers/mxc/ipu3/ipu_disp.c
+++ b/drivers/mxc/ipu3/ipu_disp.c
@@ -318,34 +318,22 @@ static void _ipu_dc_map_clear(int map)
}
static void _ipu_dc_write_tmpl(int word, u32 opcode, u32 operand, int map,
- int wave, int glue, int sync, int stop)
+ int wave, int glue, int sync)
{
u32 reg;
-
- if (opcode == WRG) {
- reg = sync;
- reg |= (glue << 4);
- reg |= (++wave << 11);
- reg |= ((operand & 0x1FFFF) << 15);
- __raw_writel(reg, ipu_dc_tmpl_reg + word * 2);
-
- reg = (operand >> 17);
- reg |= opcode << 7;
- reg |= (stop << 9);
- __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1);
- } else {
- reg = sync;
- reg |= (glue << 4);
- reg |= (++wave << 11);
- reg |= (++map << 15);
- reg |= (operand << 20) & 0xFFF00000;
- __raw_writel(reg, ipu_dc_tmpl_reg + word * 2);
-
- reg = (operand >> 12);
- reg |= opcode << 4;
- reg |= (stop << 9);
- __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1);
- }
+ int stop = 1;
+
+ reg = sync;
+ reg |= (glue << 4);
+ reg |= (++wave << 11);
+ reg |= (++map << 15);
+ reg |= (operand << 20) & 0xFFF00000;
+ __raw_writel(reg, ipu_dc_tmpl_reg + word * 2);
+
+ reg = (operand >> 12);
+ reg |= opcode << 4;
+ reg |= (stop << 9);
+ __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1);
}
static void _ipu_dc_link_event(int chan, int event, int addr, int priority)
@@ -735,26 +723,6 @@ static bool dc_swap;
static irqreturn_t dc_irq_handler(int irq, void *dev_id)
{
struct completion *comp = dev_id;
- uint32_t reg;
- uint32_t dc_chan;
-
- if (irq == IPU_IRQ_DC_FC_1)
- dc_chan = 1;
- else
- dc_chan = 5;
-
- if (!dc_swap) {
- reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
- reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
- __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
-
- reg = __raw_readl(IPU_DISP_GEN);
- if (g_dc_di_assignment[dc_chan])
- reg &= ~DI1_COUNTER_RELEASE;
- else
- reg &= ~DI0_COUNTER_RELEASE;
- __raw_writel(reg, IPU_DISP_GEN);
- }
complete(comp);
return IRQ_HANDLED;
@@ -838,6 +806,19 @@ void _ipu_dp_dc_disable(ipu_channel_t channel, bool swap)
__raw_writel(reg, DC_WR_CH_CONF(dc_chan));
spin_unlock_irqrestore(&ipu_lock, lock_flags);
} else {
+ spin_lock_irqsave(&ipu_lock, lock_flags);
+ reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
+ reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+ __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
+
+ reg = __raw_readl(IPU_DISP_GEN);
+ if (g_dc_di_assignment[dc_chan])
+ reg &= ~DI1_COUNTER_RELEASE;
+ else
+ reg &= ~DI0_COUNTER_RELEASE;
+ __raw_writel(reg, IPU_DISP_GEN);
+
+ spin_unlock_irqrestore(&ipu_lock, lock_flags);
/* Clock is already off because it must be done quickly, but
we need to fix the ref count */
clk_disable(g_pixel_clk[g_dc_di_assignment[dc_chan]]);
@@ -1062,13 +1043,9 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
dev_dbg(g_ipu_dev, "pixel clk = %d\n", pixel_clk);
if (sig.ext_clk) {
- /*
- * Set the PLL to be an even multiple of the pixel clock.
- * Not round div for tvout and ldb.
- * Did not consider both DI come from the same ext clk, if
- * meet such case, ext clk rate should be set specially.
- */
- if (clk_get_usecount(g_pixel_clk[disp]) == 0) {
+ /* Set the PLL to be an even multiple of the pixel clock. not round div for tvout*/
+ if ((clk_get_usecount(g_pixel_clk[0]) == 0) &&
+ (clk_get_usecount(g_pixel_clk[1]) == 0)) {
di_parent = clk_get_parent(g_di_clk[disp]);
if (strcmp(di_parent->name, "tve_clk") != 0 &&
strcmp(di_parent->name, "ldb_di0_clk") != 0 &&
@@ -1117,7 +1094,7 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
di_gen = __raw_readl(DI_GENERAL(disp));
if (sig.interlaced) {
- if (g_ipu_hw_rev >= 2) {
+ if (cpu_is_mx51_rev(CHIP_REV_2_0)) {
/* Setup internal HSYNC waveform */
_ipu_di_sync_config(
disp, /* display */
@@ -1357,7 +1334,7 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
}
/* Init template microcode */
- _ipu_dc_write_tmpl(0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
+ _ipu_dc_write_tmpl(0, WROD(0), 0, map, SYNC_WAVE, 0, 8);
if (sig.Hsync_pol)
di_gen |= DI_GEN_POLARITY_3;
@@ -1424,27 +1401,27 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
(pixel_fmt == IPU_PIX_FMT_UYVY) ||
(pixel_fmt == IPU_PIX_FMT_YVYU) ||
(pixel_fmt == IPU_PIX_FMT_VYUY)) {
- _ipu_dc_write_tmpl(8, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1);
- _ipu_dc_write_tmpl(9, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ _ipu_dc_write_tmpl(8, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5);
+ _ipu_dc_write_tmpl(9, WROD(0), 0, map, SYNC_WAVE, 0, 5);
/* configure user events according to DISP NUM */
__raw_writel((width - 1), DC_UGDE_3(disp));
}
- _ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
- _ipu_dc_write_tmpl(3, WRG, 0, map, SYNC_WAVE, 4, 5, 1);
- _ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ _ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5);
+ _ipu_dc_write_tmpl(3, WROD(0), 0, map, SYNC_WAVE, 4, 5);
+ _ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5);
} else {
if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
(pixel_fmt == IPU_PIX_FMT_UYVY) ||
(pixel_fmt == IPU_PIX_FMT_YVYU) ||
(pixel_fmt == IPU_PIX_FMT_VYUY)) {
- _ipu_dc_write_tmpl(10, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1);
- _ipu_dc_write_tmpl(11, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ _ipu_dc_write_tmpl(10, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5);
+ _ipu_dc_write_tmpl(11, WROD(0), 0, map, SYNC_WAVE, 0, 5);
/* configure user events according to DISP NUM */
__raw_writel(width - 1, DC_UGDE_3(disp));
}
- _ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
- _ipu_dc_write_tmpl(6, WRG, 0, map, SYNC_WAVE, 4, 5, 1);
- _ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ _ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5);
+ _ipu_dc_write_tmpl(6, WROD(0), 0, map, SYNC_WAVE, 4, 5);
+ _ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5);
}
if (sig.Hsync_pol)
@@ -1531,7 +1508,7 @@ int ipu_init_async_panel(int disp, int type, uint32_t cycle_time,
_ipu_di_data_pin_config(disp, ASYNC_SER_WAVE, DI_PIN_SER_RS,
2, 0, 0);
- _ipu_dc_write_tmpl(0x64, WROD(0), 0, map, ASYNC_SER_WAVE, 0, 0, 1);
+ _ipu_dc_write_tmpl(0x64, WROD(0), 0, map, ASYNC_SER_WAVE, 0, 0);
/* Configure DC for serial panel */
__raw_writel(0x14, DC_DISP_CONF1(DC_DISP_ID_SERIAL));
@@ -1808,39 +1785,6 @@ int32_t ipu_disp_set_window_pos(ipu_channel_t channel, int16_t x_pos,
}
EXPORT_SYMBOL(ipu_disp_set_window_pos);
-int32_t ipu_disp_get_window_pos(ipu_channel_t channel, int16_t *x_pos,
- int16_t *y_pos)
-{
- u32 reg;
- unsigned long lock_flags;
- uint32_t flow = 0;
-
- if (channel == MEM_FG_SYNC)
- flow = DP_SYNC;
- else if (channel == MEM_FG_ASYNC0)
- flow = DP_ASYNC0;
- else if (channel == MEM_FG_ASYNC1)
- flow = DP_ASYNC1;
- else
- return -EINVAL;
-
- if (!g_ipu_clk_enabled)
- clk_enable(g_ipu_clk);
- spin_lock_irqsave(&ipu_lock, lock_flags);
-
- reg = __raw_readl(DP_FG_POS(flow));
-
- *x_pos = (reg >> 16) & 0x7FF;
- *y_pos = reg & 0x7FF;
-
- spin_unlock_irqrestore(&ipu_lock, lock_flags);
- if (!g_ipu_clk_enabled)
- clk_disable(g_ipu_clk);
-
- return 0;
-}
-EXPORT_SYMBOL(ipu_disp_get_window_pos);
-
void ipu_disp_direct_write(ipu_channel_t channel, u32 value, u32 offset)
{
if (channel == DIRECT_ASYNC0)
diff --git a/drivers/mxc/ipu3/ipu_regs.h b/drivers/mxc/ipu3/ipu_regs.h
index 4a78e14df560..19fde8846aa7 100644
--- a/drivers/mxc/ipu3/ipu_regs.h
+++ b/drivers/mxc/ipu3/ipu_regs.h
@@ -664,6 +664,5 @@ enum di_sync_wave {
/* DC template opcodes */
#define WROD(lf) (0x18 | (lf << 1))
-#define WRG (0x01)
#endif
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
index 9fc25edc33fa..f62e3d46a67c 100644
--- a/drivers/mxc/vpu/mxc_vpu.c
+++ b/drivers/mxc/vpu/mxc_vpu.c
@@ -73,7 +73,6 @@ static struct vpu_mem_desc user_data_mem = { 0 };
static struct vpu_mem_desc share_mem = { 0 };
static void __iomem *vpu_base;
-static int vpu_irq;
static u32 phy_vpu_base_addr;
static struct mxc_vpu_platform_data *vpu_plat;
@@ -540,7 +539,7 @@ static int vpu_map_mem(struct file *fp, struct vm_area_struct *vm)
request_size);
vm->vm_flags |= VM_IO | VM_RESERVED;
- vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot);
+ vm->vm_page_prot = pgprot_noncached(vm->vm_page_prot);
return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff,
request_size, vm->vm_page_prot) ? -EAGAIN : 0;
@@ -636,9 +635,8 @@ static int vpu_dev_probe(struct platform_device *pdev)
err = -ENXIO;
goto err_out_class;
}
- vpu_irq = res->start;
- err = request_irq(vpu_irq, vpu_irq_handler, 0, "VPU_CODEC_IRQ",
+ err = request_irq(res->start, vpu_irq_handler, 0, "VPU_CODEC_IRQ",
(void *)(&vpu_data));
if (err)
goto err_out_class;
@@ -662,7 +660,6 @@ static int vpu_dev_probe(struct platform_device *pdev)
static int vpu_dev_remove(struct platform_device *pdev)
{
- free_irq(vpu_irq, &vpu_data);
iounmap(vpu_base);
iram_free(iram.start, VPU_IRAM_SIZE);
@@ -693,9 +690,7 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
for (i = 0; i < vpu_clk_usercount; i++)
clk_disable(vpu_clk);
- if (!cpu_is_mx37())
- return 0;
- else {
+ if (!cpu_is_mx53()) {
clk_enable(vpu_clk);
if (bitwork_mem.cpu_addr != 0) {
SAVE_WORK_REGS;
@@ -711,7 +706,8 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
clk_disable(vpu_clk);
}
- mxc_pg_enable(pdev);
+ if (cpu_is_mx37() || cpu_is_mx51())
+ mxc_pg_enable(pdev);
return 0;
@@ -725,10 +721,11 @@ static int vpu_resume(struct platform_device *pdev)
{
int i;
- if (cpu_is_mx37())
+ if (cpu_is_mx37() || cpu_is_mx51())
mxc_pg_disable(pdev);
- else
- goto recover_clk;
+
+ if (cpu_is_mx53())
+ goto recover_clk;
clk_enable(vpu_clk);
if (bitwork_mem.cpu_addr != 0) {
@@ -799,7 +796,6 @@ recover_clk:
/* Recover vpu clock */
for (i = 0; i < vpu_clk_usercount; i++)
clk_enable(vpu_clk);
- printk("vpu_resume end\n");
return 0;
}
@@ -832,6 +828,7 @@ static int __init vpu_init(void)
static void __exit vpu_exit(void)
{
+ free_irq(MXC_INT_VPU, (void *)(&vpu_data));
if (vpu_major > 0) {
device_destroy(vpu_class, MKDEV(vpu_major, 0));
class_destroy(vpu_class);
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 08419ee10290..12bfc447a896 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -1209,7 +1209,8 @@ static int __devinit ace_init(struct net_device *dev)
memset(ap->info, 0, sizeof(struct ace_info));
memset(ap->skb, 0, sizeof(struct ace_skb));
- if (ace_load_firmware(dev))
+ ecode = ace_load_firmware(dev);
+ if (ecode)
goto init_error;
ap->fw_running = 0;
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 78cea5e80b1d..bf9ab65d27a4 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -176,8 +176,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
- dev_kfree_skb(skb);
+ aarp_send_ddp(rt->dev, skb, &rt->at, NULL);
spin_unlock(&ipddp_route_lock);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index d3c734f4d679..2f6ae784a36f 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1089,7 +1089,14 @@ static struct net_device * au1000_probe(int port_num)
return NULL;
}
- if ((err = register_netdev(dev)) != 0) {
+ dev->base_addr = base;
+ dev->irq = irq;
+ dev->netdev_ops = &au1000_netdev_ops;
+ SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
+ dev->watchdog_timeo = ETH_TX_TIMEOUT;
+
+ err = register_netdev(dev);
+ if (err != 0) {
printk(KERN_ERR "%s: Cannot register net device, error %d\n",
DRV_NAME, err);
free_netdev(dev);
@@ -1207,12 +1214,6 @@ static struct net_device * au1000_probe(int port_num)
aup->tx_db_inuse[i] = pDB;
}
- dev->base_addr = base;
- dev->irq = irq;
- dev->netdev_ops = &au1000_netdev_ops;
- SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
- dev->watchdog_timeo = ETH_TX_TIMEOUT;
-
/*
* The boot code uses the ethernet controller, so reset it to start
* fresh. au1000_init() expects that the device is in reset state.
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index bafca672ea7d..351a258dccd6 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -913,9 +913,6 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
bp->istat = istat;
__b44_disable_ints(bp);
__napi_schedule(&bp->napi);
- } else {
- printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
- dev->name);
}
irq_ack:
@@ -1505,8 +1502,7 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
for (k = 0; k< ethaddr_bytes; k++) {
ppattern[offset + magicsync +
(j * ETH_ALEN) + k] = macaddr[k];
- len++;
- set_bit(len, (unsigned long *) pmask);
+ set_bit(len++, (unsigned long *) pmask);
}
}
return len - 1;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index aa1be1feceed..bcd8df92dec7 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -691,7 +691,7 @@ static int bond_check_dev_link(struct bonding *bond,
struct net_device *slave_dev, int reporting)
{
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
- static int (*ioctl)(struct net_device *, struct ifreq *, int);
+ int (*ioctl)(struct net_device *, struct ifreq *, int);
struct ifreq ifr;
struct mii_ioctl_data *mii;
@@ -3707,10 +3707,10 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb,
if (skb->protocol == htons(ETH_P_IP)) {
return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
- (data->h_dest[5] ^ bond_dev->dev_addr[5])) % count;
+ (data->h_dest[5] ^ data->h_source[5])) % count;
}
- return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+ return (data->h_dest[5] ^ data->h_source[5]) % count;
}
/*
@@ -3737,7 +3737,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
}
- return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+ return (data->h_dest[5] ^ data->h_source[5]) % count;
}
/*
@@ -3748,7 +3748,7 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
{
struct ethhdr *data = (struct ethhdr *)skb->data;
- return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+ return (data->h_dest[5] ^ data->h_source[5]) % count;
}
/*-------------------------- Device entry points ----------------------------*/
diff --git a/drivers/net/can/flexcan/mbm.c b/drivers/net/can/flexcan/mbm.c
index c846d97daadb..42266e719ce3 100644
--- a/drivers/net/can/flexcan/mbm.c
+++ b/drivers/net/can/flexcan/mbm.c
@@ -294,7 +294,7 @@ int flexcan_mbm_xmit(struct flexcan_device *flexcan, struct can_frame *frame)
hwmb[i].mb_id = (frame->can_id & CAN_SFF_MASK) << 18;
}
- hwmb[i].mb_cs &= ~MB_CS_LENGTH_MASK;
+ hwmb[i].mb_cs &= MB_CS_LENGTH_MASK;
hwmb[i].mb_cs |= frame->can_dlc << MB_CS_LENGTH_OFFSET;
flexcan_memcpy(hwmb[i].mb_data, frame->data, frame->can_dlc);
hwmb[i].mb_cs &= ~MB_CS_CODE_MASK;
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index a10c1d7b3b0a..460bb886fbdf 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -80,7 +80,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
+ netif_rx_ni(skb);
}
static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 3a6735dc9f6a..c786e6a96eae 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -156,6 +156,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
@@ -601,6 +602,7 @@ struct nic {
struct mem *mem;
dma_addr_t dma_addr;
+ struct pci_pool *cbs_pool;
dma_addr_t cbs_dma_addr;
u8 adaptive_ifs;
u8 tx_threshold;
@@ -1779,9 +1781,7 @@ static void e100_clean_cbs(struct nic *nic)
nic->cb_to_clean = nic->cb_to_clean->next;
nic->cbs_avail++;
}
- pci_free_consistent(nic->pdev,
- sizeof(struct cb) * nic->params.cbs.count,
- nic->cbs, nic->cbs_dma_addr);
+ pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr);
nic->cbs = NULL;
nic->cbs_avail = 0;
}
@@ -1799,10 +1799,11 @@ static int e100_alloc_cbs(struct nic *nic)
nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;
nic->cbs_avail = 0;
- nic->cbs = pci_alloc_consistent(nic->pdev,
- sizeof(struct cb) * count, &nic->cbs_dma_addr);
+ nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL,
+ &nic->cbs_dma_addr);
if (!nic->cbs)
return -ENOMEM;
+ memset(nic->cbs, 0, count * sizeof(struct cb));
for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
@@ -1811,7 +1812,6 @@ static int e100_alloc_cbs(struct nic *nic)
cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
cb->link = cpu_to_le32(nic->cbs_dma_addr +
((i+1) % count) * sizeof(struct cb));
- cb->skb = NULL;
}
nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
@@ -2827,7 +2827,11 @@ static int __devinit e100_probe(struct pci_dev *pdev,
DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
goto err_out_free;
}
-
+ nic->cbs_pool = pci_pool_create(netdev->name,
+ nic->pdev,
+ nic->params.cbs.count * sizeof(struct cb),
+ sizeof(u32),
+ 0);
DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n",
(unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
pdev->irq, netdev->dev_addr);
@@ -2857,6 +2861,7 @@ static void __devexit e100_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
e100_free(nic);
pci_iounmap(pdev, nic->csr);
+ pci_pool_destroy(nic->cbs_pool);
free_netdev(netdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index b53b40ba88a8..d1e0563a67df 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -1803,7 +1803,7 @@ struct e1000_info e1000_82574_info = {
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
.pba = 20,
- .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN,
+ .max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
.mac_ops = &e82571_mac_ops,
.phy_ops = &e82_phy_ops_bm,
@@ -1820,7 +1820,7 @@ struct e1000_info e1000_82583_info = {
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
.pba = 20,
- .max_hw_frame_size = DEFAULT_JUMBO,
+ .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN,
.get_variants = e1000_get_variants_82571,
.mac_ops = &e82571_mac_ops,
.phy_ops = &e82_phy_ops_bm,
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 206be36f0d19..d8817aad351f 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -296,17 +296,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
bufaddr = fep->tx_bounce[index];
}
- if (fep->ptimer_present) {
- if (fec_ptp_do_txstamp(skb))
- estatus = BD_ENET_TX_TS;
- else
- estatus = 0;
-#ifdef CONFIG_FEC_1588
- bdp->cbd_esc = (estatus | BD_ENET_TX_INT);
- bdp->cbd_bdu = 0;
-#endif
- }
-
#ifdef CONFIG_ARCH_MXS
swap_buffer(bufaddr, skb->len);
#endif
@@ -329,6 +318,16 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
| BD_ENET_TX_LAST | BD_ENET_TX_TC);
bdp->cbd_sc = status;
+ if (fep->ptimer_present) {
+ if (fec_ptp_do_txstamp(skb))
+ estatus = BD_ENET_TX_TS;
+ else
+ estatus = 0;
+#ifdef CONFIG_FEC_1588
+ bdp->cbd_esc = (estatus | BD_ENET_TX_INT);
+ bdp->cbd_bdu = 0;
+#endif
+ }
dev->trans_start = jiffies;
/* Trigger transmission start */
@@ -808,7 +807,7 @@ static struct mii_bus *fec_enet_mii_init(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(dev);
- struct fec_platform_data *pdata;
+ struct fec_enet_platform_data *pdata;
int err = -ENXIO, i;
fep->mii_timeout = 0;
@@ -837,7 +836,6 @@ static struct mii_bus *fec_enet_mii_init(struct platform_device *pdev)
fep->mii_bus->priv = fep;
fep->mii_bus->parent = &pdev->dev;
pdata = pdev->dev.platform_data;
- fep->mii_bus->phy_mask = pdata->phy_mask;
fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (!fep->mii_bus->irq) {
@@ -1412,15 +1410,6 @@ fec_stop(struct net_device *dev)
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
-#ifdef CONFIG_ARCH_MXS
- /* Check MII or RMII */
- if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
- writel(readl(fep->hwp + FEC_R_CNTRL) | 0x100,
- fep->hwp + FEC_R_CNTRL);
- else
- writel(readl(fep->hwp + FEC_R_CNTRL) & ~0x100,
- fep->hwp + FEC_R_CNTRL);
-#endif
/* Clear outstanding MII command interrupts. */
writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
@@ -1496,18 +1485,6 @@ fec_probe(struct platform_device *pdev)
fep->phy_interface = pdata->phy;
if (pdata->init && pdata->init())
goto failed_platform_init;
-
- /*
- * The priority for getting MAC address is:
- * (1) kernel command line fec_mac = xx:xx:xx...
- * (2) platform data mac field got from fuse etc
- * (3) bootloader set the FEC mac register
- */
-
- if (!is_valid_ether_addr(fec_mac_default) &&
- pdata->mac && is_valid_ether_addr(pdata->mac))
- memcpy(fec_mac_default, pdata->mac,
- sizeof(fec_mac_default));
} else
fep->phy_interface = PHY_INTERFACE_MODE_MII;
diff --git a/drivers/net/fec_1588.c b/drivers/net/fec_1588.c
index c4bf278c7f19..37b1b01778fd 100644
--- a/drivers/net/fec_1588.c
+++ b/drivers/net/fec_1588.c
@@ -178,19 +178,12 @@ void fec_ptp_stop(struct fec_ptp_private *priv)
static void fec_get_curr_cnt(struct fec_ptp_private *priv,
struct ptp_rtc_time *curr_time)
{
- u32 tempval;
-
- writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
curr_time->rtc_time.nsec = readl(priv->hwp + FEC_ATIME);
curr_time->rtc_time.sec = priv->prtc;
-
writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
- tempval = readl(priv->hwp + FEC_ATIME);
- if (tempval < curr_time->rtc_time.nsec) {
- curr_time->rtc_time.nsec = tempval;
- curr_time->rtc_time.sec = priv->prtc;
- }
+ if (readl(priv->hwp + FEC_ATIME) < curr_time->rtc_time.nsec)
+ curr_time->rtc_time.sec++;
}
/* Set the 1588 timer counter registers */
@@ -221,7 +214,7 @@ int fec_ptp_do_txstamp(struct sk_buff *skb)
return 0;
udph = udp_hdr(skb);
- if (udph != NULL && ntohs(udph->source) == 319)
+ if (udph != NULL && udph->source == 319)
return 1;
}
@@ -254,13 +247,13 @@ void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
return;
udph = (struct udphdr *)(skb->data + FEC_PTP_UDP_OFFS);
- if (ntohs(udph->source) != 319)
+ if (udph->source != 319)
return;
seq_id = *((u16 *)(skb->data + FEC_PTP_SEQ_ID_OFFS));
control = *((u8 *)(skb->data + FEC_PTP_CTRL_OFFS));
- tmp_rx_time.key = ntohs(seq_id);
+ tmp_rx_time.key = seq_id;
tmp_rx_time.ts_time.sec = fpp->prtc;
tmp_rx_time.ts_time.nsec = bdp->ts;
@@ -377,75 +370,6 @@ static uint8_t fec_get_rx_time(struct fec_ptp_private *priv,
}
}
-static void fec_handle_ptpdrift(struct ptp_set_comp *comp,
- struct ptp_time_correct *ptc)
-{
- u32 ndrift;
- u32 i;
- u32 tmp, tmp_ns, tmp_prid;
- u32 min_ns, min_prid, miss_ns;
-
- ndrift = comp->drift;
- if (ndrift == 0) {
- ptc->corr_inc = 0;
- ptc->corr_period = 0;
- return;
- }
-
- if (ndrift >= FEC_ATIME_40MHZ) {
- ptc->corr_inc = (u32)(ndrift / FEC_ATIME_40MHZ);
- ptc->corr_period = 1;
- return;
- }
-
- min_ns = 1;
- tmp = FEC_ATIME_40MHZ % ndrift;
- tmp_prid = (u32)(FEC_ATIME_40MHZ / ndrift);
- min_prid = tmp_prid;
- miss_ns = tmp / tmp_prid;
- for (i = 2; i <= FEC_T_INC_40MHZ; i++) {
- tmp = (FEC_ATIME_40MHZ * i) % ndrift;
- tmp_prid = (FEC_ATIME_40MHZ * i) / ndrift;
- tmp_ns = tmp / tmp_prid;
- if (tmp_ns <= 10) {
- min_ns = i;
- min_prid = tmp_prid;
- break;
- }
- if (tmp_ns < miss_ns) {
- min_ns = i;
- min_prid = tmp_prid;
- miss_ns = tmp_ns;
- }
- }
-
- ptc->corr_inc = min_ns;
- ptc->corr_period = min_prid;
-}
-
-static void fec_set_drift(struct fec_ptp_private *priv,
- struct ptp_set_comp *comp)
-{
- struct ptp_time_correct tc;
- struct fec_ptp_private *fpp = priv;
- u32 tmp, corr_ns;
-
- fec_handle_ptpdrift(comp, &tc);
- if (tc.corr_inc == 0)
- return;
-
- if (comp->o_ops == TRUE)
- corr_ns = FEC_T_INC_40MHZ + tc.corr_inc;
- else
- corr_ns = FEC_T_INC_40MHZ - tc.corr_inc;
-
- tmp = readl(fpp->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
- tmp |= corr_ns << FEC_T_INC_CORR_OFFSET;
- writel(tmp, fpp->hwp + FEC_ATIME_INC);
-
- writel(tc.corr_period, fpp->hwp + FEC_ATIME_CORR);
-}
-
static int ptp_open(struct inode *inode, struct file *file)
{
return 0;
@@ -466,7 +390,6 @@ static int ptp_ioctl(
struct ptp_rtc_time curr_time;
struct ptp_time rx_time, tx_time;
struct ptp_ts_data *p_ts;
- struct ptp_set_comp *p_comp;
struct fec_ptp_private *priv;
unsigned int minor = MINOR(inode->i_rdev);
int retval = 0;
@@ -509,11 +432,10 @@ static int ptp_ioctl(
priv->rx_time_pdel_resp.tail = 0;
break;
case PTP_SET_COMPENSATION:
- p_comp = (struct ptp_set_comp *)arg;
- fec_set_drift(priv, p_comp);
+ /* TBD */
break;
case PTP_GET_ORIG_COMP:
- ((struct ptp_get_comp *)arg)->dw_origcomp = FEC_PTP_ORIG_COMP;
+ /* TBD */
break;
default:
return -EINVAL;
diff --git a/drivers/net/fec_1588.h b/drivers/net/fec_1588.h
index 800ff310668f..a503527eadbb 100644
--- a/drivers/net/fec_1588.h
+++ b/drivers/net/fec_1588.h
@@ -24,9 +24,6 @@
#include <linux/circ_buf.h>
-#define FALSE 0
-#define TRUE 1
-
/* FEC 1588 register bits */
#define FEC_T_CTRL_CAPTURE 0x00000800
#define FEC_T_CTRL_RESTART 0x00000200
@@ -35,11 +32,8 @@
#define FEC_T_INC_MASK 0x0000007f
#define FEC_T_INC_OFFSET 0
-#define FEC_T_INC_CORR_MASK 0x00007f00
-#define FEC_T_INC_CORR_OFFSET 8
#define FEC_T_INC_40MHZ 25
-#define FEC_ATIME_40MHZ 40000000
#define FEC_T_PERIOD_ONE_SEC 0x3B9ACA00
@@ -58,7 +52,7 @@
#define PTP_MSG_ALL_OTHER 0x5
#define PTP_GET_TX_TIMESTAMP 0x1
-#define PTP_GET_RX_TIMESTAMP 0x9
+#define PTP_GET_RX_TIMESTAMP 0x2
#define PTP_SET_RTC_TIME 0x3
#define PTP_SET_COMPENSATION 0x4
#define PTP_GET_CURRENT_TIME 0x5
@@ -70,15 +64,13 @@
#define PTP_GET_RX_TIMESTAMP_PDELAY_RESP 0xD
#define FEC_PTP_DOMAIN_DLFT 0xe0000181
-#define FEC_PTP_IP_OFFS 0x0
-#define FEC_PTP_UDP_OFFS 0x14
-#define FEC_PTP_MSG_TYPE_OFFS 0x1C
-#define FEC_PTP_SEQ_ID_OFFS 0x3A
-#define FEC_PTP_CTRL_OFFS 0x3C
+#define FEC_PTP_IP_OFFS 0xE
+#define FEC_PTP_UDP_OFFS 0x22
+#define FEC_PTP_MSG_TYPE_OFFS 0x2A
+#define FEC_PTP_SEQ_ID_OFFS 0x48
+#define FEC_PTP_CTRL_OFFS 0x4A
#define FEC_PACKET_TYPE_UDP 0x11
-#define FEC_PTP_ORIG_COMP 0x15555555
-
/* PTP standard time representation structure */
struct ptp_time{
u64 sec; /* seconds */
@@ -110,31 +102,6 @@ struct ptp_rtc_time {
struct ptp_time rtc_time;
};
-/* interface for PTP driver command SET_COMPENSATION */
-struct ptp_set_comp {
- u32 drift;
- bool o_ops;
-};
-
-/* interface for PTP driver command GET_ORIG_COMP */
-struct ptp_get_comp {
- /* the initial compensation value */
- u32 dw_origcomp;
- /* the minimum compensation value */
- u32 dw_mincomp;
- /*the max compensation value*/
- u32 dw_maxcomp;
- /*the min drift applying min compensation value in ppm*/
- u32 dw_mindrift;
- /*the max drift applying max compensation value in ppm*/
- u32 dw_maxdrift;
-};
-
-struct ptp_time_correct {
- u32 corr_period;
- u32 corr_inc;
-};
-
/* PTP message version */
#define PTP_1588_MSG_VER_1 1
#define PTP_1588_MSG_VER_2 2
diff --git a/drivers/net/fec_switch.c b/drivers/net/fec_switch.c
index 0485349dcd76..f2c78e439278 100644
--- a/drivers/net/fec_switch.c
+++ b/drivers/net/fec_switch.c
@@ -131,13 +131,9 @@ static void *swap_buffer(void *bufaddr, int len)
/*last read entry from learning interface*/
struct eswPortInfo g_info;
-#ifdef USE_DEFAULT_SWITCH_PORT0_MAC
static unsigned char switch_mac_default[] = {
0x00, 0x08, 0x02, 0x6B, 0xA3, 0x1A,
};
-#else
-static unsigned char switch_mac_default[ETH_ALEN];
-#endif
static void switch_request_intrs(struct net_device *dev,
irqreturn_t switch_net_irq_handler(int irq, void *private),
@@ -3704,19 +3700,6 @@ static int __init switch_enet_init(struct net_device *dev,
fep->phy_interface = plat->fec_enet->phy;
if (plat->fec_enet->init && plat->fec_enet->init())
return -EIO;
-
- /*
- * The priority for getting MAC address is:
- * (1) kernel command line fec_mac = xx:xx:xx...
- * (2) platform data mac field got from fuse etc
- * (3) bootloader set the FEC mac register
- */
-
- if (!is_valid_ether_addr(switch_mac_default) &&
- plat->fec_enet->mac &&
- is_valid_ether_addr(plat->fec_enet->mac))
- memcpy(switch_mac_default, plat->fec_enet->mac,
- sizeof(switch_mac_default));
} else
fep->phy_interface = PHY_INTERFACE_MODE_MII;
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index e44215cb1882..9048718aff1b 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -495,7 +495,7 @@ static void veth_take_cap_ack(struct veth_lpar_connection *cnx,
cnx->remote_lp);
} else {
memcpy(&cnx->cap_ack_event, event,
- sizeof(&cnx->cap_ack_event));
+ sizeof(cnx->cap_ack_event));
cnx->state |= VETH_STATE_GOTCAPACK;
veth_kick_statemachine(cnx);
}
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index b9ceddde46c0..4ff665c0f144 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -526,48 +526,6 @@ static void mlx4_unmap_clr_int(struct mlx4_dev *dev)
iounmap(priv->clr_base);
}
-int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int ret;
-
- /*
- * We assume that mapping one page is enough for the whole EQ
- * context table. This is fine with all current HCAs, because
- * we only use 32 EQs and each EQ uses 64 bytes of context
- * memory, or 1 KB total.
- */
- priv->eq_table.icm_virt = icm_virt;
- priv->eq_table.icm_page = alloc_page(GFP_HIGHUSER);
- if (!priv->eq_table.icm_page)
- return -ENOMEM;
- priv->eq_table.icm_dma = pci_map_page(dev->pdev, priv->eq_table.icm_page, 0,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(dev->pdev, priv->eq_table.icm_dma)) {
- __free_page(priv->eq_table.icm_page);
- return -ENOMEM;
- }
-
- ret = mlx4_MAP_ICM_page(dev, priv->eq_table.icm_dma, icm_virt);
- if (ret) {
- pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
- __free_page(priv->eq_table.icm_page);
- }
-
- return ret;
-}
-
-void mlx4_unmap_eq_icm(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- mlx4_UNMAP_ICM(dev, priv->eq_table.icm_virt, 1);
- pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
- __free_page(priv->eq_table.icm_page);
-}
-
int mlx4_alloc_eq_table(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index dac621b1e9fc..8e8b79fed508 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -525,7 +525,10 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
goto err_unmap_aux;
}
- err = mlx4_map_eq_icm(dev, init_hca->eqc_base);
+ err = mlx4_init_icm_table(dev, &priv->eq_table.table,
+ init_hca->eqc_base, dev_cap->eqc_entry_sz,
+ dev->caps.num_eqs, dev->caps.num_eqs,
+ 0, 0);
if (err) {
mlx4_err(dev, "Failed to map EQ context memory, aborting.\n");
goto err_unmap_cmpt;
@@ -668,7 +671,7 @@ err_unmap_mtt:
mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table);
err_unmap_eq:
- mlx4_unmap_eq_icm(dev);
+ mlx4_cleanup_icm_table(dev, &priv->eq_table.table);
err_unmap_cmpt:
mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table);
@@ -698,11 +701,11 @@ static void mlx4_free_icms(struct mlx4_dev *dev)
mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table);
mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table);
mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table);
+ mlx4_cleanup_icm_table(dev, &priv->eq_table.table);
mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table);
mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table);
mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table);
mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
- mlx4_unmap_eq_icm(dev);
mlx4_UNMAP_ICM_AUX(dev);
mlx4_free_icm(dev, priv->fw.aux_icm, 0);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 5bd79c2b184f..bc72d6e4919b 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -205,9 +205,7 @@ struct mlx4_eq_table {
void __iomem **uar_map;
u32 clr_mask;
struct mlx4_eq *eq;
- u64 icm_virt;
- struct page *icm_page;
- dma_addr_t icm_dma;
+ struct mlx4_icm_table table;
struct mlx4_icm_table cmpt_table;
int have_irq;
u8 inta_pin;
@@ -373,9 +371,6 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
struct mlx4_dev_cap *dev_cap,
struct mlx4_init_hca_param *init_hca);
-int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt);
-void mlx4_unmap_eq_icm(struct mlx4_dev *dev);
-
int mlx4_cmd_init(struct mlx4_dev *dev);
void mlx4_cmd_cleanup(struct mlx4_dev *dev);
void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param);
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 01f9432c31ef..98bff5ada09a 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -444,7 +444,8 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
* the appropriate LRO method
*/
static void efx_rx_packet_lro(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf)
+ struct efx_rx_buffer *rx_buf,
+ bool checksummed)
{
struct napi_struct *napi = &channel->napi_str;
@@ -466,7 +467,8 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
skb->len = rx_buf->len;
skb->data_len = rx_buf->len;
skb->truesize += rx_buf->len;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->ip_summed =
+ checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
napi_gro_frags(napi);
@@ -475,6 +477,7 @@ out:
rx_buf->page = NULL;
} else {
EFX_BUG_ON_PARANOID(!rx_buf->skb);
+ EFX_BUG_ON_PARANOID(!checksummed);
napi_gro_receive(napi, rx_buf->skb);
rx_buf->skb = NULL;
@@ -570,7 +573,7 @@ void __efx_rx_packet(struct efx_channel *channel,
}
if (likely(checksummed || rx_buf->page)) {
- efx_rx_packet_lro(channel, rx_buf);
+ efx_rx_packet_lro(channel, rx_buf, checksummed);
goto done;
}
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 14a14788566c..d36a2894f005 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -823,8 +823,6 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
tx_queue->efx->type->txd_ring_mask];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->skb);
- buffer->len = 0;
- buffer->continuation = true;
if (buffer->unmap_len) {
unmap_addr = (buffer->dma_addr + buffer->len -
buffer->unmap_len);
@@ -838,6 +836,8 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
PCI_DMA_TODEVICE);
buffer->unmap_len = 0;
}
+ buffer->len = 0;
+ buffer->continuation = true;
}
}
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 0a551d8f5d95..329f447f5bf7 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1455,7 +1455,6 @@ static int sky2_up(struct net_device *dev)
if (ramsize > 0) {
u32 rxspace;
- hw->flags |= SKY2_HW_RAM_BUFFER;
pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
if (ramsize < 16)
rxspace = ramsize / 2;
@@ -2942,6 +2941,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
++hw->ports;
}
+ if (sky2_read8(hw, B2_E_0))
+ hw->flags |= SKY2_HW_RAM_BUFFER;
+
return 0;
}
@@ -4526,6 +4528,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_netdev;
}
+ netif_carrier_off(dev);
+
netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
err = request_irq(pdev->irq, sky2_intr,
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 7567f510eff5..d8ed1b63da78 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -2283,7 +2283,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
ndev->irq = ires->start;
- if (ires->flags & IRQF_TRIGGER_MASK)
+ if (irq_flags == -1 || ires->flags & IRQF_TRIGGER_MASK)
irq_flags = ires->flags & IRQF_TRIGGER_MASK;
ret = smc_request_attrib(pdev, ndev);
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 60abdb1081ad..97ababd189c6 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -252,6 +252,9 @@ static int smsc9420_ethtool_get_settings(struct net_device *dev,
{
struct smsc9420_pdata *pd = netdev_priv(dev);
+ if (!pd->phy_dev)
+ return -ENODEV;
+
cmd->maxtxpkt = 1;
cmd->maxrxpkt = 1;
return phy_ethtool_gset(pd->phy_dev, cmd);
@@ -262,6 +265,9 @@ static int smsc9420_ethtool_set_settings(struct net_device *dev,
{
struct smsc9420_pdata *pd = netdev_priv(dev);
+ if (!pd->phy_dev)
+ return -ENODEV;
+
return phy_ethtool_sset(pd->phy_dev, cmd);
}
@@ -290,6 +296,10 @@ static void smsc9420_ethtool_set_msglevel(struct net_device *netdev, u32 data)
static int smsc9420_ethtool_nway_reset(struct net_device *netdev)
{
struct smsc9420_pdata *pd = netdev_priv(netdev);
+
+ if (!pd->phy_dev)
+ return -ENODEV;
+
return phy_start_aneg(pd->phy_dev);
}
@@ -312,6 +322,10 @@ smsc9420_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs,
for (i = 0; i < 0x100; i += (sizeof(u32)))
data[j++] = smsc9420_reg_read(pd, i);
+ // cannot read phy registers if the net device is down
+ if (!phy_dev)
+ return;
+
for (i = 0; i <= 31; i++)
data[j++] = smsc9420_mii_read(phy_dev->bus, phy_dev->addr, i);
}
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 42b6c6319bc2..156f59b25191 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -943,8 +943,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
char *name;
unsigned long flags = 0;
- err = -EINVAL;
-
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -958,7 +956,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
flags |= TUN_TAP_DEV;
name = "tap%d";
} else
- goto failed;
+ return -EINVAL;
if (*ifr->ifr_name)
name = ifr->ifr_name;
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index f8c6d7ea7264..9e1fc2968cf1 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1362,7 +1362,7 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
/* reset the rts and dtr */
/* do the actual close */
serial->open_count--;
- kref_put(&serial->parent->ref, hso_serial_ref_free);
+
if (serial->open_count <= 0) {
serial->open_count = 0;
spin_lock_irq(&serial->serial_lock);
@@ -1382,6 +1382,8 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
usb_autopm_put_interface(serial->parent->interface);
mutex_unlock(&serial->parent->mutex);
+
+ kref_put(&serial->parent->ref, hso_serial_ref_free);
}
/* close the requested serial port */
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 1f9ec29fce50..65a43c8e76b5 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth,
int timeout)
{
struct usb_ctrlrequest *dr;
+ int retval;
dbg("kaweth_control()");
@@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth,
return -ENOMEM;
}
- dr->bRequestType= requesttype;
+ dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(size);
- return kaweth_internal_control_msg(kaweth->dev,
- pipe,
- dr,
- data,
- size,
- timeout);
+ retval = kaweth_internal_control_msg(kaweth->dev,
+ pipe,
+ dr,
+ data,
+ size,
+ timeout);
+
+ kfree(dr);
+ return retval;
}
/****************************************************************
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index fcc6fa0905d1..18686839cd12 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -324,7 +324,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
dbg("%02X:", netdev->dev_addr[i]);
dbg("%02X\n", netdev->dev_addr[i]);
/* Set the IDR registers. */
- set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr);
+ set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr);
#ifdef EEPROM_WRITE
{
u8 cr;
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index fe045896406b..df49d0daaa16 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1232,7 +1232,7 @@ static const struct driver_info smsc95xx_info = {
.rx_fixup = smsc95xx_rx_fixup,
.tx_fixup = smsc95xx_tx_fixup,
.status = smsc95xx_status,
- .flags = FLAG_ETHER,
+ .flags = FLAG_ETHER | FLAG_SEND_ZLP,
};
static const struct usb_device_id products[] = {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index edfd9e10ceba..d49df7352017 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -988,7 +988,7 @@ int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
* NOTE: strictly conforming cdc-ether devices should expect
* the ZLP here, but ignore the one-byte packet.
*/
- if ((length % dev->maxpacket) == 0) {
+ if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
urb->transfer_buffer_length++;
if (skb_tailroom(skb)) {
skb->data[skb->len] = 0;
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 8ce5e4cee168..374f74702156 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5249,11 +5249,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
WepKeyRid wkr;
int rc;
- if (keylen == 0) {
- airo_print_err(ai->dev->name, "%s: key length to set was zero",
- __func__);
- return -1;
- }
+ WARN_ON(keylen == 0);
memset(&wkr, 0, sizeof(wkr));
wkr.len = cpu_to_le16(sizeof(wkr));
@@ -6399,11 +6395,7 @@ static int airo_set_encode(struct net_device *dev,
if (dwrq->length > MIN_KEY_SIZE)
key.len = MAX_KEY_SIZE;
else
- if (dwrq->length > 0)
- key.len = MIN_KEY_SIZE;
- else
- /* Disable the key */
- key.len = 0;
+ key.len = MIN_KEY_SIZE;
/* Check if the key is not marked as invalid */
if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
/* Cleanup */
@@ -6584,12 +6576,22 @@ static int airo_set_encodeext(struct net_device *dev,
default:
return -EINVAL;
}
- /* Send the key to the card */
- rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
- if (rc < 0) {
- airo_print_err(local->dev->name, "failed to set WEP key"
- " at index %d: %d.", idx, rc);
- return rc;
+ if (key.len == 0) {
+ rc = set_wep_tx_idx(local, idx, perm, 1);
+ if (rc < 0) {
+ airo_print_err(local->dev->name,
+ "failed to set WEP transmit index to %d: %d.",
+ idx, rc);
+ return rc;
+ }
+ } else {
+ rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
+ if (rc < 0) {
+ airo_print_err(local->dev->name,
+ "failed to set WEP key at index %d: %d.",
+ idx, rc);
+ return rc;
+ }
}
}
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 007eb85fc67e..1084ca69835f 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x9170) },
/* Atheros TG121N */
{ USB_DEVICE(0x0cf3, 0x1001) },
+ /* TP-Link TL-WN821N v2 */
+ { USB_DEVICE(0x0cf3, 0x1002) },
/* Cace Airpcap NX */
{ USB_DEVICE(0xcace, 0x0300) },
/* D-Link DWA 160A */
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 6358233bac99..778baf7de231 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1164,6 +1164,7 @@ extern void ath5k_unregister_leds(struct ath5k_softc *sc);
/* Reset Functions */
extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+extern int ath5k_hw_on_hold(struct ath5k_hw *ah);
extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
/* Power management functions */
extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index c41ef58393e7..605b8f67dbe0 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -145,7 +145,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
goto err_free;
/* Bring device out of sleep and reset it's units */
- ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
+ ret = ath5k_hw_nic_wakeup(ah, 0, true);
if (ret)
goto err_free;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 029c1bc7468f..753f50e8d84f 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -666,7 +666,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
ath5k_led_off(sc);
- free_irq(pdev->irq, sc);
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
@@ -694,18 +693,8 @@ ath5k_pci_resume(struct pci_dev *pdev)
*/
pci_write_config_byte(pdev, 0x41, 0);
- err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
- if (err) {
- ATH5K_ERR(sc, "request_irq failed\n");
- goto err_no_irq;
- }
-
ath5k_led_enable(sc);
return 0;
-
-err_no_irq:
- pci_disable_device(pdev);
- return err;
}
#endif /* CONFIG_PM */
@@ -2445,27 +2434,29 @@ ath5k_stop_hw(struct ath5k_softc *sc)
ret = ath5k_stop_locked(sc);
if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
/*
- * Set the chip in full sleep mode. Note that we are
- * careful to do this only when bringing the interface
- * completely to a stop. When the chip is in this state
- * it must be carefully woken up or references to
- * registers in the PCI clock domain may freeze the bus
- * (and system). This varies by chip and is mostly an
- * issue with newer parts that go to sleep more quickly.
- */
- if (sc->ah->ah_mac_srev >= 0x78) {
- /*
- * XXX
- * don't put newer MAC revisions > 7.8 to sleep because
- * of the above mentioned problems
- */
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
- "not putting device to sleep\n");
- } else {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
- "putting device to full sleep\n");
- ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
- }
+ * Don't set the card in full sleep mode!
+ *
+ * a) When the device is in this state it must be carefully
+ * woken up or references to registers in the PCI clock
+ * domain may freeze the bus (and system). This varies
+ * by chip and is mostly an issue with newer parts
+ * (madwifi sources mentioned srev >= 0x78) that go to
+ * sleep more quickly.
+ *
+ * b) On older chips full sleep results a weird behaviour
+ * during wakeup. I tested various cards with srev < 0x78
+ * and they don't wake up after module reload, a second
+ * module reload is needed to bring the card up again.
+ *
+ * Until we figure out what's going on don't enable
+ * full chip reset on any chip (this is what Legacy HAL
+ * and Sam's HAL do anyway). Instead Perform a full reset
+ * on the device (same as initial state after attach) and
+ * leave it idle (keep MAC/BB on warm reset) */
+ ret = ath5k_hw_on_hold(sc->ah);
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ "putting device to sleep\n");
}
ath5k_txbuf_free(sc, sc->bbuf);
@@ -2676,7 +2667,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
sc->curchan = chan;
sc->curband = &sc->sbands[chan->band];
}
- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL);
if (ret) {
ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
goto err;
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index c56b494d417a..5eded5a0d452 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -97,6 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
int ret;
u16 val;
+ u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
/*
* Read values from EEPROM and store them in the capability structure
@@ -111,20 +112,44 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
return 0;
-#ifdef notyet
/*
* Validate the checksum of the EEPROM date. There are some
* devices with invalid EEPROMs.
*/
- for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val);
+ if (val) {
+ eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
+ AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
+ AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val);
+ eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE;
+
+ /*
+ * Fail safe check to prevent stupid loops due
+ * to busted EEPROMs. XXX: This value is likely too
+ * big still, waiting on a better value.
+ */
+ if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
+ ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
+ "%d (0x%04x) max expected: %d (0x%04x)\n",
+ eep_max, eep_max,
+ 3 * AR5K_EEPROM_INFO_MAX,
+ 3 * AR5K_EEPROM_INFO_MAX);
+ return -EIO;
+ }
+ }
+
+ for (cksum = 0, offset = 0; offset < eep_max; offset++) {
AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
cksum ^= val;
}
if (cksum != AR5K_EEPROM_INFO_CKSUM) {
- ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
+ ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
+ "checksum: 0x%04x eep_max: 0x%04x (%s)\n",
+ cksum, eep_max,
+ eep_max == AR5K_EEPROM_INFO_MAX ?
+ "default size" : "custom size");
return -EIO;
}
-#endif
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
ee_ant_gain);
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 64be73a5edae..020bc4c75ef0 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -34,6 +34,14 @@
#define AR5K_EEPROM_RFKILL_POLARITY_S 1
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
+
+/* FLASH(EEPROM) Defines for AR531X chips */
+#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */
+#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */
+#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0
+#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4
+#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12
+
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index a876ca8d69ef..5c0e31b197a0 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -740,13 +740,22 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
AR5K_RF_XPD_GAIN, true);
} else {
- /* TODO: Set high and low gain bits */
- ath5k_hw_rfb_op(ah, rf_regs,
- ee->ee_x_gain[ee_mode],
+ u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
+ if (ee->ee_pd_gains[ee_mode] > 1) {
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[0],
AR5K_RF_PD_GAIN_LO, true);
- ath5k_hw_rfb_op(ah, rf_regs,
- ee->ee_x_gain[ee_mode],
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[1],
AR5K_RF_PD_GAIN_HI, true);
+ } else {
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[0],
+ AR5K_RF_PD_GAIN_LO, true);
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[0],
+ AR5K_RF_PD_GAIN_HI, true);
+ }
/* Lower synth voltage on Rev 2 */
ath5k_hw_rfb_op(ah, rf_regs, 2,
@@ -1897,8 +1906,9 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
s16 min_pwrL, min_pwrR;
s16 pwr_i;
- if (WARN_ON(stepL[0] == stepL[1] || stepR[0] == stepR[1]))
- return 0;
+ /* Some vendors write the same pcdac value twice !!! */
+ if (stepL[0] == stepL[1] || stepR[0] == stepR[1])
+ return max(pwrL[0], pwrR[0]);
if (pwrL[0] == pwrL[1])
min_pwrL = pwrL[0];
@@ -2921,8 +2931,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
return -EINVAL;
}
- if (txpower == 0)
- txpower = AR5K_TUNE_DEFAULT_TXPOWER;
/* Reset TX power values */
memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index bd0a97a38d34..4980621b0239 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -258,29 +258,35 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
if (!set_chip)
goto commit;
- /* Preserve sleep duration */
data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+
+ /* If card is down we 'll get 0xffff... so we
+ * need to clean this up before we write the register
+ */
if (data & 0xffc00000)
data = 0;
else
- data = data & 0xfffcffff;
+ /* Preserve sleep duration etc */
+ data = data & ~AR5K_SLEEP_CTL_SLE;
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
udelay(15);
- for (i = 50; i > 0; i--) {
+ for (i = 200; i > 0; i--) {
/* Check if the chip did wake up */
if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
AR5K_PCICFG_SPWR_DN) == 0)
break;
/* Wait a bit and retry */
- udelay(200);
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ udelay(50);
+ ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
}
/* Fail if the chip didn't wake up */
- if (i <= 0)
+ if (i == 0)
return -EIO;
break;
@@ -297,6 +303,64 @@ commit:
}
/*
+ * Put device on hold
+ *
+ * Put MAC and Baseband on warm reset and
+ * keep that state (don't clean sleep control
+ * register). After this MAC and Baseband are
+ * disabled and a full reset is needed to come
+ * back. This way we save as much power as possible
+ * without puting the card on full sleep.
+ */
+int ath5k_hw_on_hold(struct ath5k_hw *ah)
+{
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 bus_flags;
+ int ret;
+
+ /* Make sure device is awake */
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ return ret;
+ }
+
+ /*
+ * Put chipset on warm reset...
+ *
+ * Note: puting PCI core on warm reset on PCI-E cards
+ * results card to hang and always return 0xffff... so
+ * we ingore that flag for PCI-E cards. On PCI cards
+ * this flag gets cleared after 64 PCI clocks.
+ */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
* Bring up MAC + PHY Chips and program PLL
* TODO: Half/Quarter rate support
*/
@@ -319,6 +383,50 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return ret;
}
+ /*
+ * Put chipset on warm reset...
+ *
+ * Note: puting PCI core on warm reset on PCI-E cards
+ * results card to hang and always return 0xffff... so
+ * we ingore that flag for PCI-E cards. On PCI cards
+ * this flag gets cleared after 64 PCI clocks.
+ */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!...*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ return ret;
+ }
+
+ /* ...clear reset control register and pull device out of
+ * warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* On initialization skip PLL programming since we don't have
+ * a channel / mode set yet */
+ if (initial)
+ return 0;
+
if (ah->ah_version != AR5K_AR5210) {
/*
* Get channel mode flags
@@ -384,39 +492,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
AR5K_PHY_TURBO);
}
- /* reseting PCI on PCI-E cards results card to hang
- * and always return 0xffff... so we ingore that flag
- * for PCI-E cards */
- bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
-
- /* Reset chipset */
- if (ah->ah_version == AR5K_AR5210) {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
- AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
- mdelay(2);
- } else {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_BASEBAND | bus_flags);
- }
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
- return -EIO;
- }
-
- /* ...wakeup again!*/
- ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
- return ret;
- }
-
- /* ...final warm reset */
- if (ath5k_hw_nic_reset(ah, 0)) {
- ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
- return -EIO;
- }
-
if (ah->ah_version != AR5K_AR5210) {
/* ...update PLL if needed */
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 40448067e4cc..7797166a0cdb 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -117,6 +117,7 @@
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
#define B43_MMIO_RNG 0x65A
+#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */
#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
#define B43_MMIO_POWERUP_DELAY 0x6A8
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 7964cc32b258..32e9513bbc0b 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1158,8 +1158,9 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
}
static int dma_tx_fragment(struct b43_dmaring *ring,
- struct sk_buff *skb)
+ struct sk_buff **in_skb)
{
+ struct sk_buff *skb = *in_skb;
const struct b43_dma_ops *ops = ring->ops;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
@@ -1225,8 +1226,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
}
memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+ memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
+ bounce_skb->dev = skb->dev;
+ skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
+ info = IEEE80211_SKB_CB(bounce_skb);
+
dev_kfree_skb_any(skb);
skb = bounce_skb;
+ *in_skb = bounce_skb;
meta->skb = skb;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
@@ -1334,13 +1341,22 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
spin_lock_irqsave(&ring->lock, flags);
B43_WARN_ON(!ring->tx);
- /* Check if the queue was stopped in mac80211,
- * but we got called nevertheless.
- * That would be a mac80211 bug. */
- B43_WARN_ON(ring->stopped);
- if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) {
- b43warn(dev->wl, "DMA queue overflow\n");
+ if (unlikely(ring->stopped)) {
+ /* We get here only because of a bug in mac80211.
+ * Because of a race, one packet may be queued after
+ * the queue is stopped, thus we got called when we shouldn't.
+ * For now, just refuse the transmit. */
+ if (b43_debug(dev, B43_DBG_DMAVERBOSE))
+ b43err(dev->wl, "Packet after queue stopped\n");
+ err = -ENOSPC;
+ goto out_unlock;
+ }
+
+ if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
+ /* If we get here, we have a real error with the queue
+ * full, but queues not stopped. */
+ b43err(dev->wl, "DMA queue overflow\n");
err = -ENOSPC;
goto out_unlock;
}
@@ -1350,7 +1366,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
* static, so we don't need to store it per frame. */
ring->queue_prio = skb_get_queue_mapping(skb);
- err = dma_tx_fragment(ring, skb);
+ /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
+ * into the skb data or cb now. */
+ hdr = NULL;
+ info = NULL;
+ err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index e71c8d9cd706..82fb9d48fa55 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -664,10 +664,17 @@ static void b43_upload_card_macaddress(struct b43_wldev *dev)
static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
{
/* slot_time is in usec. */
- if (dev->phy.type != B43_PHYTYPE_G)
+ /* This test used to exit for all but a G PHY. */
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
return;
- b43_write16(dev, 0x684, 510 + slot_time);
- b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time);
+ b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time);
+ /* Shared memory location 0x0010 is the slot time and should be
+ * set to slot_time; however, this register is initially 0 and changing
+ * the value adversely affects the transmit rate for BCM4311
+ * devices. Until this behavior is unterstood, delete this step
+ *
+ * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time);
+ */
}
static void b43_short_slot_timing_enable(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 31e55999893f..dcde92d682ce 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -33,7 +33,8 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
& B43_MMIO_RADIO_HWENABLED_HI_MASK))
return 1;
} else {
- if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
+ if (b43_status(dev) >= B43_STAT_STARTED &&
+ b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
& B43_MMIO_RADIO_HWENABLED_LO_MASK)
return 1;
}
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index 8783022db11e..d579df72b783 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -34,6 +34,13 @@ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
& B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
return 1;
} else {
+ /* To prevent CPU fault on PPC, do not read a register
+ * unless the interface is started; however, on resume
+ * for hibernation, this routine is entered early. When
+ * that happens, unconditionally return TRUE.
+ */
+ if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+ return 1;
if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
& B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
return 1;
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 6fe122f18c0d..eb57d1ea361f 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -875,15 +875,16 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
switch(type) {
case HOSTAP_INTERFACE_AP:
+ dev->tx_queue_len = 0; /* use main radio device queue */
dev->netdev_ops = &hostap_mgmt_netdev_ops;
dev->type = ARPHRD_IEEE80211;
dev->header_ops = &hostap_80211_ops;
break;
case HOSTAP_INTERFACE_MASTER:
- dev->tx_queue_len = 0; /* use main radio device queue */
dev->netdev_ops = &hostap_master_ops;
break;
default:
+ dev->tx_queue_len = 0; /* use main radio device queue */
dev->netdev_ops = &hostap_netdev_ops;
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 742432388ca3..d04350b14790 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -6487,6 +6487,16 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
}
#endif
+static void ipw2100_shutdown(struct pci_dev *pci_dev)
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+
+ /* Take down the device; powers it off, etc. */
+ ipw2100_down(priv);
+
+ pci_disable_device(pci_dev);
+}
+
#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
@@ -6550,6 +6560,7 @@ static struct pci_driver ipw2100_pci_driver = {
.suspend = ipw2100_suspend,
.resume = ipw2100_resume,
#endif
+ .shutdown = ipw2100_shutdown,
};
/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 7da52f1cc1d6..44baa60c9fd3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -46,7 +46,7 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 2
+#define IWL1000_UCODE_API_MAX 3
/* Lowest firmware API version supported */
#define IWL1000_UCODE_API_MIN 1
@@ -62,12 +62,15 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
.ops = &iwl5000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_A,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = true,
+ .max_ll_items = OTP_MAX_LL_ITEMS_1000,
+ .shadow_ram_support = false,
+ .use_rts_for_ht = true, /* use rts/cts protection */
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 46288e724889..b73ab6c278f3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2784,11 +2784,50 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
return 0;
}
+#define IWL3945_UCODE_GET(item) \
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+ return UCODE_HEADER_SIZE(1);
+}
+static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return 0;
+}
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
static struct iwl_hcmd_ops iwl3945_hcmd = {
.rxon_assoc = iwl3945_send_rxon_assoc,
.commit_rxon = iwl3945_commit_rxon,
};
+static struct iwl_ucode_ops iwl3945_ucode = {
+ .get_header_size = iwl3945_ucode_get_header_size,
+ .get_build = iwl3945_ucode_get_build,
+ .get_inst_size = iwl3945_ucode_get_inst_size,
+ .get_data_size = iwl3945_ucode_get_data_size,
+ .get_init_size = iwl3945_ucode_get_init_size,
+ .get_init_data_size = iwl3945_ucode_get_init_data_size,
+ .get_boot_size = iwl3945_ucode_get_boot_size,
+ .get_data = iwl3945_ucode_get_data,
+};
+
static struct iwl_lib_ops iwl3945_lib = {
.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2829,6 +2868,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
};
static struct iwl_ops iwl3945_ops = {
+ .ucode = &iwl3945_ucode,
.lib = &iwl3945_lib,
.hcmd = &iwl3945_hcmd,
.utils = &iwl3945_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 8f3d4bc6a03f..157ee1506b3c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2221,12 +2221,50 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->txpower_work);
}
+#define IWL4965_UCODE_GET(item) \
+static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl4965_ucode_get_header_size(u32 api_ver)
+{
+ return UCODE_HEADER_SIZE(1);
+}
+static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return 0;
+}
+static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL4965_UCODE_GET(inst_size);
+IWL4965_UCODE_GET(data_size);
+IWL4965_UCODE_GET(init_size);
+IWL4965_UCODE_GET(init_data_size);
+IWL4965_UCODE_GET(boot_size);
+
static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
};
+static struct iwl_ucode_ops iwl4965_ucode = {
+ .get_header_size = iwl4965_ucode_get_header_size,
+ .get_build = iwl4965_ucode_get_build,
+ .get_inst_size = iwl4965_ucode_get_inst_size,
+ .get_data_size = iwl4965_ucode_get_data_size,
+ .get_init_size = iwl4965_ucode_get_init_size,
+ .get_init_data_size = iwl4965_ucode_get_init_data_size,
+ .get_boot_size = iwl4965_ucode_get_boot_size,
+ .get_data = iwl4965_ucode_get_data,
+};
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.get_hcmd_size = iwl4965_get_hcmd_size,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2287,6 +2325,7 @@ static struct iwl_lib_ops iwl4965_lib = {
};
static struct iwl_ops iwl4965_ops = {
+ .ucode = &iwl4965_ucode,
.lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd,
.utils = &iwl4965_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index b3c648ce8c7b..a9ea3b5d49d5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -239,6 +239,13 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_1000) {
+ /* Setting digital SVR for 1000 card to 1.32V */
+ iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG,
+ APMG_SVR_DIGITAL_VOLTAGE_1_32,
+ ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
+ }
+
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1426,6 +1433,44 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWL49_RSSI_OFFSET;
}
+#define IWL5000_UCODE_GET(item) \
+static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ if (api_ver <= 2) \
+ return le32_to_cpu(ucode->u.v1.item); \
+ return le32_to_cpu(ucode->u.v2.item); \
+}
+
+static u32 iwl5000_ucode_get_header_size(u32 api_ver)
+{
+ if (api_ver <= 2)
+ return UCODE_HEADER_SIZE(1);
+ return UCODE_HEADER_SIZE(2);
+}
+
+static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ if (api_ver <= 2)
+ return 0;
+ return le32_to_cpu(ucode->u.v2.build);
+}
+
+static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ if (api_ver <= 2)
+ return (u8 *) ucode->u.v1.data;
+ return (u8 *) ucode->u.v2.data;
+}
+
+IWL5000_UCODE_GET(inst_size);
+IWL5000_UCODE_GET(data_size);
+IWL5000_UCODE_GET(init_size);
+IWL5000_UCODE_GET(init_data_size);
+IWL5000_UCODE_GET(boot_size);
+
struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
@@ -1441,6 +1486,17 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
.calc_rssi = iwl5000_calc_rssi,
};
+struct iwl_ucode_ops iwl5000_ucode = {
+ .get_header_size = iwl5000_ucode_get_header_size,
+ .get_build = iwl5000_ucode_get_build,
+ .get_inst_size = iwl5000_ucode_get_inst_size,
+ .get_data_size = iwl5000_ucode_get_data_size,
+ .get_init_size = iwl5000_ucode_get_init_size,
+ .get_init_data_size = iwl5000_ucode_get_init_data_size,
+ .get_boot_size = iwl5000_ucode_get_boot_size,
+ .get_data = iwl5000_ucode_get_data,
+};
+
struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
@@ -1542,12 +1598,14 @@ static struct iwl_lib_ops iwl5150_lib = {
};
struct iwl_ops iwl5000_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
};
static struct iwl_ops iwl5150_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5150_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index bd438d8acf55..ee7b48ed3e8b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -46,8 +46,8 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL6000_UCODE_API_MAX 2
-#define IWL6050_UCODE_API_MAX 2
+#define IWL6000_UCODE_API_MAX 3
+#define IWL6050_UCODE_API_MAX 3
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 1
@@ -69,6 +69,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
};
static struct iwl_ops iwl6000_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils,
@@ -81,13 +82,15 @@ struct iwl_cfg iwl6000_2ag_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_BC,
.valid_rx_ant = ANT_BC,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
};
struct iwl_cfg iwl6000_2agn_cfg = {
@@ -97,13 +100,16 @@ struct iwl_cfg iwl6000_2agn_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .use_rts_for_ht = true, /* use rts/cts protection */
};
struct iwl_cfg iwl6050_2agn_cfg = {
@@ -113,13 +119,16 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .use_rts_for_ht = true, /* use rts/cts protection */
};
struct iwl_cfg iwl6000_3agn_cfg = {
@@ -129,13 +138,16 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .use_rts_for_ht = true, /* use rts/cts protection */
};
struct iwl_cfg iwl6050_3agn_cfg = {
@@ -145,13 +157,16 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .use_rts_for_ht = true, /* use rts/cts protection */
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index ff20e5048a55..f5c108be541c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -415,6 +415,15 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
else if (tid == IWL_AGG_ALL_TID)
for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
+ if (priv->cfg->use_rts_for_ht) {
+ /*
+ * switch to RTS/CTS if it is the prefer protection method
+ * for HT traffic
+ */
+ IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
+ priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
+ iwlcore_commit_rxon(priv);
+ }
}
static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 355f50ea7fef..fc33b29c58ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -115,9 +115,6 @@ int iwl_commit_rxon(struct iwl_priv *priv)
/* always get timestamp with Rx frame */
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
- /* allow CTS-to-self if possible. this is relevant only for
- * 5000, but will not damage 4965 */
- priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
ret = iwl_check_rxon_cmd(priv);
if (ret) {
@@ -217,6 +214,13 @@ int iwl_commit_rxon(struct iwl_priv *priv)
"Could not send WEP static key.\n");
}
+ /*
+ * allow CTS-to-self if possible for new association.
+ * this is relevant only for 5000 series and up,
+ * but will not damage 4965
+ */
+ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
+
/* Apply the new configuration
* RXON assoc doesn't clear the station table in uCode,
*/
@@ -1348,7 +1352,7 @@ static void iwl_nic_start(struct iwl_priv *priv)
*/
static int iwl_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
const char *name_pre = priv->cfg->fw_name_pre;
@@ -1357,7 +1361,8 @@ static int iwl_read_ucode(struct iwl_priv *priv)
char buf[25];
u8 *src;
size_t len;
- u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
+ u32 api_ver, build;
+ u32 inst_size, data_size, init_size, init_data_size, boot_size;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
@@ -1387,23 +1392,26 @@ static int iwl_read_ucode(struct iwl_priv *priv)
if (ret < 0)
goto error;
- /* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ /* Make sure that we got at least the v1 header! */
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ build = priv->cfg->ops->ucode->get_build(ucode, api_ver);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -1429,6 +1437,9 @@ static int iwl_read_ucode(struct iwl_priv *priv)
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
+ if (build)
+ IWL_DEBUG_INFO(priv, "Build %u\n", build);
+
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
priv->ucode_ver);
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
@@ -1443,12 +1454,14 @@ static int iwl_read_ucode(struct iwl_priv *priv)
boot_size);
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size !=
+ priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %d too small\n",
- (int)ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %d does not match expected size\n",
+ (int)ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
@@ -1528,42 +1541,42 @@ static int iwl_read_ucode(struct iwl_priv *priv)
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
@@ -2206,7 +2219,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0;
- if (iwl_is_ready_rf(priv)) {
+ if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
/* stop mac, cancel any scan request and clear
* RXON_FILTER_ASSOC_MSK BIT
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index dabf663e36e5..4e616eccebfb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -116,6 +116,17 @@ struct iwl_temp_ops {
void (*set_ct_kill)(struct iwl_priv *priv);
};
+struct iwl_ucode_ops {
+ u32 (*get_header_size)(u32);
+ u32 (*get_build)(const struct iwl_ucode_header *, u32);
+ u32 (*get_inst_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_data_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_init_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_boot_size)(const struct iwl_ucode_header *, u32);
+ u8 * (*get_data)(const struct iwl_ucode_header *, u32);
+};
+
struct iwl_lib_ops {
/* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
@@ -171,6 +182,7 @@ struct iwl_lib_ops {
};
struct iwl_ops {
+ const struct iwl_ucode_ops *ucode;
const struct iwl_lib_ops *lib;
const struct iwl_hcmd_ops *hcmd;
const struct iwl_hcmd_utils_ops *utils;
@@ -195,6 +207,9 @@ struct iwl_mod_params {
* filename is constructed as fw_name_pre<api>.ucode.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
+ * @use_rts_for_ht: use rts/cts protection for HT traffic
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@@ -231,6 +246,9 @@ struct iwl_cfg {
u8 valid_rx_ant;
bool need_pll_cfg;
bool use_isr_legacy;
+ const u16 max_ll_items;
+ const bool shadow_ram_support;
+ bool use_rts_for_ht;
};
/***************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 650e20af20fa..e8c86079334a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -66,6 +66,7 @@ extern struct iwl_cfg iwl1000_bgn_cfg;
/* shared structures from iwl-5000.c */
extern struct iwl_mod_params iwl50_mod_params;
extern struct iwl_ops iwl5000_ops;
+extern struct iwl_ucode_ops iwl5000_ucode;
extern struct iwl_lib_ops iwl5000_lib;
extern struct iwl_hcmd_ops iwl5000_hcmd;
extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils;
@@ -525,15 +526,29 @@ struct fw_desc {
};
/* uCode file layout */
-struct iwl_ucode {
- __le32 ver; /* major/minor/API/serial */
- __le32 inst_size; /* bytes of runtime instructions */
- __le32 data_size; /* bytes of runtime data */
- __le32 init_size; /* bytes of initialization instructions */
- __le32 init_data_size; /* bytes of initialization data */
- __le32 boot_size; /* bytes of bootstrap instructions */
- u8 data[0]; /* data in same order as "size" elements */
+struct iwl_ucode_header {
+ __le32 ver; /* major/minor/API/serial */
+ union {
+ struct {
+ __le32 inst_size; /* bytes of runtime code */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of init code */
+ __le32 init_data_size; /* bytes of init data */
+ __le32 boot_size; /* bytes of bootstrap code */
+ u8 data[0]; /* in same order as sizes */
+ } v1;
+ struct {
+ __le32 build; /* build number */
+ __le32 inst_size; /* bytes of runtime code */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of init code */
+ __le32 init_data_size; /* bytes of init data */
+ __le32 boot_size; /* bytes of bootstrap code */
+ u8 data[0]; /* in same order as sizes */
+ } v2;
+ } u;
};
+#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28)
struct iwl4965_ibss_seq {
u8 mac[ETH_ALEN];
@@ -820,6 +835,18 @@ enum iwl_nvm_type {
NVM_DEVICE_TYPE_OTP,
};
+/*
+ * Two types of OTP memory access modes
+ * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
+ * based on physical memory addressing
+ * IWL_OTP_ACCESS_RELATIVE - relative address mode,
+ * based on logical memory addressing
+ */
+enum iwl_access_mode {
+ IWL_OTP_ACCESS_ABSOLUTE,
+ IWL_OTP_ACCESS_RELATIVE,
+};
+
/* interrupt statistics */
struct isr_statistics {
u32 hw;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 7d7554a2f341..eabe48a7ebfe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
+static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
+{
+ u32 otpgp;
+
+ otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+ if (mode == IWL_OTP_ACCESS_ABSOLUTE)
+ iwl_clear_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+ else
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+}
+
static int iwlcore_get_nvm_type(struct iwl_priv *priv)
{
u32 otpgp;
@@ -249,6 +262,123 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
return ret;
}
+static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
+{
+ int ret = 0;
+ u32 r;
+ u32 otpgp;
+
+ _iwl_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+ ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret < 0) {
+ IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+ return ret;
+ }
+ r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+ /* check for ECC errors: */
+ otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+ if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
+ /* stop in this case */
+ /* set the uncorrectable OTP ECC bit for acknowledgement */
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
+ IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
+ return -EINVAL;
+ }
+ if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
+ /* continue in this case */
+ /* set the correctable OTP ECC bit for acknowledgement */
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
+ IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
+ }
+ *eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
+ return 0;
+}
+
+/*
+ * iwl_is_otp_empty: check for empty OTP
+ */
+static bool iwl_is_otp_empty(struct iwl_priv *priv)
+{
+ u16 next_link_addr = 0, link_value;
+ bool is_empty = false;
+
+ /* locate the beginning of OTP link list */
+ if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) {
+ if (!link_value) {
+ IWL_ERR(priv, "OTP is empty\n");
+ is_empty = true;
+ }
+ } else {
+ IWL_ERR(priv, "Unable to read first block of OTP list.\n");
+ is_empty = true;
+ }
+
+ return is_empty;
+}
+
+
+/*
+ * iwl_find_otp_image: find EEPROM image in OTP
+ * finding the OTP block that contains the EEPROM image.
+ * the last valid block on the link list (the block _before_ the last block)
+ * is the block we should read and used to configure the device.
+ * If all the available OTP blocks are full, the last block will be the block
+ * we should read and used to configure the device.
+ * only perform this operation if shadow RAM is disabled
+ */
+static int iwl_find_otp_image(struct iwl_priv *priv,
+ u16 *validblockaddr)
+{
+ u16 next_link_addr = 0, link_value = 0, valid_addr;
+ int usedblocks = 0;
+
+ /* set addressing mode to absolute to traverse the link list */
+ iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE);
+
+ /* checking for empty OTP or error */
+ if (iwl_is_otp_empty(priv))
+ return -EINVAL;
+
+ /*
+ * start traverse link list
+ * until reach the max number of OTP blocks
+ * different devices have different number of OTP blocks
+ */
+ do {
+ /* save current valid block address
+ * check for more block on the link list
+ */
+ valid_addr = next_link_addr;
+ next_link_addr = link_value * sizeof(u16);
+ IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
+ usedblocks, next_link_addr);
+ if (iwl_read_otp_word(priv, next_link_addr, &link_value))
+ return -EINVAL;
+ if (!link_value) {
+ /*
+ * reach the end of link list, return success and
+ * set address point to the starting address
+ * of the image
+ */
+ *validblockaddr = valid_addr;
+ /* skip first 2 bytes (link list pointer) */
+ *validblockaddr += 2;
+ return 0;
+ }
+ /* more in the link list, continue */
+ usedblocks++;
+ } while (usedblocks <= priv->cfg->max_ll_items);
+
+ /* OTP has no valid blocks */
+ IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
+ return -EINVAL;
+}
+
/**
* iwl_eeprom_init - read EEPROM contents
*
@@ -263,14 +393,13 @@ int iwl_eeprom_init(struct iwl_priv *priv)
int sz;
int ret;
u16 addr;
- u32 otpgp;
+ u16 validblockaddr = 0;
+ u16 cache_addr = 0;
priv->nvm_device_type = iwlcore_get_nvm_type(priv);
/* allocate eeprom */
- if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
- priv->cfg->eeprom_size =
- OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
+ IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
sz = priv->cfg->eeprom_size;
priv->eeprom = kzalloc(sz, GFP_KERNEL);
if (!priv->eeprom) {
@@ -298,46 +427,31 @@ int iwl_eeprom_init(struct iwl_priv *priv)
if (ret) {
IWL_ERR(priv, "Failed to initialize OTP access.\n");
ret = -ENOENT;
- goto err;
+ goto done;
}
_iwl_write32(priv, CSR_EEPROM_GP,
iwl_read32(priv, CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK);
- /* clear */
- _iwl_write32(priv, CSR_OTP_GP_REG,
- iwl_read32(priv, CSR_OTP_GP_REG) |
+
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
-
- for (addr = 0; addr < sz; addr += sizeof(u16)) {
- u32 r;
-
- _iwl_write32(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
-
- ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_READ_VALID_MSK,
- IWL_EEPROM_ACCESS_TIMEOUT);
- if (ret < 0) {
- IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+ /* traversing the linked list if no shadow ram supported */
+ if (!priv->cfg->shadow_ram_support) {
+ if (iwl_find_otp_image(priv, &validblockaddr)) {
+ ret = -ENOENT;
goto done;
}
- r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
- /* check for ECC errors: */
- otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
- if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
- /* stop in this case */
- IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
+ }
+ for (addr = validblockaddr; addr < validblockaddr + sz;
+ addr += sizeof(u16)) {
+ u16 eeprom_data;
+
+ ret = iwl_read_otp_word(priv, addr, &eeprom_data);
+ if (ret)
goto done;
- }
- if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
- /* continue in this case */
- _iwl_write32(priv, CSR_OTP_GP_REG,
- iwl_read32(priv, CSR_OTP_GP_REG) |
- CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
- IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
- }
- e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+ e[cache_addr / 2] = eeprom_data;
+ cache_addr += sizeof(u16);
}
} else {
/* eeprom is an array of 16bit values */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 195b4ef12c27..78998854dd99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -180,8 +180,14 @@ struct iwl_eeprom_channel {
#define EEPROM_5050_EEPROM_VERSION (0x21E)
/* OTP */
-#define OTP_LOWER_BLOCKS_TOTAL (3)
-#define OTP_BLOCK_SIZE (0x400)
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
+/* high blocks contain PAPD data */
+#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
+#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
+#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
+#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
+#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
/* 2.4 GHz */
extern const u8 iwl_eeprom_band_1[14];
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 3b9cac3fd216..d393e8f02102 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -80,6 +80,8 @@
#define APMG_RFKILL_REG (APMG_BASE + 0x0014)
#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c)
#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020)
+#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
+#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
@@ -91,7 +93,8 @@
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
-
+#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
+#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 2b8d40b37a1c..a13f678fe44c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -239,33 +239,51 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
+ struct sk_buff *skb;
unsigned long flags;
while (1) {
spin_lock_irqsave(&rxq->lock, flags);
-
if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags);
return;
}
- element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
- list_del(element);
-
spin_unlock_irqrestore(&rxq->lock, flags);
+ if (rxq->free_count > RX_LOW_WATERMARK)
+ priority |= __GFP_NOWARN;
/* Alloc a new receive buffer */
- rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
+ skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
priority);
- if (!rxb->skb) {
- IWL_CRIT(priv, "Can not allocate SKB buffers\n");
+ if (!skb) {
+ if (net_ratelimit())
+ IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+ if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+ net_ratelimit())
+ IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+ priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
+ rxq->free_count);
/* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs
* more buffers it will schedule replenish */
break;
}
+ spin_lock_irqsave(&rxq->lock, flags);
+
+ if (list_empty(&rxq->rx_used)) {
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+ element = rxq->rx_used.next;
+ rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ list_del(element);
+
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ rxb->skb = skb;
/* Get physical address of RB/SKB */
rxb->real_dma_addr = pci_map_single(
priv->pci_dev,
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index e26875dbe859..474fd4982471 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -799,7 +799,8 @@ void iwl_bg_abort_scan(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
- if (!iwl_is_ready(priv))
+ if (!test_bit(STATUS_READY, &priv->status) ||
+ !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return;
mutex_lock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 2e89040e63be..c17b8f93ad15 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1233,8 +1233,16 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
return -ENXIO;
}
+ if (priv->stations[sta_id].tid[tid].agg.state ==
+ IWL_EMPTYING_HW_QUEUE_ADDBA) {
+ IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
+ ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid);
+ priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
+ return 0;
+ }
+
if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
- IWL_WARN(priv, "Stopping AGG while state not IWL_AGG_ON\n");
+ IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
tid_data = &priv->stations[sta_id].tid[tid];
ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 523843369ca2..4fac58260001 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1196,6 +1196,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
+ struct sk_buff *skb;
unsigned long flags;
while (1) {
@@ -1205,25 +1206,39 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
spin_unlock_irqrestore(&rxq->lock, flags);
return;
}
-
- element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
- list_del(element);
spin_unlock_irqrestore(&rxq->lock, flags);
+ if (rxq->free_count > RX_LOW_WATERMARK)
+ priority |= __GFP_NOWARN;
/* Alloc a new receive buffer */
- rxb->skb =
- alloc_skb(priv->hw_params.rx_buf_size,
- priority);
- if (!rxb->skb) {
+ skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
+ if (!skb) {
if (net_ratelimit())
- IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
+ IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+ if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+ net_ratelimit())
+ IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+ priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
+ rxq->free_count);
/* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs
* more buffers it will schedule replenish */
break;
}
+ spin_lock_irqsave(&rxq->lock, flags);
+ if (list_empty(&rxq->rx_used)) {
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+ element = rxq->rx_used.next;
+ rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ list_del(element);
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ rxb->skb = skb;
+
/* If radiotap head is required, reserve some headroom here.
* The physical head count is a variable rx_stats->phy_count.
* We reserve 4 bytes here. Plus these extra bytes, the
@@ -2111,7 +2126,7 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
*/
static int iwl3945_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ const struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
@@ -2152,22 +2167,24 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
goto error;
/* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -2208,12 +2225,13 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n",
- ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %zd does not match expected size\n",
+ ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
@@ -2296,44 +2314,44 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode instr len %zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl3945_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode data len %zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init instr len %zd\n", len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init data len %zd\n", len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) boot instr len %zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 1844c5adf6e9..3a9a8c13b8a9 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -507,7 +507,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
- (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
+ skb->data + IPFIELD_ALIGN_OFFSET,
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
cardp);
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 8bc1907458b1..f9c366c6ce4c 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1951,10 +1951,8 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
if (priv->connect_status == LBS_CONNECTED) {
memcpy(extra, priv->curbssparams.ssid,
priv->curbssparams.ssid_len);
- extra[priv->curbssparams.ssid_len] = '\0';
} else {
memset(extra, 0, 32);
- extra[priv->curbssparams.ssid_len] = '\0';
}
/*
* If none, we may want to get the one that was set
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 0e877a104a89..b17ec7f24b82 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -66,6 +66,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
{USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
{USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
+ {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */
{USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
{USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
{USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
@@ -426,12 +427,16 @@ static const char p54u_romboot_3887[] = "~~~~";
static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)
{
struct p54u_priv *priv = dev->priv;
- u8 buf[4];
+ u8 *buf;
int ret;
- memcpy(&buf, p54u_romboot_3887, sizeof(buf));
+ buf = kmalloc(4, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ memcpy(buf, p54u_romboot_3887, 4);
ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
- buf, sizeof(buf));
+ buf, 4);
+ kfree(buf);
if (ret)
dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
"boot ROM (%d)!\n", ret);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 698b11b1cadb..8c67a488f83b 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -2878,7 +2878,7 @@ static int write_essid(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
static char proc_essid[33];
- int len = count;
+ unsigned int len = count;
if (len > 32)
len = 32;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
index cf9f899fe0e6..75648dd17595 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -210,10 +210,10 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
/* turn the LED off before exiting */
queue_delayed_work(dev->workqueue, &priv->led_off, 0);
- cancel_delayed_work_sync(&priv->led_off);
- cancel_delayed_work_sync(&priv->led_on);
rtl8187_unregister_led(&priv->led_rx);
rtl8187_unregister_led(&priv->led_tx);
+ cancel_delayed_work_sync(&priv->led_off);
+ cancel_delayed_work_sync(&priv->led_on);
}
#endif /* def CONFIG_RTL8187_LED */
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index a45b0c0d574e..a6b4a5a53d40 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -1266,7 +1266,7 @@ ccio_ioc_init(struct ioc *ioc)
** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
*/
- iova_space_size = (u32) (num_physpages / count_parisc_driver(&ccio_driver));
+ iova_space_size = (u32) (totalram_pages / count_parisc_driver(&ccio_driver));
/* limit IOVA space size to 1MB-1GB */
@@ -1305,7 +1305,7 @@ ccio_ioc_init(struct ioc *ioc)
DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
__func__, ioc->ioc_regs,
- (unsigned long) num_physpages >> (20 - PAGE_SHIFT),
+ (unsigned long) totalram_pages >> (20 - PAGE_SHIFT),
iova_space_size>>20,
iov_order + PAGE_SHIFT);
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 123d8fe3427d..57a6d19eba4c 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1390,7 +1390,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
** for DMA hints - ergo only 30 bits max.
*/
- iova_space_size = (u32) (num_physpages/global_ioc_cnt);
+ iova_space_size = (u32) (totalram_pages/global_ioc_cnt);
/* limit IOVA space size to 1MB-1GB */
if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
@@ -1415,7 +1415,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n",
__func__,
ioc->ioc_hpa,
- (unsigned long) num_physpages >> (20 - PAGE_SHIFT),
+ (unsigned long) totalram_pages >> (20 - PAGE_SHIFT),
iova_space_size>>20,
iov_order + PAGE_SHIFT);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 7b287cb38b7a..380b60e677e0 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -632,20 +632,31 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+ if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
+ /* Promote an attitude of violence to a BIOS engineer today */
+ WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
+ "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+ drhd->reg_base_addr,
+ dmi_get_system_info(DMI_BIOS_VENDOR),
+ dmi_get_system_info(DMI_BIOS_VERSION),
+ dmi_get_system_info(DMI_PRODUCT_VERSION));
+ goto err_unmap;
+ }
+
#ifdef CONFIG_DMAR
agaw = iommu_calculate_agaw(iommu);
if (agaw < 0) {
printk(KERN_ERR
"Cannot get a valid agaw for iommu (seq_id = %d)\n",
iommu->seq_id);
- goto error;
+ goto err_unmap;
}
msagaw = iommu_calculate_max_sagaw(iommu);
if (msagaw < 0) {
printk(KERN_ERR
"Cannot get a valid max agaw for iommu (seq_id = %d)\n",
iommu->seq_id);
- goto error;
+ goto err_unmap;
}
#endif
iommu->agaw = agaw;
@@ -665,7 +676,7 @@ 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",
+ pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
(unsigned long long)drhd->reg_base_addr,
DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
(unsigned long long)iommu->cap,
@@ -675,7 +686,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
drhd->iommu = iommu;
return 0;
-error:
+
+ err_unmap:
+ iounmap(iommu->reg);
+ error:
kfree(iommu);
return -1;
}
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 4770f13b3ca1..e2504be1fa8d 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -52,7 +52,7 @@ static struct pci_error_handlers aer_error_handlers = {
static struct pcie_port_service_driver aerdriver = {
.name = "aer",
- .port_type = PCIE_ANY_PORT,
+ .port_type = PCIE_RC_PORT,
.service = PCIE_PORT_SERVICE_AER,
.probe = aer_probe,
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 06b965623962..10731373d00e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1201,6 +1201,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
switch(dev->subsystem_device) {
case 0x00b8: /* Compaq Evo D510 CMT */
case 0x00b9: /* Compaq Evo D510 SFF */
+ case 0x00ba: /* Compaq Evo D510 USDT */
/* Motherboard doesn't have Host bridge
* subvendor/subdevice IDs and on-board VGA
* controller is disabled if an AGP card is
@@ -2382,8 +2383,10 @@ static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
{
@@ -2492,6 +2495,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
#endif /* CONFIG_PCI_IOV */
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 9e1140f085fd..e1dccedc5960 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -363,7 +363,7 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
- pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ pcmcia_socket_dev_suspend(&pdev->dev);
if (device_may_wakeup(&pdev->dev)) {
enable_irq_wake(board->det_pin);
if (board->irq_pin)
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 90013341cd5f..02088704ac2c 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -515,7 +515,7 @@ static int au1x00_drv_pcmcia_probe(struct platform_device *dev)
static int au1x00_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int au1x00_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
index b59d4115d20f..300b368605c9 100644
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -302,7 +302,7 @@ static int __devexit bfin_cf_remove(struct platform_device *pdev)
static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int bfin_cf_resume(struct platform_device *pdev)
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 0660ad182589..698d75cda084 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -98,10 +98,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
* These functions check for the appropriate struct pcmcia_soket arrays,
* and pass them to the low-level functions pcmcia_{suspend,resume}_socket
*/
+static int socket_early_resume(struct pcmcia_socket *skt);
+static int socket_late_resume(struct pcmcia_socket *skt);
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
+static void pcmcia_socket_dev_run(struct device *dev,
+ int (*cb)(struct pcmcia_socket *))
{
struct pcmcia_socket *socket;
@@ -110,29 +113,34 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
if (socket->dev.parent != dev)
continue;
mutex_lock(&socket->skt_mutex);
- socket_suspend(socket);
+ cb(socket);
mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
+}
+int pcmcia_socket_dev_suspend(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_suspend);
return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-int pcmcia_socket_dev_resume(struct device *dev)
+void pcmcia_socket_dev_early_resume(struct device *dev)
{
- struct pcmcia_socket *socket;
+ pcmcia_socket_dev_run(dev, socket_early_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
- if (socket->dev.parent != dev)
- continue;
- mutex_lock(&socket->skt_mutex);
- socket_resume(socket);
- mutex_unlock(&socket->skt_mutex);
- }
- up_read(&pcmcia_socket_list_rwsem);
+void pcmcia_socket_dev_late_resume(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_late_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
+int pcmcia_socket_dev_resume(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_resume);
return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_resume);
@@ -546,29 +554,24 @@ static int socket_suspend(struct pcmcia_socket *skt)
return 0;
}
-/*
- * Resume a socket. If a card is present, verify its CIS against
- * our cached copy. If they are different, the card has been
- * replaced, and we need to tell the drivers.
- */
-static int socket_resume(struct pcmcia_socket *skt)
+static int socket_early_resume(struct pcmcia_socket *skt)
{
- int ret;
-
- if (!(skt->state & SOCKET_SUSPEND))
- return -EBUSY;
-
skt->socket = dead_socket;
skt->ops->init(skt);
skt->ops->set_socket(skt, &skt->socket);
+ if (skt->state & SOCKET_PRESENT)
+ skt->resume_status = socket_setup(skt, resume_delay);
+ return 0;
+}
+static int socket_late_resume(struct pcmcia_socket *skt)
+{
if (!(skt->state & SOCKET_PRESENT)) {
skt->state &= ~SOCKET_SUSPEND;
return socket_insert(skt);
}
- ret = socket_setup(skt, resume_delay);
- if (ret == 0) {
+ if (skt->resume_status == 0) {
/*
* FIXME: need a better check here for cardbus cards.
*/
@@ -596,6 +599,20 @@ static int socket_resume(struct pcmcia_socket *skt)
return 0;
}
+/*
+ * Resume a socket. If a card is present, verify its CIS against
+ * our cached copy. If they are different, the card has been
+ * replaced, and we need to tell the drivers.
+ */
+static int socket_resume(struct pcmcia_socket *skt)
+{
+ if (!(skt->state & SOCKET_SUSPEND))
+ return -EBUSY;
+
+ socket_early_resume(skt);
+ return socket_late_resume(skt);
+}
+
static void socket_remove(struct pcmcia_socket *skt)
{
dev_printk(KERN_NOTICE, &skt->dev,
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 46561face128..a04f21c8170f 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
#ifdef CONFIG_PM
static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int i82092aa_socket_resume (struct pci_dev *dev)
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 40d4953e4b12..b906abe26ad0 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1241,7 +1241,7 @@ static int pcic_init(struct pcmcia_socket *s)
static int i82365_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int i82365_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 62b4ecc97c46..d1d89c4491ad 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -699,7 +699,7 @@ static struct pccard_operations pcc_operations = {
static int cfc_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int cfc_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 12034b41d196..a0655839c8d3 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -675,7 +675,7 @@ static struct pccard_operations pcc_operations = {
static int pcc_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pcc_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index d1ad0966392d..c69f2c4fe520 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1296,7 +1296,7 @@ static int m8xx_remove(struct of_device *ofdev)
#ifdef CONFIG_PM
static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, state);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int m8xx_resume(struct platform_device *pdev)
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index f3736398900e..68570bc3ac86 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -334,7 +334,7 @@ static int __exit omap_cf_remove(struct platform_device *pdev)
static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int omap_cf_resume(struct platform_device *pdev)
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 8bed1dab9039..1c39d3438f20 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -758,7 +758,7 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
#ifdef CONFIG_PM
static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pd6729_socket_resume(struct pci_dev *dev)
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index c49a7269f6d1..86ad87604241 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -302,7 +302,7 @@ static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
static int pxa2xx_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index d8da5ac844e9..2d0e99751530 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -89,7 +89,7 @@ static int sa11x0_drv_pcmcia_remove(struct platform_device *dev)
static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int sa11x0_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index 401052a21ce8..4be4e172ffa1 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -159,7 +159,7 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev)
static int pcmcia_suspend(struct sa1111_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pcmcia_resume(struct sa1111_dev *dev)
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 8eb04230fec7..582413fcb62f 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -366,7 +366,7 @@ static int __init get_tcic_id(void)
static int tcic_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int tcic_drv_pcmcia_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index d4ad50d737b0..c9fcbdc164ea 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -707,7 +707,7 @@ __setup("vrc4171_card=", vrc4171_card_setup);
static int vrc4171_card_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int vrc4171_card_resume(struct platform_device *dev)
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 3ecd7c99d8eb..bcebffb54b25 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1225,60 +1225,81 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
}
#ifdef CONFIG_PM
-static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
+static int yenta_dev_suspend_noirq(struct device *dev)
{
- struct yenta_socket *socket = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct yenta_socket *socket = pci_get_drvdata(pdev);
int ret;
- ret = pcmcia_socket_dev_suspend(&dev->dev, state);
+ ret = pcmcia_socket_dev_suspend(dev);
- if (socket) {
- if (socket->type && socket->type->save_state)
- socket->type->save_state(socket);
+ if (!socket)
+ return ret;
- /* FIXME: pci_save_state needs to have a better interface */
- pci_save_state(dev);
- pci_read_config_dword(dev, 16*4, &socket->saved_state[0]);
- pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
- pci_disable_device(dev);
+ if (socket->type && socket->type->save_state)
+ socket->type->save_state(socket);
- /*
- * Some laptops (IBM T22) do not like us putting the Cardbus
- * bridge into D3. At a guess, some other laptop will
- * probably require this, so leave it commented out for now.
- */
- /* pci_set_power_state(dev, 3); */
- }
+ pci_save_state(pdev);
+ pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]);
+ pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]);
+ pci_disable_device(pdev);
+
+ /*
+ * Some laptops (IBM T22) do not like us putting the Cardbus
+ * bridge into D3. At a guess, some other laptop will
+ * probably require this, so leave it commented out for now.
+ */
+ /* pci_set_power_state(dev, 3); */
return ret;
}
-
-static int yenta_dev_resume (struct pci_dev *dev)
+static int yenta_dev_resume_noirq(struct device *dev)
{
- struct yenta_socket *socket = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct yenta_socket *socket = pci_get_drvdata(pdev);
+ int ret;
- if (socket) {
- int rc;
+ if (!socket)
+ return 0;
- pci_set_power_state(dev, 0);
- /* FIXME: pci_restore_state needs to have a better interface */
- pci_restore_state(dev);
- pci_write_config_dword(dev, 16*4, socket->saved_state[0]);
- pci_write_config_dword(dev, 17*4, socket->saved_state[1]);
+ pci_write_config_dword(pdev, 16*4, socket->saved_state[0]);
+ pci_write_config_dword(pdev, 17*4, socket->saved_state[1]);
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
+ ret = pci_enable_device(pdev);
+ if (ret)
+ return ret;
- pci_set_master(dev);
+ pci_set_master(pdev);
- if (socket->type && socket->type->restore_state)
- socket->type->restore_state(socket);
- }
+ if (socket->type && socket->type->restore_state)
+ socket->type->restore_state(socket);
+
+ pcmcia_socket_dev_early_resume(dev);
+ return 0;
+}
- return pcmcia_socket_dev_resume(&dev->dev);
+static int yenta_dev_resume(struct device *dev)
+{
+ pcmcia_socket_dev_late_resume(dev);
+ return 0;
}
+
+static struct dev_pm_ops yenta_pm_ops = {
+ .suspend_noirq = yenta_dev_suspend_noirq,
+ .resume_noirq = yenta_dev_resume_noirq,
+ .resume = yenta_dev_resume,
+ .freeze_noirq = yenta_dev_suspend_noirq,
+ .thaw_noirq = yenta_dev_resume_noirq,
+ .thaw = yenta_dev_resume,
+ .poweroff_noirq = yenta_dev_suspend_noirq,
+ .restore_noirq = yenta_dev_resume_noirq,
+ .restore = yenta_dev_resume,
+};
+
+#define YENTA_PM_OPS (&yenta_pm_ops)
+#else
+#define YENTA_PM_OPS NULL
#endif
#define CB_ID(vend,dev,type) \
@@ -1376,10 +1397,7 @@ static struct pci_driver yenta_cardbus_driver = {
.id_table = yenta_table,
.probe = yenta_probe,
.remove = __devexit_p(yenta_close),
-#ifdef CONFIG_PM
- .suspend = yenta_dev_suspend,
- .resume = yenta_dev_resume,
-#endif
+ .driver.pm = YENTA_PM_OPS,
};
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index bdfee177eefb..034ca6d9081d 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -52,7 +52,7 @@
*/
#undef START_IN_KERNEL_MODE
-#define DRV_VER "0.5.13"
+#define DRV_VER "0.5.16"
/*
* According to the Atom N270 datasheet,
@@ -61,7 +61,7 @@
* measured by the on-die thermal monitor are within 0 <= Tj <= 90. So,
* assume 89°C is critical temperature.
*/
-#define ACERHDF_TEMP_CRIT 89
+#define ACERHDF_TEMP_CRIT 89000
#define ACERHDF_FAN_OFF 0
#define ACERHDF_FAN_AUTO 1
@@ -69,7 +69,7 @@
* No matter what value the user puts into the fanon variable, turn on the fan
* at 80 degree Celsius to prevent hardware damage
*/
-#define ACERHDF_MAX_FANON 80
+#define ACERHDF_MAX_FANON 80000
/*
* Maximum interval between two temperature checks is 15 seconds, as the die
@@ -85,11 +85,12 @@ static int kernelmode;
#endif
static unsigned int interval = 10;
-static unsigned int fanon = 63;
-static unsigned int fanoff = 58;
+static unsigned int fanon = 63000;
+static unsigned int fanoff = 58000;
static unsigned int verbose;
static unsigned int fanstate = ACERHDF_FAN_AUTO;
static char force_bios[16];
+static char force_product[16];
static unsigned int prev_interval;
struct thermal_zone_device *thz_dev;
struct thermal_cooling_device *cl_dev;
@@ -107,34 +108,62 @@ module_param(verbose, uint, 0600);
MODULE_PARM_DESC(verbose, "Enable verbose dmesg output");
module_param_string(force_bios, force_bios, 16, 0);
MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check");
+module_param_string(force_product, force_product, 16, 0);
+MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
+
+/*
+ * cmd_off: to switch the fan completely off / to check if the fan is off
+ * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then
+ * the fan speed depending on the temperature
+ */
+struct fancmd {
+ u8 cmd_off;
+ u8 cmd_auto;
+};
/* BIOS settings */
struct bios_settings_t {
const char *vendor;
+ const char *product;
const char *version;
unsigned char fanreg;
unsigned char tempreg;
- unsigned char fancmd[2]; /* fan off and auto commands */
+ struct fancmd cmd;
};
/* Register addresses and values for different BIOS versions */
static const struct bios_settings_t bios_tbl[] = {
- {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} },
- {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
- {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} },
- {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} },
- {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} },
- {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} },
- {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} },
- {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} },
- {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
- {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
- {"", "", 0, 0, {0, 0} }
+ /* AOA110 */
+ {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} },
+ {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
+ {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} },
+ {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} },
+ {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} },
+ {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} },
+ {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} },
+ {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} },
+ {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} },
+ /* AOA150 */
+ {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
+ /* special BIOS / other */
+ {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
+ {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
+ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
+ {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
+ {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
+ /* pewpew-terminator */
+ {"", "", "", 0, 0, {0, 0} }
};
static const struct bios_settings_t *bios_cfg __read_mostly;
-
static int acerhdf_get_temp(int *temp)
{
u8 read_temp;
@@ -142,7 +171,7 @@ static int acerhdf_get_temp(int *temp)
if (ec_read(bios_cfg->tempreg, &read_temp))
return -EINVAL;
- *temp = read_temp;
+ *temp = read_temp * 1000;
return 0;
}
@@ -150,13 +179,14 @@ static int acerhdf_get_temp(int *temp)
static int acerhdf_get_fanstate(int *state)
{
u8 fan;
- bool tmp;
if (ec_read(bios_cfg->fanreg, &fan))
return -EINVAL;
- tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]);
- *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO;
+ if (fan != bios_cfg->cmd.cmd_off)
+ *state = ACERHDF_FAN_AUTO;
+ else
+ *state = ACERHDF_FAN_OFF;
return 0;
}
@@ -175,7 +205,8 @@ static void acerhdf_change_fanstate(int state)
state = ACERHDF_FAN_AUTO;
}
- cmd = bios_cfg->fancmd[state];
+ cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off
+ : bios_cfg->cmd.cmd_auto;
fanstate = state;
ec_write(bios_cfg->fanreg, cmd);
@@ -437,7 +468,7 @@ static int acerhdf_remove(struct platform_device *device)
return 0;
}
-struct platform_driver acerhdf_drv = {
+static struct platform_driver acerhdf_driver = {
.driver = {
.name = "acerhdf",
.owner = THIS_MODULE,
@@ -454,32 +485,40 @@ static int acerhdf_check_hardware(void)
{
char const *vendor, *version, *product;
int i;
+ unsigned long prod_len = 0;
/* get BIOS data */
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
version = dmi_get_system_info(DMI_BIOS_VERSION);
product = dmi_get_system_info(DMI_PRODUCT_NAME);
+
pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER);
- if (!force_bios[0]) {
- if (strncmp(product, "AO", 2)) {
- pr_err("no Aspire One hardware found\n");
- return -EINVAL;
- }
- } else {
- pr_info("forcing BIOS version: %s\n", version);
+ if (force_bios[0]) {
version = force_bios;
+ pr_info("forcing BIOS version: %s\n", version);
kernelmode = 0;
}
+ if (force_product[0]) {
+ product = force_product;
+ pr_info("forcing BIOS product: %s\n", product);
+ kernelmode = 0;
+ }
+
+ prod_len = strlen(product);
+
if (verbose)
pr_info("BIOS info: %s %s, product: %s\n",
vendor, version, product);
/* search BIOS version and vendor in BIOS settings table */
for (i = 0; bios_tbl[i].version[0]; i++) {
- if (!strcmp(bios_tbl[i].vendor, vendor) &&
+ if (strlen(bios_tbl[i].product) >= prod_len &&
+ !strncmp(bios_tbl[i].product, product,
+ strlen(bios_tbl[i].product)) &&
+ !strcmp(bios_tbl[i].vendor, vendor) &&
!strcmp(bios_tbl[i].version, version)) {
bios_cfg = &bios_tbl[i];
break;
@@ -487,8 +526,8 @@ static int acerhdf_check_hardware(void)
}
if (!bios_cfg) {
- pr_err("unknown (unsupported) BIOS version %s/%s, "
- "please report, aborting!\n", vendor, version);
+ pr_err("unknown (unsupported) BIOS version %s/%s/%s, "
+ "please report, aborting!\n", vendor, product, version);
return -EINVAL;
}
@@ -509,7 +548,7 @@ static int acerhdf_register_platform(void)
{
int err = 0;
- err = platform_driver_register(&acerhdf_drv);
+ err = platform_driver_register(&acerhdf_driver);
if (err)
return err;
@@ -525,7 +564,7 @@ static void acerhdf_unregister_platform(void)
return;
platform_device_del(acerhdf_dev);
- platform_driver_unregister(&acerhdf_drv);
+ platform_driver_unregister(&acerhdf_driver);
}
static int acerhdf_register_thermal(void)
@@ -594,9 +633,10 @@ static void __exit acerhdf_exit(void)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Feuerer");
MODULE_DESCRIPTION("Aspire One temperature and fan driver");
-MODULE_ALIAS("dmi:*:*Acer*:*:");
-MODULE_ALIAS("dmi:*:*Gateway*:*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
module_init(acerhdf_init);
module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index db657bbeec90..fae1951cb753 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -1172,8 +1172,8 @@ static int asus_hotk_add(struct acpi_device *device)
hotk->ledd_status = 0xFFF;
/* Set initial values of light sensor and level */
- hotk->light_switch = 1; /* Default to light sensor disabled */
- hotk->light_level = 0; /* level 5 for sensor sensitivity */
+ hotk->light_switch = 0; /* Default to light sensor disabled */
+ hotk->light_level = 5; /* level 5 for sensor sensitivity */
if (ls_switch_handle)
set_light_sens_switch(hotk->light_switch);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index dafaa4a92df5..a234a9db15d9 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1081,6 +1081,8 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
struct rfkill *rfk;
enum rfkill_type type;
const char *name;
+ int result;
+ bool hwblock;
switch (nc_type) {
case SONY_WIFI:
@@ -1108,6 +1110,10 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
if (!rfk)
return -ENOMEM;
+ sony_call_snc_handle(0x124, 0x200, &result);
+ hwblock = !(result & 0x1);
+ rfkill_set_hw_state(rfk, hwblock);
+
err = rfkill_register(rfk);
if (err) {
rfkill_destroy(rfk);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index e85600852502..05e5d56f9c82 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3406,15 +3406,6 @@ enum {
#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
-static void bluetooth_suspend(pm_message_t state)
-{
- /* Try to make sure radio will resume powered off */
- if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
- TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
- vdbg_printk(TPACPI_DBG_RFKILL,
- "bluetooth power down on resume request failed\n");
-}
-
static int bluetooth_get_status(void)
{
int status;
@@ -3448,10 +3439,9 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
#endif
/* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
+ status = TP_ACPI_BLUETOOTH_RESUMECTRL;
if (state == TPACPI_RFK_RADIO_ON)
- status = TP_ACPI_BLUETOOTH_RADIOSSW;
- else
- status = 0;
+ status |= TP_ACPI_BLUETOOTH_RADIOSSW;
if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
return -EIO;
@@ -3590,7 +3580,6 @@ static struct ibm_struct bluetooth_driver_data = {
.read = bluetooth_read,
.write = bluetooth_write,
.exit = bluetooth_exit,
- .suspend = bluetooth_suspend,
.shutdown = bluetooth_shutdown,
};
@@ -3608,15 +3597,6 @@ enum {
#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
-static void wan_suspend(pm_message_t state)
-{
- /* Try to make sure radio will resume powered off */
- if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
- TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
- vdbg_printk(TPACPI_DBG_RFKILL,
- "WWAN power down on resume request failed\n");
-}
-
static int wan_get_status(void)
{
int status;
@@ -3649,11 +3629,10 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
}
#endif
- /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
+ /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
+ status = TP_ACPI_WANCARD_RESUMECTRL;
if (state == TPACPI_RFK_RADIO_ON)
- status = TP_ACPI_WANCARD_RADIOSSW;
- else
- status = 0;
+ status |= TP_ACPI_WANCARD_RADIOSSW;
if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
return -EIO;
@@ -3791,7 +3770,6 @@ static struct ibm_struct wan_driver_data = {
.read = wan_read,
.write = wan_write,
.exit = wan_exit,
- .suspend = wan_suspend,
.shutdown = wan_shutdown,
};
@@ -5655,16 +5633,16 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
/* Models with ATI GPUs known to require ECNVRAM mode */
TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
- /* Models with ATI GPUs (waiting confirmation) */
- TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+ /* Models with ATI GPUs that can use ECNVRAM */
+ TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
- /* Models with Intel Extreme Graphics 2 (waiting confirmation) */
- TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
- TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
- TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
+ /* Models with Intel Extreme Graphics 2 */
+ TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
+ TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+ TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
/* Models with Intel GMA900 */
TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
@@ -5863,7 +5841,7 @@ static int brightness_write(char *buf)
* Doing it this way makes the syscall restartable in case of EINTR
*/
rc = brightness_set(level);
- return (rc == -EINTR)? ERESTARTSYS : rc;
+ return (rc == -EINTR)? -ERESTARTSYS : rc;
}
static struct ibm_struct brightness_driver_data = {
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index 35a0b192d768..2d414e23d390 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -271,6 +271,7 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data)
{
struct pps_device *pps;
unsigned long flags;
+ int captured = 0;
if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) {
printk(KERN_ERR "pps: unknown event (%x) for source %d\n",
@@ -293,7 +294,8 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data)
/* Check the event */
pps->current_mode = pps->params.mode;
- if (event & PPS_CAPTUREASSERT) {
+ if ((event & PPS_CAPTUREASSERT) &
+ (pps->params.mode & PPS_CAPTUREASSERT)) {
/* We have to add an offset? */
if (pps->params.mode & PPS_OFFSETASSERT)
pps_add_offset(ts, &pps->params.assert_off_tu);
@@ -303,8 +305,11 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data)
pps->assert_sequence++;
pr_debug("capture assert seq #%u for source %d\n",
pps->assert_sequence, source);
+
+ captured = ~0;
}
- if (event & PPS_CAPTURECLEAR) {
+ if ((event & PPS_CAPTURECLEAR) &
+ (pps->params.mode & PPS_CAPTURECLEAR)) {
/* We have to add an offset? */
if (pps->params.mode & PPS_OFFSETCLEAR)
pps_add_offset(ts, &pps->params.clear_off_tu);
@@ -314,12 +319,17 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data)
pps->clear_sequence++;
pr_debug("capture clear seq #%u for source %d\n",
pps->clear_sequence, source);
+
+ captured = ~0;
}
- pps->go = ~0;
- wake_up_interruptible(&pps->queue);
+ /* Wake up iif captured somthing */
+ if (captured) {
+ pps->go = ~0;
+ wake_up_interruptible(&pps->queue);
- kill_fasync(&pps->async_queue, SIGIO, POLL_IN);
+ kill_fasync(&pps->async_queue, SIGIO, POLL_IN);
+ }
spin_unlock_irqrestore(&pps->lock, flags);
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index fea17e7805e9..ca5183bdad85 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -71,9 +71,14 @@ static long pps_cdev_ioctl(struct file *file,
case PPS_GETPARAMS:
pr_debug("PPS_GETPARAMS: source %d\n", pps->id);
- /* Return current parameters */
- err = copy_to_user(uarg, &pps->params,
- sizeof(struct pps_kparams));
+ spin_lock_irq(&pps->lock);
+
+ /* Get the current parameters */
+ params = pps->params;
+
+ spin_unlock_irq(&pps->lock);
+
+ err = copy_to_user(uarg, &params, sizeof(struct pps_kparams));
if (err)
return -EFAULT;
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
index 18066d555397..af0afa1db4a8 100644
--- a/drivers/ps3/ps3stor_lib.c
+++ b/drivers/ps3/ps3stor_lib.c
@@ -23,6 +23,65 @@
#include <asm/lv1call.h>
#include <asm/ps3stor.h>
+/*
+ * A workaround for flash memory I/O errors when the internal hard disk
+ * has not been formatted for OtherOS use. Delay disk close until flash
+ * memory is closed.
+ */
+
+static struct ps3_flash_workaround {
+ int flash_open;
+ int disk_open;
+ struct ps3_system_bus_device *disk_sbd;
+} ps3_flash_workaround;
+
+static int ps3stor_open_hv_device(struct ps3_system_bus_device *sbd)
+{
+ int error = ps3_open_hv_device(sbd);
+
+ if (error)
+ return error;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_FLASH)
+ ps3_flash_workaround.flash_open = 1;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_DISK)
+ ps3_flash_workaround.disk_open = 1;
+
+ return 0;
+}
+
+static int ps3stor_close_hv_device(struct ps3_system_bus_device *sbd)
+{
+ int error;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_DISK
+ && ps3_flash_workaround.disk_open
+ && ps3_flash_workaround.flash_open) {
+ ps3_flash_workaround.disk_sbd = sbd;
+ return 0;
+ }
+
+ error = ps3_close_hv_device(sbd);
+
+ if (error)
+ return error;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_DISK)
+ ps3_flash_workaround.disk_open = 0;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_FLASH) {
+ ps3_flash_workaround.flash_open = 0;
+
+ if (ps3_flash_workaround.disk_sbd) {
+ ps3_close_hv_device(ps3_flash_workaround.disk_sbd);
+ ps3_flash_workaround.disk_open = 0;
+ ps3_flash_workaround.disk_sbd = NULL;
+ }
+ }
+
+ return 0;
+}
static int ps3stor_probe_access(struct ps3_storage_device *dev)
{
@@ -90,7 +149,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
int error, res, alignment;
enum ps3_dma_page_size page_size;
- error = ps3_open_hv_device(&dev->sbd);
+ error = ps3stor_open_hv_device(&dev->sbd);
if (error) {
dev_err(&dev->sbd.core,
"%s:%u: ps3_open_hv_device failed %d\n", __func__,
@@ -166,7 +225,7 @@ fail_free_irq:
fail_sb_event_receive_port_destroy:
ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
fail_close_device:
- ps3_close_hv_device(&dev->sbd);
+ ps3stor_close_hv_device(&dev->sbd);
fail:
return error;
}
@@ -193,7 +252,7 @@ void ps3stor_teardown(struct ps3_storage_device *dev)
"%s:%u: destroy event receive port failed %d\n",
__func__, __LINE__, error);
- error = ps3_close_hv_device(&dev->sbd);
+ error = ps3stor_close_hv_device(&dev->sbd);
if (error)
dev_err(&dev->sbd.core,
"%s:%u: ps3_close_hv_device failed %d\n", __func__,
diff --git a/drivers/regulator/max17135-regulator.c b/drivers/regulator/max17135-regulator.c
index a667c2f7cf59..3fdec795fbeb 100644
--- a/drivers/regulator/max17135-regulator.c
+++ b/drivers/regulator/max17135-regulator.c
@@ -30,6 +30,12 @@
#include <linux/gpio.h>
/*
+ * Define this as 1 when using a Rev 1 MAX17135 part. These parts have
+ * some limitations, including an inability to turn on the PMIC via I2C.
+ */
+#define MAX17135_REV 1
+
+/*
* PMIC Register Addresses
*/
enum {
@@ -170,8 +176,27 @@ enum {
#define MAX17135_GVEE_MIN_VAL 0
#define MAX17135_GVEE_MAX_VAL 1
+#if (MAX17135_REV == 1)
+#define MAX17135_VCOM_MIN_uV -4325000
+#define MAX17135_VCOM_MAX_uV -500000
+#define MAX17135_VCOM_STEP_uV 15000
#define MAX17135_VCOM_MIN_VAL 0
#define MAX17135_VCOM_MAX_VAL 255
+/* Required due to discrepancy between
+ * observed VCOM programming and
+ * what is suggested in the spec.
+ */
+#define MAX17135_VCOM_FUDGE_FACTOR 330000
+#else
+#define MAX17135_VCOM_MIN_uV -3050000
+#define MAX17135_VCOM_MAX_uV -500000
+#define MAX17135_VCOM_STEP_uV 10000
+#define MAX17135_VCOM_MIN_VAL 0
+#define MAX17135_VCOM_MAX_VAL 255
+#define MAX17135_VCOM_FUDGE_FACTOR 330000
+#endif
+
+#define MAX17135_VCOM_VOLTAGE_DEFAULT -1250000
#define MAX17135_VNEG_MIN_uV 5000000
#define MAX17135_VNEG_MAX_uV 20000000
@@ -185,25 +210,6 @@ enum {
#define MAX17135_VPOS_MIN_VAL 0
#define MAX17135_VPOS_MAX_VAL 1
-struct max17135_vcom_programming_data {
- int vcom_min_uV;
- int vcom_max_uV;
- int vcom_step_uV;
-};
-
-struct max17135_vcom_programming_data vcom_data[2] = {
- {
- -4325000,
- -500000,
- 15000,
- },
- {
- -3050000,
- -500000,
- 10000,
- },
-};
-
struct max17135 {
/* chip revision */
int rev;
@@ -222,9 +228,6 @@ struct max17135 {
int gpio_pmic_wakeup;
int gpio_pmic_intr;
- int pass_num;
- int vcom_uV;
-
bool vcom_setup;
int max_wait;
@@ -290,17 +293,15 @@ static int max17135_hvinp_disable(struct regulator_dev *reg)
}
/* Convert uV to the VCOM register bitfield setting */
-static inline int vcom_uV_to_rs(int uV, int pass_num)
+static inline int vcom_uV_to_rs(int uV)
{
- return (vcom_data[pass_num].vcom_max_uV - uV)
- / vcom_data[pass_num].vcom_step_uV;
+ return (MAX17135_VCOM_MAX_uV - uV) / MAX17135_VCOM_STEP_uV;
}
/* Convert the VCOM register bitfield setting to uV */
-static inline int vcom_rs_to_uV(int rs, int pass_num)
+static inline int vcom_rs_to_uV(int rs)
{
- return vcom_data[pass_num].vcom_max_uV
- - (vcom_data[pass_num].vcom_step_uV * rs);
+ return MAX17135_VCOM_MAX_uV - (MAX17135_VCOM_STEP_uV * rs);
}
static int max17135_vcom_set_voltage(struct regulator_dev *reg,
@@ -311,8 +312,7 @@ static int max17135_vcom_set_voltage(struct regulator_dev *reg,
unsigned int reg_val;
int vcom_read;
- if ((uV < vcom_data[max17135->pass_num-1].vcom_min_uV)
- || (uV > vcom_data[max17135->pass_num-1].vcom_max_uV))
+ if ((uV < MAX17135_VCOM_MIN_uV) || (uV > MAX17135_VCOM_MAX_uV))
return -EINVAL;
reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_DVR);
@@ -322,11 +322,11 @@ static int max17135_vcom_set_voltage(struct regulator_dev *reg,
* Programming VCOM excessively degrades ability to keep
* DVR register value persistent.
*/
- vcom_read = vcom_rs_to_uV(reg_val, max17135->pass_num-1);
- if (vcom_read != max17135->vcom_uV) {
+ vcom_read = vcom_rs_to_uV(reg_val) - MAX17135_VCOM_FUDGE_FACTOR;
+ if (vcom_read != MAX17135_VCOM_VOLTAGE_DEFAULT) {
reg_val &= ~BITFMASK(DVR);
- reg_val |= BITFVAL(DVR, vcom_uV_to_rs(uV,
- max17135->pass_num-1));
+ reg_val |= BITFVAL(DVR,
+ vcom_uV_to_rs(uV + MAX17135_VCOM_FUDGE_FACTOR));
i2c_smbus_write_byte_data(client, REG_MAX17135_DVR, reg_val);
reg_val = BITFVAL(CTRL_DVR, true); /* shift to correct bit */
@@ -342,7 +342,7 @@ static int max17135_vcom_get_voltage(struct regulator_dev *reg)
unsigned int reg_val;
reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_DVR);
- return vcom_rs_to_uV(BITFEXT(reg_val, DVR), max17135->pass_num-1);
+ return vcom_rs_to_uV(BITFEXT(reg_val, DVR));
}
static int max17135_vcom_enable(struct regulator_dev *reg)
@@ -357,41 +357,38 @@ static int max17135_vcom_enable(struct regulator_dev *reg)
if (!max17135->vcom_setup
&& gpio_get_value(max17135->gpio_pmic_pwrgood)) {
max17135_vcom_set_voltage(reg,
- max17135->vcom_uV,
- max17135->vcom_uV);
+ MAX17135_VCOM_VOLTAGE_DEFAULT,
+ MAX17135_VCOM_VOLTAGE_DEFAULT);
max17135->vcom_setup = true;
}
/* enable VCOM regulator output */
- if (max17135->pass_num == 1)
- gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 1);
- else {
- struct i2c_client *client = max17135->i2c_client;
- unsigned int reg_val;
-
- reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_ENABLE);
- reg_val &= ~BITFMASK(VCOM_ENABLE);
- reg_val |= BITFVAL(VCOM_ENABLE, 1); /* shift to correct bit */
- i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE, reg_val);
- }
+#if (MAX17135_REV == 1)
+ gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 1);
+#else
+ struct i2c_client *client = max17135->i2c_client;
+ reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_ENABLE);
+ reg_val &= ~BITFMASK(VCOM_ENABLE);
+ reg_val |= BITFVAL(VCOM_ENABLE, 1); /* shift to correct bit */
+ i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE, reg_val);
+#endif
return 0;
}
static int max17135_vcom_disable(struct regulator_dev *reg)
{
struct max17135 *max17135 = rdev_get_drvdata(reg);
- if (max17135->pass_num == 1)
- gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 0);
- else {
- struct i2c_client *client = max17135->i2c_client;
- unsigned int reg_val;
-
- reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_ENABLE);
- reg_val &= ~BITFMASK(VCOM_ENABLE);
- i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE, reg_val);
- }
+#if (MAX17135_REV == 1)
+ gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 0);
+#else
+ struct i2c_client *client = max17135->i2c_client;
+ unsigned int reg_val;
+ reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_ENABLE);
+ reg_val &= ~BITFMASK(VCOM_ENABLE);
+ i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE, reg_val);
+#endif
return 0;
}
@@ -411,21 +408,17 @@ static int max17135_wait_power_good(struct max17135 *max17135)
static int max17135_display_enable(struct regulator_dev *reg)
{
struct max17135 *max17135 = rdev_get_drvdata(reg);
+#if (MAX17135_REV == 1)
+ gpio_set_value(max17135->gpio_pmic_wakeup, 1);
+#else
+ struct i2c_client *client = max17135->i2c_client;
+ unsigned int reg_val;
- /* The Pass 1 parts cannot turn on the PMIC via I2C. */
- if (max17135->pass_num == 1)
- gpio_set_value(max17135->gpio_pmic_wakeup, 1);
- else {
- struct i2c_client *client = max17135->i2c_client;
- unsigned int reg_val;
-
- reg_val = i2c_smbus_read_byte_data(client,
- REG_MAX17135_ENABLE);
- reg_val &= ~BITFMASK(ENABLE);
- reg_val |= BITFVAL(ENABLE, 1);
- i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE,
- reg_val);
- }
+ reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_ENABLE);
+ reg_val &= ~BITFMASK(ENABLE);
+ reg_val |= BITFVAL(ENABLE, 1);
+ i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE, reg_val);
+#endif
return max17135_wait_power_good(max17135);
}
@@ -433,20 +426,17 @@ static int max17135_display_enable(struct regulator_dev *reg)
static int max17135_display_disable(struct regulator_dev *reg)
{
struct max17135 *max17135 = rdev_get_drvdata(reg);
+#if (MAX17135_REV == 1)
+ gpio_set_value(max17135->gpio_pmic_wakeup, 0);
+#else
+ struct i2c_client *client = max17135->i2c_client;
+ unsigned int reg_val;
- if (max17135->pass_num == 1)
- gpio_set_value(max17135->gpio_pmic_wakeup, 0);
- else {
- struct i2c_client *client = max17135->i2c_client;
- unsigned int reg_val;
-
- reg_val = i2c_smbus_read_byte_data(client,
- REG_MAX17135_ENABLE);
- reg_val &= ~BITFMASK(ENABLE);
- i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE,
- reg_val);
- }
-
+ reg_val = i2c_smbus_read_byte_data(client, REG_MAX17135_ENABLE);
+ reg_val &= ~BITFMASK(ENABLE);
+ i2c_smbus_write_byte_data(client, REG_MAX17135_ENABLE, reg_val);
+ msleep(PMIC_DISABLE__V3P3_DESERT/1000);
+#endif
return 0;
}
@@ -668,9 +658,6 @@ static int max17135_i2c_probe(struct i2c_client *client,
max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
- max17135->pass_num = pdata->pass_num;
- max17135->vcom_uV = pdata->vcom_uV;
-
max17135->vcom_setup = false;
ret = platform_driver_register(&max17135_regulator_driver);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index bd320c1ab70c..09492700cddf 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -109,16 +109,6 @@ config RTC_INTF_DEV_UIE_EMUL
clock several times per second, please enable this option
only if you know that you really need it.
-config RTC_INTF_ALARM
- bool "Android alarm driver"
- depends on RTC_CLASS
- default y
- help
- Provides non-wakeup and rtc backed wakeup alarms based on rtc or
- elapsed realtime, and a non-wakeup alarm on the monotonic clock.
- Also provides an ioctl to set the wall time which must be used
- for elapsed realtime to work.
-
config RTC_DRV_TEST
tristate "Test driver/device"
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index c8df86258348..91da97eca589 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
rtc-core-y := class.o interface.o
-rtc-core-$(CONFIG_RTC_INTF_ALARM) += alarm.o
rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index 3a7be11cc6b9..812c66755083 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -376,20 +376,22 @@ static int __devinit fm3130_probe(struct i2c_client *client,
}
/* Disabling calibration mode */
- if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL)
+ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_CAL));
dev_warn(&client->dev, "Disabling calibration mode!\n");
+ }
/* Disabling read and write modes */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
- fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ)
+ fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_READ |
FM3130_RTC_CONTROL_BIT_WRITE));
dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
+ }
/* oscillator off? turn it on, so clock can tick. */
if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
diff --git a/drivers/rtc/rtc-mxs.c b/drivers/rtc/rtc-mxs.c
index bb4c33b1a0ba..0e2b0e1e14f6 100644
--- a/drivers/rtc/rtc-mxs.c
+++ b/drivers/rtc/rtc-mxs.c
@@ -254,8 +254,6 @@ static int mxs_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc_data);
- device_init_wakeup(&pdev->dev, 1);
-
return 0;
}
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index ad164056feb6..423cd5a30b10 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -96,7 +96,7 @@ static void v3020_mmio_write_bit(struct v3020 *chip, unsigned char bit)
static unsigned char v3020_mmio_read_bit(struct v3020 *chip)
{
- return readl(chip->ioaddress) & (1 << chip->leftshift);
+ return !!(readl(chip->ioaddress) & (1 << chip->leftshift));
}
static struct v3020_chip_ops v3020_mmio_ops = {
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 644086ba2ede..b76dee9f2861 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -145,6 +145,15 @@ dasd_diag_erp(struct dasd_device *device)
mdsk_term_io(device);
rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
+ if (rc == 4) {
+ if (!(device->features & DASD_FEATURE_READONLY)) {
+ dev_warn(&device->cdev->dev,
+ "The access mode of a DIAG device changed"
+ " to read-only");
+ device->features |= DASD_FEATURE_READONLY;
+ }
+ rc = 0;
+ }
if (rc)
dev_warn(&device->cdev->dev, "DIAG ERP failed with "
"rc=%d\n", rc);
@@ -433,16 +442,20 @@ dasd_diag_check_device(struct dasd_device *device)
for (sb = 512; sb < bsize; sb = sb << 1)
block->s2b_shift++;
rc = mdsk_init_io(device, block->bp_block, 0, NULL);
- if (rc) {
+ if (rc && (rc != 4)) {
dev_warn(&device->cdev->dev, "DIAG initialization "
"failed with rc=%d\n", rc);
rc = -EIO;
} else {
+ if (rc == 4)
+ device->features |= DASD_FEATURE_READONLY;
dev_info(&device->cdev->dev,
- "New DASD with %ld byte/block, total size %ld KB\n",
+ "New DASD with %ld byte/block, total size %ld KB%s\n",
(unsigned long) block->bp_block,
(unsigned long) (block->blocks <<
- block->s2b_shift) >> 1);
+ block->s2b_shift) >> 1,
+ (rc == 4) ? ", read-only device" : "");
+ rc = 0;
}
out_label:
free_page((long) label);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index b6af63ca980b..496764349c41 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -1918,6 +1918,10 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
}
size = size>>16;
size *= 4;
+ if (size > MAX_MESSAGE_SIZE) {
+ rcode = -EINVAL;
+ goto cleanup;
+ }
/* Copy in the user's I2O command */
if (copy_from_user (msg, user_msg, size)) {
rcode = -EFAULT;
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 185e6bc4dd40..9e8fce0f0c1b 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2900,7 +2900,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
eindex = handle;
estr->event_source = 0;
- if (eindex >= MAX_EVENTS) {
+ if (eindex < 0 || eindex >= MAX_EVENTS) {
spin_unlock_irqrestore(&ha->smp_lock, flags);
return eindex;
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5fd2da494d08..28a753d796f3 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -180,14 +180,20 @@ void scsi_remove_host(struct Scsi_Host *shost)
EXPORT_SYMBOL(scsi_remove_host);
/**
- * scsi_add_host - add a scsi host
+ * scsi_add_host_with_dma - add a scsi host with dma device
* @shost: scsi host pointer to add
* @dev: a struct device of type scsi class
+ * @dma_dev: dma device for the host
+ *
+ * Note: You rarely need to worry about this unless you're in a
+ * virtualised host environments, so use the simpler scsi_add_host()
+ * function instead.
*
* Return value:
* 0 on success / != 0 for error
**/
-int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
+ struct device *dma_dev)
{
struct scsi_host_template *sht = shost->hostt;
int error = -EINVAL;
@@ -207,6 +213,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (!shost->shost_gendev.parent)
shost->shost_gendev.parent = dev ? dev : &platform_bus;
+ shost->dma_dev = dma_dev;
error = device_add(&shost->shost_gendev);
if (error)
@@ -262,7 +269,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
fail:
return error;
}
-EXPORT_SYMBOL(scsi_add_host);
+EXPORT_SYMBOL(scsi_add_host_with_dma);
static void scsi_host_dev_release(struct device *dev)
{
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c
index 2742ae8a3d09..9ad38e81e343 100644
--- a/drivers/scsi/libsrp.c
+++ b/drivers/scsi/libsrp.c
@@ -124,6 +124,7 @@ static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max,
dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
kfree(ring[i]);
}
+ kfree(ring);
}
int srp_target_alloc(struct srp_target *target, struct device *dev,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index fc67cc65c63b..cf13ff2e9f01 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2384,7 +2384,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
vport->els_tmofunc.function = lpfc_els_timeout;
vport->els_tmofunc.data = (unsigned long)vport;
- error = scsi_add_host(shost, dev);
+ error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
if (error)
goto out_put_shost;
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 7dc3d1894b1a..4352e30cd1f6 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -3032,7 +3032,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
int error = 0, i;
void *sense = NULL;
dma_addr_t sense_handle;
- u32 *sense_ptr;
+ unsigned long *sense_ptr;
memset(kbuff_arr, 0, sizeof(kbuff_arr));
@@ -3109,7 +3109,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
}
sense_ptr =
- (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
+ (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
*sense_ptr = sense_handle;
}
@@ -3140,8 +3140,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
* sense_ptr points to the location that has the user
* sense buffer address
*/
- sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
- ioc->sense_off);
+ sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
+ ioc->sense_off);
if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
sense, ioc->sense_len)) {
@@ -3451,7 +3451,7 @@ out:
return retval;
}
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO,
+static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
megasas_sysfs_show_poll_mode_io,
megasas_sysfs_set_poll_mode_io);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 35a13867495e..2e4bc3d2b435 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -94,7 +94,7 @@ _base_fault_reset_work(struct work_struct *work)
int rc;
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->ioc_reset_in_progress)
+ if (ioc->shost_recovery)
goto rearm_timer;
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
@@ -1542,6 +1542,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
(ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
ioc->bios_pg3.BiosVersion & 0x000000FF);
+ _base_display_dell_branding(ioc);
+
printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
@@ -1554,8 +1556,6 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
i++;
}
- _base_display_dell_branding(ioc);
-
i = 0;
printk("), ");
printk("Capabilities=(");
@@ -1627,6 +1627,9 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
u32 iounit_pg1_flags;
mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
+ if (ioc->ir_firmware)
+ mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
+ &ioc->manu_pg10);
mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
@@ -3501,20 +3504,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
__func__));
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->ioc_reset_in_progress) {
+ if (ioc->shost_recovery) {
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
printk(MPT2SAS_ERR_FMT "%s: busy\n",
ioc->name, __func__);
return -EBUSY;
}
- ioc->ioc_reset_in_progress = 1;
ioc->shost_recovery = 1;
- if (ioc->shost->shost_state == SHOST_RUNNING) {
- /* set back to SHOST_RUNNING in mpt2sas_scsih.c */
- scsi_host_set_state(ioc->shost, SHOST_RECOVERY);
- printk(MPT2SAS_INFO_FMT "putting controller into "
- "SHOST_RECOVERY\n", ioc->name);
- }
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
_base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
@@ -3534,7 +3530,10 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- ioc->ioc_reset_in_progress = 0;
+ ioc->shost_recovery = 0;
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ if (!r)
+ _base_reset_handler(ioc, MPT2_IOC_RUNNING);
return r;
}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index acdcff150a35..22f84d3a3f2e 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -119,6 +119,7 @@
#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */
#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */
#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */
+#define MPT2_IOC_RUNNING 4 /* shost running */
/*
* logging format
@@ -196,6 +197,38 @@ struct MPT2SAS_TARGET {
* @block: device is in SDEV_BLOCK state
* @tlr_snoop_check: flag used in determining whether to disable TLR
*/
+
+/* OEM Identifiers */
+#define MFG10_OEM_ID_INVALID (0x00000000)
+#define MFG10_OEM_ID_DELL (0x00000001)
+#define MFG10_OEM_ID_FSC (0x00000002)
+#define MFG10_OEM_ID_SUN (0x00000003)
+#define MFG10_OEM_ID_IBM (0x00000004)
+
+/* GENERIC Flags 0*/
+#define MFG10_GF0_OCE_DISABLED (0x00000001)
+#define MFG10_GF0_R1E_DRIVE_COUNT (0x00000002)
+#define MFG10_GF0_R10_DISPLAY (0x00000004)
+#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008)
+#define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010)
+
+/* OEM Specific Flags will come from OEM specific header files */
+typedef struct _MPI2_CONFIG_PAGE_MAN_10 {
+ MPI2_CONFIG_PAGE_HEADER Header; /* 00h */
+ U8 OEMIdentifier; /* 04h */
+ U8 Reserved1; /* 05h */
+ U16 Reserved2; /* 08h */
+ U32 Reserved3; /* 0Ch */
+ U32 GenericFlags0; /* 10h */
+ U32 GenericFlags1; /* 14h */
+ U32 Reserved4; /* 18h */
+ U32 OEMSpecificFlags0; /* 1Ch */
+ U32 OEMSpecificFlags1; /* 20h */
+ U32 Reserved5[18]; /* 24h-60h*/
+} MPI2_CONFIG_PAGE_MAN_10,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10,
+ Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t;
+
struct MPT2SAS_DEVICE {
struct MPT2SAS_TARGET *sas_target;
unsigned int lun;
@@ -431,7 +464,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
* @fw_event_list: list of fw events
* @aen_event_read_flag: event log was read
* @broadcast_aen_busy: broadcast aen waiting to be serviced
- * @ioc_reset_in_progress: host reset in progress
+ * @shost_recovery: host reset in progress
* @ioc_reset_in_progress_lock:
* @ioc_link_reset_in_progress: phy/hard reset in progress
* @ignore_loginfos: ignore loginfos during task managment
@@ -460,6 +493,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
* @facts: static facts data
* @pfacts: static port facts data
* @manu_pg0: static manufacturing page 0
+ * @manu_pg10: static manufacturing page 10
* @bios_pg2: static bios page 2
* @bios_pg3: static bios page 3
* @ioc_pg8: static ioc page 8
@@ -544,7 +578,6 @@ struct MPT2SAS_ADAPTER {
/* misc flags */
int aen_event_read_flag;
u8 broadcast_aen_busy;
- u8 ioc_reset_in_progress;
u8 shost_recovery;
spinlock_t ioc_reset_in_progress_lock;
u8 ioc_link_reset_in_progress;
@@ -663,6 +696,7 @@ struct MPT2SAS_ADAPTER {
dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
+ Mpi2ManufacturingPage10_t manu_pg10;
u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
};
@@ -734,6 +768,8 @@ void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 re
int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys);
int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
+int mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page);
int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
*mpi_reply, Mpi2BiosPage2_t *config_page);
int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
@@ -776,7 +812,6 @@ int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
u16 *volume_handle);
int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
u64 *wwid);
-
/* ctl shared API */
extern struct device_attribute *mpt2sas_host_attrs[];
extern struct device_attribute *mpt2sas_dev_attrs[];
@@ -802,5 +837,7 @@ void mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc, u16 h
u16 attached_handle, u8 phy_number, u8 link_rate);
extern struct sas_function_template mpt2sas_transport_functions;
extern struct scsi_transport_template *mpt2sas_transport_template;
+extern int scsi_internal_device_block(struct scsi_device *sdev);
+extern int scsi_internal_device_unblock(struct scsi_device *sdev);
#endif /* MPT2SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
index 6ddee161beb3..b9f4d0f97e50 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -426,6 +426,67 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
}
/**
+ * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ memset(config_page, 0, sizeof(Mpi2ManufacturingPage10_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+ mpi_request.Header.PageNumber = 10;
+ mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2ManufacturingPage10_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ return r;
+}
+
+/**
* mpt2sas_config_get_bios_pg2 - obtain bios page 2
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 14e473d1fa7b..c2a51018910f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -1963,7 +1963,6 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
{
enum block_state state;
long ret = -EINVAL;
- unsigned long flags;
state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
BLOCKING;
@@ -1989,13 +1988,8 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
!ioc)
return -ENODEV;
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
- flags);
+ if (ioc->shost_recovery)
return -EAGAIN;
- }
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
uarg = arg;
@@ -2098,7 +2092,6 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
struct mpt2_ioctl_command karg;
struct MPT2SAS_ADAPTER *ioc;
enum block_state state;
- unsigned long flags;
if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
return -EINVAL;
@@ -2113,13 +2106,8 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
- flags);
+ if (ioc->shost_recovery)
return -EAGAIN;
- }
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
karg.hdr.ioc_number = karg32.hdr.ioc_number;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 2e9a4445596f..bb65cce0491d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -103,7 +103,6 @@ struct sense_info {
};
-#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
/**
* struct fw_event_work - firmware event struct
* @list: link list framework
@@ -1502,7 +1501,13 @@ _scsih_slave_configure(struct scsi_device *sdev)
break;
case MPI2_RAID_VOL_TYPE_RAID1E:
qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
- r_level = "RAID1E";
+ if (ioc->manu_pg10.OEMIdentifier &&
+ (ioc->manu_pg10.GenericFlags0 &
+ MFG10_GF0_R10_DISPLAY) &&
+ !(raid_device->num_pds % 2))
+ r_level = "RAID10";
+ else
+ r_level = "RAID1E";
break;
case MPI2_RAID_VOL_TYPE_RAID1:
qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
@@ -1786,17 +1791,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
u32 ioc_state;
unsigned long timeleft;
u8 VF_ID = 0;
- unsigned long flags;
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED ||
- ioc->shost_recovery) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
+ __func__, ioc->name);
+ return;
+ }
+
+ if (ioc->shost_recovery) {
printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
__func__, ioc->name);
return;
}
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
if (ioc_state & MPI2_DOORBELL_USED) {
@@ -2222,7 +2228,7 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
MPT2SAS_INFO_FMT "SDEV_RUNNING: "
"handle(0x%04x)\n", ioc->name, handle));
sas_device_priv_data->block = 0;
- scsi_device_set_state(sdev, SDEV_RUNNING);
+ scsi_internal_device_unblock(sdev);
}
}
}
@@ -2251,7 +2257,7 @@ _scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
MPT2SAS_INFO_FMT "SDEV_BLOCK: "
"handle(0x%04x)\n", ioc->name, handle));
sas_device_priv_data->block = 1;
- scsi_device_set_state(sdev, SDEV_BLOCK);
+ scsi_internal_device_block(sdev);
}
}
}
@@ -2327,6 +2333,7 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
u16 handle;
u16 reason_code;
u8 phy_number;
+ u8 link_rate;
for (i = 0; i < event_data->NumEntries; i++) {
handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
@@ -2337,6 +2344,11 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
MPI2_EVENT_SAS_TOPO_RC_MASK;
if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
_scsih_block_io_device(ioc, handle);
+ if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
+ link_rate = event_data->PHY[i].LinkRate >> 4;
+ if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)
+ _scsih_ublock_io_device(ioc, handle);
+ }
}
}
@@ -2405,27 +2417,6 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
}
/**
- * _scsih_queue_rescan - queue a topology rescan from user context
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
-{
- struct fw_event_work *fw_event;
-
- if (ioc->wait_for_port_enable_to_complete)
- return;
- fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
- if (!fw_event)
- return;
- fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
- fw_event->ioc = ioc;
- _scsih_fw_event_add(ioc, fw_event);
-}
-
-/**
* _scsih_flush_running_cmds - completing outstanding commands.
* @ioc: per adapter object
*
@@ -2456,46 +2447,6 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
}
/**
- * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- *
- * Return nothing.
- */
-void
-mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
- switch (reset_phase) {
- case MPT2_IOC_PRE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
- "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
- _scsih_fw_event_off(ioc);
- break;
- case MPT2_IOC_AFTER_RESET:
- dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
- "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
- if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
- ioc->tm_cmds.status |= MPT2_CMD_RESET;
- mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
- complete(&ioc->tm_cmds.done);
- }
- _scsih_fw_event_on(ioc);
- _scsih_flush_running_cmds(ioc);
- break;
- case MPT2_IOC_DONE_RESET:
- dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
- "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
- _scsih_queue_rescan(ioc);
- break;
- }
-}
-
-/**
* _scsih_setup_eedp - setup MPI request for EEDP transfer
* @scmd: pointer to scsi command object
* @mpi_request: pointer to the SCSI_IO reqest message frame
@@ -2615,7 +2566,6 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
Mpi2SCSIIORequest_t *mpi_request;
u32 mpi_control;
u16 smid;
- unsigned long flags;
scmd->scsi_done = done;
sas_device_priv_data = scmd->device->hostdata;
@@ -2634,13 +2584,10 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
}
/* see if we are busy with task managment stuff */
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (sas_target_priv_data->tm_busy ||
- ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (sas_target_priv_data->tm_busy)
+ return SCSI_MLQUEUE_DEVICE_BUSY;
+ else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
return SCSI_MLQUEUE_HOST_BUSY;
- }
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
if (scmd->sc_data_direction == DMA_FROM_DEVICE)
mpi_control = MPI2_SCSIIO_CONTROL_READ;
@@ -3436,6 +3383,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
if (!handle)
return -1;
+ if (ioc->shost_recovery)
+ return -1;
+
if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
@@ -3572,6 +3522,9 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle)
struct _sas_node *sas_expander;
unsigned long flags;
+ if (ioc->shost_recovery)
+ return;
+
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
@@ -3743,6 +3696,8 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
mutex_unlock(&ioc->tm_cmds.mutex);
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset "
"done: handle(0x%04x)\n", ioc->name, device_handle));
+ if (ioc->shost_recovery)
+ goto out;
}
/* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
@@ -3765,6 +3720,9 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
le32_to_cpu(mpi_reply.IOCLogInfo)));
out:
+
+ _scsih_ublock_io_device(ioc, handle);
+
mpt2sas_transport_port_remove(ioc, sas_device->sas_address,
sas_device->parent_handle);
@@ -3908,6 +3866,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
"expander event\n", ioc->name));
return;
}
+ if (ioc->shost_recovery)
+ return;
if (event_data->PHY[i].PhyStatus &
MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
continue;
@@ -3942,10 +3902,6 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
link_rate_);
}
}
- if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
- if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5)
- _scsih_ublock_io_device(ioc, handle);
- }
if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) {
if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5)
break;
@@ -5156,22 +5112,9 @@ static void
_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
{
struct _sas_device *sas_device, *sas_device_next;
- struct _sas_node *sas_expander, *sas_expander_next;
+ struct _sas_node *sas_expander;
struct _raid_device *raid_device, *raid_device_next;
- unsigned long flags;
-
- _scsih_search_responding_sas_devices(ioc);
- _scsih_search_responding_raid_devices(ioc);
- _scsih_search_responding_expanders(ioc);
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- ioc->shost_recovery = 0;
- if (ioc->shost->shost_state == SHOST_RECOVERY) {
- printk(MPT2SAS_INFO_FMT "putting controller into "
- "SHOST_RUNNING\n", ioc->name);
- scsi_host_set_state(ioc->shost, SHOST_RUNNING);
- }
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
@@ -5207,16 +5150,63 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
_scsih_raid_device_remove(ioc, raid_device);
}
- list_for_each_entry_safe(sas_expander, sas_expander_next,
- &ioc->sas_expander_list, list) {
+ retry_expander_search:
+ sas_expander = NULL;
+ list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
if (sas_expander->responding) {
sas_expander->responding = 0;
continue;
}
- printk("\tremoving expander: handle(0x%04x), "
- " sas_addr(0x%016llx)\n", sas_expander->handle,
- (unsigned long long)sas_expander->sas_address);
_scsih_expander_remove(ioc, sas_expander->handle);
+ goto retry_expander_search;
+ }
+}
+
+/**
+ * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
+ * MPT2_IOC_DONE_RESET
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
+{
+ switch (reset_phase) {
+ case MPT2_IOC_PRE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+ _scsih_fw_event_off(ioc);
+ break;
+ case MPT2_IOC_AFTER_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
+ if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
+ ioc->tm_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
+ complete(&ioc->tm_cmds.done);
+ }
+ _scsih_fw_event_on(ioc);
+ _scsih_flush_running_cmds(ioc);
+ break;
+ case MPT2_IOC_DONE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+ _scsih_sas_host_refresh(ioc, 0);
+ _scsih_search_responding_sas_devices(ioc);
+ _scsih_search_responding_raid_devices(ioc);
+ _scsih_search_responding_expanders(ioc);
+ break;
+ case MPT2_IOC_RUNNING:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_RUNNING\n", ioc->name, __func__));
+ _scsih_remove_unresponding_devices(ioc);
+ break;
}
}
@@ -5236,14 +5226,6 @@ _firmware_event_work(struct work_struct *work)
unsigned long flags;
struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
- /* This is invoked by calling _scsih_queue_rescan(). */
- if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
- _scsih_fw_event_free(ioc, fw_event);
- _scsih_sas_host_refresh(ioc, 1);
- _scsih_remove_unresponding_devices(ioc);
- return;
- }
-
/* the queue is being flushed so ignore this event */
spin_lock_irqsave(&ioc->fw_event_lock, flags);
if (ioc->fw_events_off || ioc->remove_host) {
@@ -5253,13 +5235,10 @@ _firmware_event_work(struct work_struct *work)
}
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
if (ioc->shost_recovery) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
_scsih_fw_event_requeue(ioc, fw_event, 1000);
return;
}
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
switch (fw_event->event) {
case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
@@ -5461,6 +5440,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
if (!sas_device)
continue;
_scsih_remove_device(ioc, sas_device->handle);
+ if (ioc->shost_recovery)
+ return;
goto retry_device_search;
}
}
@@ -5482,6 +5463,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
if (!expander_sibling)
continue;
_scsih_expander_remove(ioc, expander_sibling->handle);
+ if (ioc->shost_recovery)
+ return;
goto retry_expander_search;
}
}
@@ -5513,6 +5496,8 @@ _scsih_remove(struct pci_dev *pdev)
struct _sas_port *mpt2sas_port;
struct _sas_device *sas_device;
struct _sas_node *expander_sibling;
+ struct _raid_device *raid_device, *next;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
struct workqueue_struct *wq;
unsigned long flags;
@@ -5526,6 +5511,21 @@ _scsih_remove(struct pci_dev *pdev)
if (wq)
destroy_workqueue(wq);
+ /* release all the volumes */
+ list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
+ list) {
+ if (raid_device->starget) {
+ sas_target_priv_data =
+ raid_device->starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ scsi_remove_target(&raid_device->starget->dev);
+ }
+ printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
+ "(0x%016llx)\n", ioc->name, raid_device->handle,
+ (unsigned long long) raid_device->wwid);
+ _scsih_raid_device_remove(ioc, raid_device);
+ }
+
/* free ports attached to the sas_host */
retry_again:
list_for_each_entry(mpt2sas_port,
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index 686695b155c7..a53086d0381a 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -140,11 +140,18 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
u32 device_info;
u32 ioc_status;
+ if (ioc->shost_recovery) {
+ printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+ __func__, ioc->name);
+ return -EFAULT;
+ }
+
if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+
ioc->name, __FILE__, __LINE__, __func__);
- return -1;
+ return -ENXIO;
}
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
@@ -153,7 +160,7 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
"\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
__FILE__, __LINE__, __func__);
- return -1;
+ return -EIO;
}
memset(identify, 0, sizeof(identify));
@@ -288,21 +295,17 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
void *psge;
u32 sgl_flags;
u8 issue_reset = 0;
- unsigned long flags;
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
u64 *sas_address_le;
u16 wait_state_count;
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->ioc_reset_in_progress) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->shost_recovery) {
printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
__func__, ioc->name);
return -EFAULT;
}
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
mutex_lock(&ioc->transport_cmds.mutex);
@@ -806,6 +809,12 @@ mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc,
struct _sas_node *sas_node;
struct _sas_phy *mpt2sas_phy;
+ if (ioc->shost_recovery) {
+ printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+ __func__, ioc->name);
+ return;
+ }
+
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_node = _transport_sas_node_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
@@ -1025,7 +1034,6 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
void *psge;
u32 sgl_flags;
u8 issue_reset = 0;
- unsigned long flags;
dma_addr_t dma_addr_in = 0;
dma_addr_t dma_addr_out = 0;
u16 wait_state_count;
@@ -1045,14 +1053,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
return -EINVAL;
}
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->ioc_reset_in_progress) {
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->shost_recovery) {
printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
__func__, ioc->name);
return -EFAULT;
}
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
if (rc)
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 0f8796201504..67e016d29f96 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1654,7 +1654,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
}
- if (scsi_add_host(vha->host, &fc_vport->dev)) {
+ if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
+ &ha->pdev->dev)) {
DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
vha->host_no, vha->vp_idx));
goto vport_create_failed_2;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2de5f3ad640b..69397bb964a4 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -241,10 +241,7 @@ scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
*/
struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
{
- struct scsi_cmnd *cmd;
- unsigned char *buf;
-
- cmd = scsi_host_alloc_command(shost, gfp_mask);
+ struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask);
if (unlikely(!cmd)) {
unsigned long flags;
@@ -258,9 +255,15 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
spin_unlock_irqrestore(&shost->free_list_lock, flags);
if (cmd) {
+ void *buf, *prot;
+
buf = cmd->sense_buffer;
+ prot = cmd->prot_sdb;
+
memset(cmd, 0, sizeof(*cmd));
+
cmd->sense_buffer = buf;
+ cmd->prot_sdb = prot;
}
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index a1689353d7fd..c253e9c051b2 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -721,6 +721,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
case NEEDS_RETRY:
case FAILED:
break;
+ case ADD_TO_MLQUEUE:
+ rtn = NEEDS_RETRY;
+ break;
default:
rtn = FAILED;
break;
diff --git a/drivers/scsi/scsi_lib_dma.c b/drivers/scsi/scsi_lib_dma.c
index ac6855cd2657..dcd128583b89 100644
--- a/drivers/scsi/scsi_lib_dma.c
+++ b/drivers/scsi/scsi_lib_dma.c
@@ -23,7 +23,7 @@ int scsi_dma_map(struct scsi_cmnd *cmd)
int nseg = 0;
if (scsi_sg_count(cmd)) {
- struct device *dev = cmd->device->host->shost_gendev.parent;
+ struct device *dev = cmd->device->host->dma_dev;
nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
cmd->sc_data_direction);
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(scsi_dma_map);
void scsi_dma_unmap(struct scsi_cmnd *cmd)
{
if (scsi_sg_count(cmd)) {
- struct device *dev = cmd->device->host->shost_gendev.parent;
+ struct device *dev = cmd->device->host->dma_dev;
dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
cmd->sc_data_direction);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 292c02f810d0..7c3264ed146d 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -648,11 +648,22 @@ static __init int fc_transport_init(void)
return error;
error = transport_class_register(&fc_vport_class);
if (error)
- return error;
+ goto unreg_host_class;
error = transport_class_register(&fc_rport_class);
if (error)
- return error;
- return transport_class_register(&fc_transport_class);
+ goto unreg_vport_class;
+ error = transport_class_register(&fc_transport_class);
+ if (error)
+ goto unreg_rport_class;
+ return 0;
+
+unreg_rport_class:
+ transport_class_unregister(&fc_rport_class);
+unreg_vport_class:
+ transport_class_unregister(&fc_vport_class);
+unreg_host_class:
+ transport_class_unregister(&fc_host_class);
+ return error;
}
static void __exit fc_transport_exit(void)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b7b9fec67a98..a89c421dab51 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2021,6 +2021,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : "");
+ put_device(&sdkp->dev);
}
/**
@@ -2106,6 +2107,7 @@ static int sd_probe(struct device *dev)
get_device(&sdp->sdev_gendev);
+ get_device(&sdkp->dev); /* prevent release before async_schedule */
async_schedule(sd_probe_async, sdkp);
return 0;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9230402c45af..dc0e3d4eacc2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1708,11 +1708,6 @@ static int sg_finish_rem_req(Sg_request * srp)
Sg_scatter_hold *req_schp = &srp->data;
SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used));
- if (srp->res_used)
- sg_unlink_reserve(sfp, srp);
- else
- sg_remove_scat(req_schp);
-
if (srp->rq) {
if (srp->bio)
ret = blk_rq_unmap_user(srp->bio);
@@ -1720,6 +1715,11 @@ static int sg_finish_rem_req(Sg_request * srp)
blk_put_request(srp->rq);
}
+ if (srp->res_used)
+ sg_unlink_reserve(sfp, srp);
+ else
+ sg_remove_scat(req_schp);
+
sg_remove_request(sfp, srp);
return ret;
@@ -1811,7 +1811,7 @@ retry:
return 0;
out:
for (i = 0; i < k; i++)
- __free_pages(schp->pages[k], order);
+ __free_pages(schp->pages[i], order);
if (--order >= 0)
goto retry;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d5da26f34cee..ecbf0dac375a 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -81,6 +81,9 @@ static int serial_index(struct uart_port *port)
#define PASS_LIMIT 256
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+
/*
* We default to IRQ0 for the "no irq" hack. Some
* machine types want others as well - they're free
@@ -1342,14 +1345,12 @@ static void serial8250_start_tx(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
if (up->bugs & UART_BUG_TXEN) {
- unsigned char lsr, iir;
+ unsigned char lsr;
lsr = serial_in(up, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- iir = serial_in(up, UART_IIR) & 0x0f;
if ((up->port.type == PORT_RM9000) ?
- (lsr & UART_LSR_THRE &&
- (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
- (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
+ (lsr & UART_LSR_THRE) :
+ (lsr & UART_LSR_TEMT))
transmit_chars(up);
}
}
@@ -1802,7 +1803,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&up->port.lock, flags);
- return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+ return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
}
static unsigned int serial8250_get_mctrl(struct uart_port *port)
@@ -1860,8 +1861,6 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&up->port.lock, flags);
}
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
/*
* Wait for transmitter & holding register to empty
*/
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index e7108e75653d..7b5ff096c2db 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1561,6 +1561,7 @@ enum pci_board_num_t {
pbn_exar_XR17C152,
pbn_exar_XR17C154,
pbn_exar_XR17C158,
+ pbn_exar_ibm_saturn,
pbn_pasemi_1682M,
pbn_ni8430_2,
pbn_ni8430_4,
@@ -2146,6 +2147,13 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 0x200,
},
+ [pbn_exar_ibm_saturn] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 0x200,
+ },
+
/*
* PA Semi PWRficient PA6T-1682M on-chip UART
*/
@@ -2649,6 +2657,9 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
+ 0, 0, pbn_exar_ibm_saturn },
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index d71dfe398940..9fb71903c107 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_dev_table[] = {
/* U.S. Robotics 56K Voice INT PnP*/
{ "USR9190", 0 },
/* Wacom tablets */
- { "WACF004", 0 },
- { "WACF005", 0 },
- { "WACF006", 0 },
- { "WACF007", 0 },
- { "WACF008", 0 },
- { "WACF009", 0 },
- { "WACF00A", 0 },
- { "WACF00B", 0 },
- { "WACF00C", 0 },
+ { "WACFXXX", 0 },
/* Compaq touchscreen */
{ "FPI2002", 0 },
/* Fujitsu Stylistic touchscreens */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b41db4d22436..869337a7fd68 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -373,24 +373,6 @@ config SERIAL_MXS_AUART
help
Driver for Freescale i.MXS internal application serial port
-config SERIAL_MXS_AUART_CONSOLE
- bool "Support for console on i.MXS application serial port"
- depends on SERIAL_MXS_AUART=y
- select SERIAL_CORE_CONSOLE
- ---help---
- Say Y here if you wish to use the i.MXS app serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode).
-
- Even if you say Y here, the currently visible framebuffer console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttySP1". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-
config SERIAL_MXS_DUART_CONSOLE
bool "Support for console on i.MXS debug serial port"
depends on SERIAL_MXS_DUART=y
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index b4a7650af696..4fff4e524034 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -42,6 +42,10 @@
# undef CONFIG_EARLY_PRINTK
#endif
+#ifdef CONFIG_SERIAL_BFIN_MODULE
+# undef CONFIG_EARLY_PRINTK
+#endif
+
/* UART name and device definitions */
#define BFIN_SERIAL_NAME "ttyBF"
#define BFIN_SERIAL_MAJOR 204
diff --git a/drivers/serial/mxs-auart.c b/drivers/serial/mxs-auart.c
index 63d7d9128efc..0791af105f72 100644
--- a/drivers/serial/mxs-auart.c
+++ b/drivers/serial/mxs-auart.c
@@ -19,7 +19,6 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -48,8 +47,6 @@
#define MXS_AUART_MAJOR 242
#define MXS_AUART_RX_THRESHOLD 16
-static struct uart_driver auart_driver;
-
struct mxs_auart_port {
struct uart_port port;
@@ -788,160 +785,7 @@ static struct uart_ops mxs_auart_ops = {
.config_port = mxs_auart_config_port,
.verify_port = mxs_auart_verify_port,
};
-#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
-static struct mxs_auart_port auart_port[CONFIG_MXS_AUART_PORTS] = {};
-
-static void
-auart_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_port *port;
- unsigned int status, old_cr;
- int i;
-
- if (co->index > CONFIG_MXS_AUART_PORTS || co->index < 0)
- return;
- port = &auart_port[co->index].port;
-
- /* First save the CR then disable the interrupts */
- old_cr = __raw_readl(port->membase + HW_UARTAPP_CTRL2);
- __raw_writel(BM_UARTAPP_CTRL2_UARTEN | BM_UARTAPP_CTRL2_TXE,
- port->membase + HW_UARTAPP_CTRL2_SET);
-
- /* Now, do each character */
- for (i = 0; i < count; i++) {
- do {
- status = __raw_readl(port->membase + HW_UARTAPP_STAT);
- } while (status & BM_UARTAPP_STAT_TXFF);
-
- __raw_writel(s[i], port->membase + HW_UARTAPP_DATA);
- if (s[i] == '\n') {
- do {
- status = __raw_readl(port->membase +
- HW_UARTAPP_STAT);
- } while (status & BM_UARTAPP_STAT_TXFF);
- __raw_writel('\r', port->membase + HW_UARTAPP_DATA);
- }
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the TCR
- */
- do {
- status = __raw_readl(port->membase + HW_UARTAPP_STAT);
- } while (status & BM_UARTAPP_STAT_BUSY);
- __raw_writel(old_cr, port->membase + HW_UARTAPP_CTRL2);
-}
-
-static void __init
-auart_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- if (__raw_readl(port->membase + HW_UARTAPP_CTRL2)
- & BM_UARTAPP_CTRL2_UARTEN) {
- unsigned int lcr_h, quot;
- lcr_h = __raw_readl(port->membase + HW_UARTAPP_LINECTRL);
-
- *parity = 'n';
- if (lcr_h & BM_UARTAPP_LINECTRL_PEN) {
- if (lcr_h & BM_UARTAPP_LINECTRL_EPS)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- if ((lcr_h & BM_UARTAPP_LINECTRL_WLEN)
- == BF_UARTAPP_LINECTRL_WLEN(2))
- *bits = 7;
- else
- *bits = 8;
-
- quot = (((__raw_readl(port->membase + HW_UARTAPP_LINECTRL)
- & BM_UARTAPP_LINECTRL_BAUD_DIVINT))
- >> (BP_UARTAPP_LINECTRL_BAUD_DIVINT - 6))
- | (((__raw_readl(port->membase + HW_UARTAPP_LINECTRL)
- & BM_UARTAPP_LINECTRL_BAUD_DIVFRAC))
- >> BP_UARTAPP_LINECTRL_BAUD_DIVFRAC);
- if (quot == 0)
- quot = 1;
- *baud = (port->uartclk << 2) / quot;
- }
-}
-
-static int __init auart_console_setup(struct console *co, char *options)
-{
- struct mxs_auart_port *port;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index > CONFIG_MXS_AUART_PORTS || co->index < 0)
- return -EINVAL;
-
- port = &auart_port[co->index].port;
-
- if (port->port.membase == 0) {
- if (cpu_is_mx23()) {
- if (co->index == 1) {
- port->port.membase = IO_ADDRESS(0x8006C000);
- port->port.mapbase = 0x8006C000;
- } else {
- port->port.membase = IO_ADDRESS(0x8006E000);
- port->port.mapbase = 0x8006E000;
- }
- }
-
- port->port.fifosize = 16;
- port->port.ops = &mxs_auart_ops;
- port->port.flags = ASYNC_BOOT_AUTOCONF;
- port->port.line = 0;
- }
- mxs_auart_reset(port);
-
- __raw_writel(BM_UARTAPP_CTRL2_UARTEN,
- port->port.membase + HW_UARTAPP_CTRL2_SET);
-
- if (port->clk == NULL || IS_ERR(port->clk)) {
- port->clk = clk_get(NULL, "uart");
- if (port->clk == NULL || IS_ERR(port->clk))
- return -ENODEV;
- port->port.uartclk = clk_get_rate(port->clk);
- }
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- auart_console_get_options(port, &baud, &parity, &bits);
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct console auart_console = {
- .name = "ttySP",
- .write = auart_console_write,
- .device = uart_console_device,
- .setup = auart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &auart_driver,
-};
-
-#ifdef CONFIG_MXS_EARLY_CONSOLE
-static int __init auart_console_init(void)
-{
- register_console(&auart_console);
- return 0;
-}
-
-console_initcall(auart_console_init);
-#endif
-
-#endif
static struct uart_driver auart_driver = {
.owner = THIS_MODULE,
.driver_name = "auart",
@@ -949,9 +793,6 @@ static struct uart_driver auart_driver = {
.major = MXS_AUART_MAJOR,
.minor = 0,
.nr = CONFIG_MXS_AUART_PORTS,
-#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
- .cons = &auart_console,
-#endif
};
static int __devinit mxs_auart_probe(struct platform_device *pdev)
@@ -1032,10 +873,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
-#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
- memcpy(&auart_port[pdev->id], s, sizeof(struct mxs_auart_port));
-#endif
-
ret = uart_add_one_port(&auart_driver, &s->port);
if (ret)
goto out_free_clk;
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
index 02406ba6da1c..cdf172eda2e3 100644
--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -161,6 +161,7 @@ static int of_platform_serial_remove(struct of_device *ofdev)
static struct of_device_id __devinitdata of_platform_serial_table[] = {
{ .type = "serial", .compatible = "ns8250", .data = (void *)PORT_8250, },
{ .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, },
+ { .type = "serial", .compatible = "ns16550a", .data = (void *)PORT_16550A, },
{ .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, },
{ .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, },
{ .type = "serial", .compatible = "ns16850", .data = (void *)PORT_16850, },
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 79c9c5f5cdba..6ecb51baf56e 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -884,6 +884,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index a2d4a19550ab..ed7d958b0a01 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -53,20 +53,21 @@ void sunserial_unregister_minors(struct uart_driver *drv, int count)
EXPORT_SYMBOL(sunserial_unregister_minors);
int sunserial_console_match(struct console *con, struct device_node *dp,
- struct uart_driver *drv, int line)
+ struct uart_driver *drv, int line, bool ignore_line)
{
- int off;
-
if (!con || of_console_device != dp)
return 0;
- off = 0;
- if (of_console_options &&
- *of_console_options == 'b')
- off = 1;
+ if (!ignore_line) {
+ int off = 0;
- if ((line & 1) != off)
- return 0;
+ if (of_console_options &&
+ *of_console_options == 'b')
+ off = 1;
+
+ if ((line & 1) != off)
+ return 0;
+ }
con->index = line;
drv->cons = con;
@@ -76,23 +77,24 @@ int sunserial_console_match(struct console *con, struct device_node *dp,
}
EXPORT_SYMBOL(sunserial_console_match);
-void
-sunserial_console_termios(struct console *con)
+void sunserial_console_termios(struct console *con, struct device_node *uart_dp)
{
- struct device_node *dp;
- const char *od, *mode, *s;
+ const char *mode, *s;
char mode_prop[] = "ttyX-mode";
int baud, bits, stop, cflag;
char parity;
- dp = of_find_node_by_path("/options");
- od = of_get_property(dp, "output-device", NULL);
- if (!strcmp(od, "rsc")) {
- mode = of_get_property(of_console_device,
+ if (!strcmp(uart_dp->name, "rsc") ||
+ !strcmp(uart_dp->name, "rsc-console") ||
+ !strcmp(uart_dp->name, "rsc-control")) {
+ mode = of_get_property(uart_dp,
"ssp-console-modes", NULL);
if (!mode)
mode = "115200,8,n,1,-";
+ } else if (!strcmp(uart_dp->name, "lom-console")) {
+ mode = "9600,8,n,1,-";
} else {
+ struct device_node *dp;
char c;
c = 'a';
@@ -101,6 +103,7 @@ sunserial_console_termios(struct console *con)
mode_prop[3] = c;
+ dp = of_find_node_by_path("/options");
mode = of_get_property(dp, mode_prop, NULL);
if (!mode)
mode = "9600,8,n,1,-";
diff --git a/drivers/serial/suncore.h b/drivers/serial/suncore.h
index 042668aa602e..db2057936c31 100644
--- a/drivers/serial/suncore.h
+++ b/drivers/serial/suncore.h
@@ -26,7 +26,8 @@ extern int sunserial_register_minors(struct uart_driver *, int);
extern void sunserial_unregister_minors(struct uart_driver *, int);
extern int sunserial_console_match(struct console *, struct device_node *,
- struct uart_driver *, int);
-extern void sunserial_console_termios(struct console *);
+ struct uart_driver *, int, bool);
+extern void sunserial_console_termios(struct console *,
+ struct device_node *);
#endif /* !(_SERIAL_SUN_H) */
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 1df5325faab2..3b6953aa5d03 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -566,7 +566,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
goto out_free_con_read_page;
sunserial_console_match(&sunhv_console, op->node,
- &sunhv_reg, port->line);
+ &sunhv_reg, port->line, false);
err = uart_add_one_port(&sunhv_reg, port);
if (err)
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 0355efe115d9..9cbf597e0ab8 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -883,7 +883,7 @@ static int sunsab_console_setup(struct console *con, char *options)
printk("Console: ttyS%d (SAB82532)\n",
(sunsab_reg.minor - 64) + con->index);
- sunserial_console_termios(con);
+ sunserial_console_termios(con, to_of_device(up->port.dev)->node);
switch (con->cflag & CBAUD) {
case B150: baud = 150; break;
@@ -1027,10 +1027,12 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
goto out1;
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
- &sunsab_reg, up[0].port.line);
+ &sunsab_reg, up[0].port.line,
+ false);
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
- &sunsab_reg, up[1].port.line);
+ &sunsab_reg, up[1].port.line,
+ false);
err = uart_add_one_port(&sunsab_reg, &up[0].port);
if (err)
@@ -1116,7 +1118,6 @@ static int __init sunsab_init(void)
if (!sunsab_ports)
return -ENOMEM;
- sunsab_reg.cons = SUNSAB_CONSOLE();
err = sunserial_register_minors(&sunsab_reg, num_channels);
if (err) {
kfree(sunsab_ports);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 47c6837850b1..ab91166b1b16 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1329,11 +1329,9 @@ static void sunsu_console_write(struct console *co, const char *s,
*/
static int __init sunsu_console_setup(struct console *co, char *options)
{
+ static struct ktermios dummy;
+ struct ktermios termios;
struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
printk("Console: ttyS%d (SU)\n",
(sunsu_reg.minor - 64) + co->index);
@@ -1352,10 +1350,15 @@ static int __init sunsu_console_setup(struct console *co, char *options)
*/
spin_lock_init(&port->lock);
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
+ /* Get firmware console settings. */
+ sunserial_console_termios(co, to_of_device(port->dev)->node);
- return uart_set_options(port, co, baud, parity, bits, flow);
+ memset(&termios, 0, sizeof(struct ktermios));
+ termios.c_cflag = co->cflag;
+ port->mctrl |= TIOCM_DTR;
+ port->ops->set_termios(port, &termios, &dummy);
+
+ return 0;
}
static struct console sunsu_console = {
@@ -1409,6 +1412,7 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
struct uart_sunsu_port *up;
struct resource *rp;
enum su_type type;
+ bool ignore_line;
int err;
type = su_get_type(dp);
@@ -1467,8 +1471,14 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
up->port.ops = &sunsu_pops;
+ ignore_line = false;
+ if (!strcmp(dp->name, "rsc-console") ||
+ !strcmp(dp->name, "lom-console"))
+ ignore_line = true;
+
sunserial_console_match(SUNSU_CONSOLE(), dp,
- &sunsu_reg, up->port.line);
+ &sunsu_reg, up->port.line,
+ ignore_line);
err = uart_add_one_port(&sunsu_reg, &up->port);
if (err)
goto out_unmap;
@@ -1517,6 +1527,10 @@ static const struct of_device_id su_match[] = {
.name = "serial",
.compatible = "su",
},
+ {
+ .type = "serial",
+ .compatible = "su",
+ },
{},
};
MODULE_DEVICE_TABLE(of, su_match);
@@ -1548,6 +1562,12 @@ static int __init sunsu_init(void)
num_uart++;
}
}
+ for_each_node_by_type(dp, "serial") {
+ if (of_device_is_compatible(dp, "su")) {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
+ }
+ }
if (num_uart) {
err = sunserial_register_minors(&sunsu_reg, num_uart);
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index e09d3cebb4fb..0a2a3335f30f 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1180,7 +1180,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
(sunzilog_reg.minor - 64) + con->index, con->index);
/* Get firmware console settings. */
- sunserial_console_termios(con);
+ sunserial_console_termios(con, to_of_device(up->port.dev)->node);
/* Firmware console speed is limited to 150-->38400 baud so
* this hackish cflag thing is OK.
@@ -1416,7 +1416,8 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
if (!keyboard_mouse) {
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
- &sunzilog_reg, up[0].port.line))
+ &sunzilog_reg, up[0].port.line,
+ false))
up->flags |= SUNZILOG_FLAG_IS_CONS;
err = uart_add_one_port(&sunzilog_reg, &up[0].port);
if (err) {
@@ -1425,7 +1426,8 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
return err;
}
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
- &sunzilog_reg, up[1].port.line))
+ &sunzilog_reg, up[1].port.line,
+ false))
up->flags |= SUNZILOG_FLAG_IS_CONS;
err = uart_add_one_port(&sunzilog_reg, &up[1].port);
if (err) {
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 8943015a3eef..eb708431cb96 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -13,6 +13,8 @@
#include "ssb_private.h"
+#include <linux/ctype.h>
+
static const struct ssb_sprom *fallback_sprom;
@@ -33,17 +35,27 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
static int hex2sprom(u16 *sprom, const char *dump, size_t len,
size_t sprom_size_words)
{
- char tmp[5] = { 0 };
- int cnt = 0;
+ char c, tmp[5] = { 0 };
+ int err, cnt = 0;
unsigned long parsed;
- if (len < sprom_size_words * 2)
+ /* Strip whitespace at the end. */
+ while (len) {
+ c = dump[len - 1];
+ if (!isspace(c) && c != '\0')
+ break;
+ len--;
+ }
+ /* Length must match exactly. */
+ if (len != sprom_size_words * 4)
return -EINVAL;
while (cnt < sprom_size_words) {
memcpy(tmp, dump, 4);
dump += 4;
- parsed = simple_strtoul(tmp, NULL, 16);
+ err = strict_strtoul(tmp, 16, &parsed);
+ if (err)
+ return err;
sprom[cnt++] = swab16((u16)parsed);
}
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index da7c984b5641..17d89a8124ad 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -43,7 +43,6 @@ static struct proc_dir_entry *binder_proc_dir_entry_proc;
static struct hlist_head binder_dead_nodes;
static HLIST_HEAD(binder_deferred_list);
static DEFINE_MUTEX(binder_deferred_lock);
-static struct workqueue_struct *binder_deferred_workqueue;
static int binder_read_proc_proc(char *page, char **start, off_t off,
int count, int *eof, void *data);
@@ -2987,7 +2986,6 @@ static void binder_deferred_release(struct binder_proc *proc)
int i;
for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
if (proc->pages[i]) {
- void *page_addr = proc->buffer + i * PAGE_SIZE;
if (binder_debug_mask &
BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_INFO
@@ -2995,8 +2993,6 @@ static void binder_deferred_release(struct binder_proc *proc)
"page %d at %p not freed\n",
proc->pid, i,
proc->buffer + i * PAGE_SIZE);
- unmap_kernel_range((unsigned long)page_addr,
- PAGE_SIZE);
__free_page(proc->pages[i]);
page_count++;
}
@@ -3066,7 +3062,7 @@ static void binder_defer_work(struct binder_proc *proc, int defer)
if (hlist_unhashed(&proc->deferred_work_node)) {
hlist_add_head(&proc->deferred_work_node,
&binder_deferred_list);
- queue_work(binder_deferred_workqueue, &binder_deferred_work);
+ schedule_work(&binder_deferred_work);
}
mutex_unlock(&binder_deferred_lock);
}
@@ -3694,10 +3690,6 @@ static int __init binder_init(void)
{
int ret;
- binder_deferred_workqueue = create_singlethread_workqueue("binder");
- if (!binder_deferred_workqueue)
- return -ENOMEM;
-
binder_proc_dir_entry_root = proc_mkdir("binder", NULL);
if (binder_proc_dir_entry_root)
binder_proc_dir_entry_proc = proc_mkdir("proc",
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index 7f64f8fb26b0..6c10b456c6cc 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -556,7 +556,6 @@ static struct logger_log VAR = { \
DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)
-DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 64*1024)
static struct logger_log *get_log_from_minor(int minor)
{
@@ -566,8 +565,6 @@ static struct logger_log *get_log_from_minor(int minor)
return &log_events;
if (log_radio.misc.minor == minor)
return &log_radio;
- if (log_system.misc.minor == minor)
- return &log_system;
return NULL;
}
@@ -604,10 +601,6 @@ static int __init logger_init(void)
if (unlikely(ret))
goto out;
- ret = init_log(&log_system);
- if (unlikely(ret))
- goto out;
-
out:
return ret;
}
diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h
index 2cb06e9d8f98..a562434d7419 100644
--- a/drivers/staging/android/logger.h
+++ b/drivers/staging/android/logger.h
@@ -32,7 +32,6 @@ struct logger_entry {
#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
-#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */
#define LOGGER_LOG_MAIN "log_main" /* everything else */
#define LOGGER_ENTRY_MAX_LEN (4*1024)
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 572dc062759a..ae41f79d995d 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -20,7 +20,6 @@
#include <linux/sched.h>
#include <linux/nodemask.h>
#include <linux/vmstat.h>
-#include <linux/notifier.h>
static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask);
@@ -44,8 +43,6 @@ static size_t lowmem_minfree[6] = {
};
static int lowmem_minfree_size = 4;
-static struct task_struct *lowmem_deathpending;
-
#define lowmem_print(level, x...) \
do { \
if (lowmem_debug_level >= (level)) \
@@ -59,24 +56,6 @@ module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
S_IRUGO | S_IWUSR);
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data);
-
-static struct notifier_block task_nb = {
- .notifier_call = task_notify_func,
-};
-
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data)
-{
- struct task_struct *task = data;
- if (task == lowmem_deathpending) {
- lowmem_deathpending = NULL;
- task_free_unregister(&task_nb);
- }
- return NOTIFY_OK;
-}
-
static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
{
struct task_struct *p;
@@ -92,15 +71,6 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
int other_file = global_page_state(NR_FILE_PAGES);
int node;
- /*
- * If we already have a death outstanding, then
- * bail out right away; indicating to vmscan
- * that we have nothing further to offer on
- * this pass.
- */
- if (lowmem_deathpending)
- return 0;
-
for_each_node_state(node, N_HIGH_MEMORY) {
struct zone *z =
&NODE_DATA(node)->node_zones[ZONE_DMA];
@@ -169,19 +139,9 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
p->pid, p->comm, oom_adj, tasksize);
}
if (selected) {
- if (fatal_signal_pending(selected)) {
- pr_warning("process %d is suffering a slow death\n",
- selected->pid);
- read_unlock(&tasklist_lock);
- return rem;
- }
lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
selected->pid, selected->comm,
selected_oom_adj, selected_tasksize);
-
- lowmem_deathpending = selected;
- task_free_register(&task_nb);
-
force_sig(SIGKILL, selected);
rem -= selected_tasksize;
}
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
index fad25b753042..5546898dbdb4 100644
--- a/drivers/staging/dst/dcore.c
+++ b/drivers/staging/dst/dcore.c
@@ -846,15 +846,19 @@ static dst_command_func dst_commands[] = {
/*
* Configuration parser.
*/
-static void cn_dst_callback(void *data)
+static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct dst_ctl *ctl;
- struct cn_msg *msg = data;
int err;
struct dst_ctl_ack ack;
struct dst_node *n = NULL, *tmp;
unsigned int hash;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
+
if (msg->len < sizeof(struct dst_ctl)) {
err = -EBADMSG;
goto out;
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
index a6eaa42fb669..d8ec47a6ee06 100644
--- a/drivers/staging/pohmelfs/config.c
+++ b/drivers/staging/pohmelfs/config.c
@@ -446,11 +446,13 @@ out_unlock:
return err;
}
-static void pohmelfs_cn_callback(void *data)
+static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
- struct cn_msg *msg = data;
int err;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
switch (msg->flags) {
case POHMELFS_FLAGS_ADD:
case POHMELFS_FLAGS_DEL:
diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c
index fb1735533b74..857ff450b6c9 100644
--- a/drivers/staging/rt2860/common/cmm_data_2860.c
+++ b/drivers/staging/rt2860/common/cmm_data_2860.c
@@ -363,6 +363,8 @@ int RtmpPCIMgmtKickOut(
ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
+ if (!pTxD)
+ return 0;
pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 31fcd3270b26..3f06818cf9fa 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -157,12 +157,6 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
struct uio_pdrv_genirq_platdata *priv = platform_get_drvdata(pdev);
uio_unregister_device(priv->uioinfo);
-
- priv->uioinfo->irq_flags = 0;
- priv->uioinfo->handler = NULL;
- priv->uioinfo->irqcontrol = NULL;
- priv->uioinfo->priv = NULL;
-
kfree(priv);
return 0;
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b8134ad5f05f..b72fa49eb257 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -609,9 +609,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
acm->throttle = 0;
- tasklet_schedule(&acm->urb_task);
set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
rv = tty_port_block_til_ready(&acm->port, tty, filp);
+ tasklet_schedule(&acm->urb_task);
done:
mutex_unlock(&acm->mutex);
err_out:
@@ -860,10 +860,7 @@ static void acm_tty_set_termios(struct tty_struct *tty,
if (!ACM_READY(acm))
return;
- /* FIXME: Needs to support the tty_baud interface */
- /* FIXME: Broken on sparc */
- newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
- (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
+ newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty));
newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
newline.bParityType = termios->c_cflag & PARENB ?
(termios->c_cflag & PARODD ? 1 : 2) +
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index ba589d4ca8bc..a9c33994459b 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -313,8 +313,13 @@ static ssize_t wdm_write
r = usb_autopm_get_interface(desc->intf);
if (r < 0)
goto outnp;
- r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
- &desc->flags));
+
+ if (!file->f_flags && O_NONBLOCK)
+ r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
+ &desc->flags));
+ else
+ if (test_bit(WDM_IN_USE, &desc->flags))
+ r = -EAGAIN;
if (r < 0)
goto out;
@@ -377,7 +382,7 @@ outnl:
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- int rv, cntr;
+ int rv, cntr = 0;
int i = 0;
struct wdm_device *desc = file->private_data;
@@ -389,10 +394,23 @@ static ssize_t wdm_read
if (desc->length == 0) {
desc->read = 0;
retry:
+ if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
+ rv = -ENODEV;
+ goto err;
+ }
i++;
- rv = wait_event_interruptible(desc->wait,
- test_bit(WDM_READ, &desc->flags));
+ if (file->f_flags & O_NONBLOCK) {
+ if (!test_bit(WDM_READ, &desc->flags)) {
+ rv = cntr ? cntr : -EAGAIN;
+ goto err;
+ }
+ rv = 0;
+ } else {
+ rv = wait_event_interruptible(desc->wait,
+ test_bit(WDM_READ, &desc->flags));
+ }
+ /* may have happened while we slept */
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
rv = -ENODEV;
goto err;
@@ -448,7 +466,7 @@ retry:
err:
mutex_unlock(&desc->rlock);
- if (rv < 0)
+ if (rv < 0 && rv != -EAGAIN)
dev_err(&desc->intf->dev, "wdm_read: exit error\n");
return rv;
}
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index b09a527f7341..aa145f7b4e25 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -367,13 +367,13 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
{
struct usbtmc_device_data *data;
struct device *dev;
- unsigned long int n_characters;
+ u32 n_characters;
u8 *buffer;
int actual;
- int done;
- int remaining;
+ size_t done;
+ size_t remaining;
int retval;
- int this_part;
+ size_t this_part;
/* Get pointer to private data structure */
data = filp->private_data;
@@ -455,6 +455,18 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
(buffer[6] << 16) +
(buffer[7] << 24);
+ /* Ensure the instrument doesn't lie about it */
+ if(n_characters > actual - 12) {
+ dev_err(dev, "Device lies about message size: %zu > %zu\n", n_characters, actual - 12);
+ n_characters = actual - 12;
+ }
+
+ /* Ensure the instrument doesn't send more back than requested */
+ if(n_characters > this_part) {
+ dev_err(dev, "Device returns more than requested: %zu > %zu\n", done + n_characters, done + this_part);
+ n_characters = this_part;
+ }
+
/* Copy buffer to user space */
if (copy_to_user(buf + done, &buffer[12], n_characters)) {
/* There must have been an addressing problem */
@@ -465,6 +477,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
done += n_characters;
if (n_characters < USBTMC_SIZE_IOBUFFER)
remaining = 0;
+ else
+ remaining -= n_characters;
}
/* Update file position value */
@@ -531,10 +545,16 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
n_bytes = roundup(12 + this_part, 4);
memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part));
- retval = usb_bulk_msg(data->usb_dev,
- usb_sndbulkpipe(data->usb_dev,
- data->bulk_out),
- buffer, n_bytes, &actual, USBTMC_TIMEOUT);
+ do {
+ retval = usb_bulk_msg(data->usb_dev,
+ usb_sndbulkpipe(data->usb_dev,
+ data->bulk_out),
+ buffer, n_bytes,
+ &actual, USBTMC_TIMEOUT);
+ if (retval != 0)
+ break;
+ n_bytes -= actual;
+ } while (n_bytes);
data->bTag_last_write = data->bTag;
data->bTag++;
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index a16c538d0132..0d3af6a6ee49 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -105,7 +105,7 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
ep->ss_ep_comp->extralen = i;
buffer += i;
size -= i;
- retval = buffer - buffer_start + i;
+ retval = buffer - buffer_start;
if (num_skipped > 0)
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
num_skipped, plural(num_skipped),
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 96f11715cd26..355dffcc23b0 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
return 0;
/* allocate 2^1 pages = 8K (on i386);
* should be more than enough for one device */
- pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
+ pages_start = (char *)__get_free_pages(GFP_NOIO, 1);
if (!pages_start)
return -ENOMEM;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 4247eccf858c..5ae4099fb4c1 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1139,6 +1139,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
free_async(as);
return -ENOMEM;
}
+ /* Isochronous input data may end up being discontiguous
+ * if some of the packets are short. Clear the buffer so
+ * that the gaps don't leak kernel data to userspace.
+ */
+ if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
+ memset(as->urb->transfer_buffer, 0,
+ uurb->buffer_length);
}
as->urb->dev = ps->dev;
as->urb->pipe = (uurb->type << 30) |
@@ -1240,10 +1247,14 @@ static int processcompl(struct async *as, void __user * __user *arg)
void __user *addr = as->userurb;
unsigned int i;
- if (as->userbuffer)
- if (copy_to_user(as->userbuffer, urb->transfer_buffer,
- urb->transfer_buffer_length))
+ if (as->userbuffer && urb->actual_length) {
+ if (urb->number_of_packets > 0) /* Isochronous */
+ i = urb->transfer_buffer_length;
+ else /* Non-Isoc */
+ i = urb->actual_length;
+ if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
goto err_out;
+ }
if (put_user(as->status, &userurb->status))
goto err_out;
if (put_user(urb->actual_length, &userurb->actual_length))
@@ -1262,14 +1273,11 @@ static int processcompl(struct async *as, void __user * __user *arg)
}
}
- free_async(as);
-
if (put_user(addr, (void __user * __user *)arg))
return -EFAULT;
return 0;
err_out:
- free_async(as);
return -EFAULT;
}
@@ -1299,8 +1307,11 @@ static struct async *reap_as(struct dev_state *ps)
static int proc_reapurb(struct dev_state *ps, void __user *arg)
{
struct async *as = reap_as(ps);
- if (as)
- return processcompl(as, (void __user * __user *)arg);
+ if (as) {
+ int retval = processcompl(as, (void __user * __user *)arg);
+ free_async(as);
+ return retval;
+ }
if (signal_pending(current))
return -EINTR;
return -EIO;
@@ -1308,11 +1319,16 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg)
static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
{
+ int retval;
struct async *as;
- if (!(as = async_getcompleted(ps)))
- return -EAGAIN;
- return processcompl(as, (void __user * __user *)arg);
+ as = async_getcompleted(ps);
+ retval = -EAGAIN;
+ if (as) {
+ retval = processcompl(as, (void __user * __user *)arg);
+ free_async(as);
+ }
+ return retval;
}
#ifdef CONFIG_COMPAT
@@ -1363,9 +1379,9 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
void __user *addr = as->userurb;
unsigned int i;
- if (as->userbuffer)
+ if (as->userbuffer && urb->actual_length)
if (copy_to_user(as->userbuffer, urb->transfer_buffer,
- urb->transfer_buffer_length))
+ urb->actual_length))
return -EFAULT;
if (put_user(as->status, &userurb->status))
return -EFAULT;
@@ -1385,7 +1401,6 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
}
}
- free_async(as);
if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
return -EFAULT;
return 0;
@@ -1394,8 +1409,11 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
{
struct async *as = reap_as(ps);
- if (as)
- return processcompl_compat(as, (void __user * __user *)arg);
+ if (as) {
+ int retval = processcompl_compat(as, (void __user * __user *)arg);
+ free_async(as);
+ return retval;
+ }
if (signal_pending(current))
return -EINTR;
return -EIO;
@@ -1403,11 +1421,16 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
{
+ int retval;
struct async *as;
- if (!(as = async_getcompleted(ps)))
- return -EAGAIN;
- return processcompl_compat(as, (void __user * __user *)arg);
+ retval = -EAGAIN;
+ as = async_getcompleted(ps);
+ if (as) {
+ retval = processcompl_compat(as, (void __user * __user *)arg);
+ free_async(as);
+ }
+ return retval;
}
#endif
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 07f503aa9078..c209dbe4f6c6 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1754,9 +1754,6 @@ int usb_resume(struct device *dev, pm_message_t msg)
udev = to_usb_device(dev);
-/* At otg mode, if it is a device wakeup interrupt, the host should do nothing */
- if (udev->bus->is_b_host)
- return 0;
/* If udev->skip_sys_resume is set then udev was already suspended
* when the system sleep started, so we don't want to resume it
* during this system wakeup.
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 539a2c0dde00..66e8a424c9f4 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -196,6 +196,7 @@ extern void usb_host_set_wakeup(struct device *wkup_dev, bool para);
static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
int rc;
+ u32 temp;
/* Normal USB devices suspend through their upstream port.
* Root hubs don't have upstream ports to suspend,
@@ -203,7 +204,25 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
* interfaces manually by doing a bus (or "global") suspend.
*/
if (!udev->parent) {
+ struct usb_hcd *hcd =
+ container_of(udev->bus, struct usb_hcd, self);
+ struct fsl_usb2_platform_data *pdata;
+ pdata = hcd->self.controller->platform_data;
+
rc = hcd_bus_suspend(udev, msg);
+
+ if (device_may_wakeup(hcd->self.controller)) {
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ /* enable remote wake up irq */
+ usb_host_set_wakeup(hcd->self.controller, true);
+
+ /* Put PHY into low power mode */
+ temp = readl(hcd->regs + 0x184);
+ writel(temp | (1 << 23), (hcd->regs + 0x184));
+
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(false);
+ }
/* Non-root devices don't need to do anything for FREEZE or PRETHAW */
} else if (msg.event == PM_EVENT_FREEZE ||
msg.event == PM_EVENT_PRETHAW)
@@ -217,6 +236,7 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
static int generic_resume(struct usb_device *udev, pm_message_t msg)
{
int rc;
+ u32 temp;
/* Normal USB devices resume/reset through their upstream port.
* Root hubs don't have upstream ports to resume or reset,
@@ -224,6 +244,13 @@ static int generic_resume(struct usb_device *udev, pm_message_t msg)
* interfaces manually by doing a bus (or "global") resume.
*/
if (!udev->parent) {
+ struct usb_hcd *hcd =
+ container_of(udev->bus, struct usb_hcd, self);
+
+ if (device_may_wakeup(hcd->self.controller)) {
+ temp = readl(hcd->regs + 0x184);
+ writel(temp & (~(1 << 23)), (hcd->regs + 0x184));
+ }
rc = hcd_bus_resume(udev, msg);
} else
rc = usb_port_resume(udev, msg);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 2f47bdc7c93a..d27ad104731c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1739,7 +1739,6 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
int status;
int old_state = hcd->state;
- printk("%s\n", __func__);
dev_dbg(&rhdev->dev, "bus %s%s\n",
(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
if (!hcd->driver->bus_suspend) {
@@ -1877,6 +1876,7 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
{
struct usb_hcd *hcd = __hcd;
+ struct fsl_usb2_platform_data *pdata;
unsigned long flags;
irqreturn_t rc;
@@ -1885,14 +1885,25 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
* assume it's never used.
*/
local_irq_save(flags);
- /* At otg mode, the host does need to handle device interrupt */
- if (hcd->self.is_b_host){
- local_irq_restore(flags);
- return IRQ_NONE;
- }
- else if (unlikely(hcd->state == HC_STATE_HALT ||
- !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ /* Need open clock for register access */
+ pdata = hcd->self.controller->platform_data;
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(true);
+
+ /* if receive a remote wakeup interrrupt after suspend */
+ if (usb_host_wakeup_irq(hcd->self.controller)) {
+ /* disable remote wake up irq */
+ usb_host_set_wakeup(hcd->self.controller, false);
+
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ hcd->driver->irq(hcd);
+ rc = IRQ_HANDLED;
+ } else
rc = IRQ_NONE;
+ } else if (unlikely(hcd->state == HC_STATE_HALT)) {
+ rc = IRQ_NONE;
} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
rc = IRQ_NONE;
} else {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index cc8f911afbc4..3bcd08fbfb71 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -457,7 +457,7 @@ resubmit:
static inline int
hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
{
- return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+ return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo,
tt, NULL, 0, 1000);
}
@@ -1177,6 +1177,12 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
"Unsupported bus topology: hub nested too deep\n");
return -E2BIG;
}
+#ifdef CONFIG_PM
+ /* Defaultly disable autosuspend for hub and reley on sys
+ * to enable it.
+ */
+ hdev->autosuspend_disabled = 1;
+#endif
#ifdef CONFIG_USB_OTG_BLACKLIST_HUB
if (hdev->parent) {
@@ -2298,6 +2304,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
+
/* fail if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
@@ -2321,15 +2328,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
static int hub_resume(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
- struct usb_hcd *hcd = bus_to_hcd(hub->hdev->bus);
dev_dbg(&intf->dev, "%s\n", __func__);
- /* At otg mode, if the hcd which the hub is attached to is not accessible,
- * It should do nothing.
- */
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
- return 0;
-
hub_activate(hub, HUB_RESUME);
return 0;
}
@@ -3286,6 +3286,9 @@ static void hub_events(void)
USB_PORT_FEAT_C_SUSPEND);
udev = hdev->children[i-1];
if (udev) {
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+
usb_lock_device(udev);
ret = remote_wakeup(hdev->
children[i-1]);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 9720e699f472..8c929daa71f2 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -923,11 +923,11 @@ char *usb_cache_string(struct usb_device *udev, int index)
if (index <= 0)
return NULL;
- buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL);
+ buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
if (buf) {
len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
if (len > 0) {
- smallbuf = kmalloc(++len, GFP_KERNEL);
+ smallbuf = kmalloc(++len, GFP_NOIO);
if (!smallbuf)
return buf;
memcpy(smallbuf, buf, len);
@@ -1694,7 +1694,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
if (cp) {
nintf = cp->desc.bNumInterfaces;
new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
- GFP_KERNEL);
+ GFP_NOIO);
if (!new_interfaces) {
dev_err(&dev->dev, "Out of memory\n");
return -ENOMEM;
@@ -1703,7 +1703,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
for (; n < nintf; ++n) {
new_interfaces[n] = kzalloc(
sizeof(struct usb_interface),
- GFP_KERNEL);
+ GFP_NOIO);
if (!new_interfaces[n]) {
dev_err(&dev->dev, "Out of memory\n");
ret = -ENOMEM;
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index b5c72e458943..7bc1469c8f0e 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -111,6 +111,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf)
case USB_SPEED_HIGH:
speed = "480";
break;
+ case USB_SPEED_VARIABLE:
+ speed = "480";
+ break;
+ case USB_SPEED_SUPER:
+ speed = "5000";
+ break;
default:
speed = "unknown";
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index a26f73880c32..b661dbd93208 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting);
struct find_interface_arg {
int minor;
- struct usb_interface *interface;
+ struct device_driver *drv;
};
static int __find_interface(struct device *dev, void *data)
@@ -143,12 +143,10 @@ static int __find_interface(struct device *dev, void *data)
if (!is_usb_interface(dev))
return 0;
+ if (dev->driver != arg->drv)
+ return 0;
intf = to_usb_interface(dev);
- if (intf->minor != -1 && intf->minor == arg->minor) {
- arg->interface = intf;
- return 1;
- }
- return 0;
+ return intf->minor == arg->minor;
}
/**
@@ -156,21 +154,24 @@ static int __find_interface(struct device *dev, void *data)
* @drv: the driver whose current configuration is considered
* @minor: the minor number of the desired device
*
- * This walks the driver device list and returns a pointer to the interface
- * with the matching minor. Note, this only works for devices that share the
- * USB major number.
+ * This walks the bus device list and returns a pointer to the interface
+ * with the matching minor and driver. Note, this only works for devices
+ * that share the USB major number.
*/
struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
{
struct find_interface_arg argb;
- int retval;
+ struct device *dev;
argb.minor = minor;
- argb.interface = NULL;
- /* eat the error, it will be in argb.interface */
- retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
- __find_interface);
- return argb.interface;
+ argb.drv = &drv->drvwrap.driver;
+
+ dev = bus_find_device(&usb_bus_type, NULL, &argb, __find_interface);
+
+ /* Drop reference count from bus_find_device */
+ put_device(dev);
+
+ return dev ? to_usb_interface(dev) : NULL;
}
EXPORT_SYMBOL_GPL(usb_find_interface);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c29ebda61b2f..a19d73730470 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -791,15 +791,6 @@ config USB_G_PRINTER
For more information, see Documentation/usb/gadget_printer.txt
which includes sample code for accessing the device file.
-config USB_ANDROID
- tristate "Android Gadget"
- depends on SWITCH
- help
- The Android gadget provides mass storage and adb transport.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_android".
-
config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
depends on NET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 545c0e256e28..477114e43372 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -41,7 +41,6 @@ gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o
g_printer-objs := printer.o
g_cdc-objs := cdc2.o
-g_android-objs := android.o f_adb.o f_mass_storage.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
@@ -52,5 +51,4 @@ obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
-obj-$(CONFIG_USB_ANDROID) += g_android.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 77352ccc245e..fb0976643a2f 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -1213,7 +1213,12 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
tmp &= AMD_UNMASK_BIT(ep->num);
writel(tmp, &dev->regs->ep_irqmsk);
}
- }
+ } else if (ep->in) {
+ /* enable ep irq */
+ tmp = readl(&dev->regs->ep_irqmsk);
+ tmp &= AMD_UNMASK_BIT(ep->num);
+ writel(tmp, &dev->regs->ep_irqmsk);
+ }
} else if (ep->dma) {
@@ -2005,18 +2010,17 @@ __acquires(dev->lock)
{
int tmp;
- /* empty queues and init hardware */
- udc_basic_init(dev);
- for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
- empty_req_queue(&dev->ep[tmp]);
- }
-
if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
spin_unlock(&dev->lock);
driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
- /* init */
+
+ /* empty queues and init hardware */
+ udc_basic_init(dev);
+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
+ empty_req_queue(&dev->ep[tmp]);
+
udc_setup_endpoints(dev);
}
@@ -2478,6 +2482,13 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
}
}
+ } else if (!use_dma && ep->in) {
+ /* disable interrupt */
+ tmp = readl(
+ &dev->regs->ep_irqmsk);
+ tmp |= AMD_BIT(ep->num);
+ writel(tmp,
+ &dev->regs->ep_irqmsk);
}
}
/* clear status bits */
@@ -3285,6 +3296,17 @@ static int udc_pci_probe(
goto finished;
}
+ spin_lock_init(&dev->lock);
+ /* udc csr registers base */
+ dev->csr = dev->virt_addr + UDC_CSR_ADDR;
+ /* dev registers base */
+ dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
+ /* ep registers base */
+ dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
+ /* fifo's base */
+ dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
+ dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
+
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
kfree(dev);
@@ -3337,7 +3359,6 @@ static int udc_probe(struct udc *dev)
udc_pollstall_timer.data = 0;
/* device struct setup */
- spin_lock_init(&dev->lock);
dev->gadget.ops = &udc_ops;
dev_set_name(&dev->gadget.dev, "gadget");
@@ -3346,16 +3367,6 @@ static int udc_probe(struct udc *dev)
dev->gadget.name = name;
dev->gadget.is_dualspeed = 1;
- /* udc csr registers base */
- dev->csr = dev->virt_addr + UDC_CSR_ADDR;
- /* dev registers base */
- dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
- /* ep registers base */
- dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
- /* fifo's base */
- dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
- dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
-
/* init registers, interrupts, ... */
startup_registers(dev);
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index 8e94549f891e..abba4d2ae8d4 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -106,6 +106,19 @@ extern struct resource *otg_get_resources(void);
extern void fsl_platform_set_test_mode(struct fsl_usb2_platform_data *pdata, enum usb_test_mode mode);
+static inline void
+dr_wake_up_enable(struct fsl_udc *udc, bool enable)
+{
+ struct fsl_usb2_platform_data *pdata;
+ pdata = udc->pdata;
+
+ if (enable && (!device_may_wakeup(udc_controller->gadget.dev.parent)))
+ return;
+
+ if (pdata->wake_up_enable)
+ pdata->wake_up_enable(pdata, enable);
+}
+
#ifdef CONFIG_WORKAROUND_ARCUSB_REG_RW
static void safe_writel(u32 val32, void *addr)
{
@@ -270,12 +283,9 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
static void nuke(struct fsl_ep *ep, int status)
{
ep->stopped = 1;
- /*
- * At udc stop mode, the clock is already off
- * So flush fifo, should be done at clock on mode.
- */
- if (!ep->udc->stopped)
- fsl_ep_fifo_flush(&ep->ep);
+
+ /* Flush fifo */
+ fsl_ep_fifo_flush(&ep->ep);
/* Whether this eq has request linked */
while (!list_empty(&ep->queue)) {
@@ -290,83 +300,31 @@ static void nuke(struct fsl_ep *ep, int status)
/*------------------------------------------------------------------
Internal Hardware related function
------------------------------------------------------------------*/
-static inline void
-dr_wake_up_enable(struct fsl_udc *udc, bool enable)
-{
- struct fsl_usb2_platform_data *pdata;
- pdata = udc->pdata;
- if (pdata && pdata->wake_up_enable)
- pdata->wake_up_enable(pdata, enable);
-}
-static bool clk_stoped = false;
-static inline void dr_clk_gate(bool on)
+static void dr_phy_low_power_mode(struct fsl_udc *udc, bool enable)
{
- struct fsl_usb2_platform_data *pdata = udc_controller->pdata;
+ u32 temp;
- if (!pdata || !pdata->usb_clock_for_pm)
+ if (!device_may_wakeup(udc_controller->gadget.dev.parent))
return;
- if (on && clk_stoped) {
- pdata->usb_clock_for_pm(true);
- clk_stoped = false;
- }
- if (!on && !clk_stoped) {
- pdata->usb_clock_for_pm(false);
- clk_stoped = true;
- }
- if (on)
- reset_phy();
-}
-static void dr_phy_low_power_mode(struct fsl_udc *udc, bool enable)
-{
- struct fsl_usb2_platform_data *pdata = udc->pdata;
- u32 portsc;
+ if (enable) {
+ temp = fsl_readl(&dr_regs->portsc1);
+ temp |= PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(temp, &dr_regs->portsc1);
- if (pdata && pdata->phy_lowpower_suspend) {
- pdata->phy_lowpower_suspend(enable);
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
} else {
- if (enable){
- portsc = fsl_readl(&dr_regs->portsc1);
- portsc |= PORTSCX_PHY_LOW_POWER_SPD;
- fsl_writel(portsc, &dr_regs->portsc1);
- } else {
- portsc = fsl_readl(&dr_regs->portsc1);
- portsc &= ~PORTSCX_PHY_LOW_POWER_SPD;
- fsl_writel(portsc, &dr_regs->portsc1);
- }
- }
-}
-
-
-/* workaroud for some boards, maybe there is a large capacitor between the ground and the Vbus
- * that will cause the vbus dropping very slowly when device is detached,
- * may cost 2-3 seconds to below 0.8V */
-static void udc_wait_b_session_low(void)
-{
- u32 temp;
- u32 wait = 5000; /* max wait time is 5000 ms */
- /* if we are in host mode, don't need to care the B session */
- if ((fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) == 0)
- return;
- /* if the udc is dettached , there will be a suspend irq */
- if (udc_controller->usb_state != USB_STATE_SUSPENDED)
- return;
- temp = fsl_readl(&dr_regs->otgsc);
- temp &= ~(OTGSC_B_SESSION_VALID_IRQ_EN );
- fsl_writel(temp, &dr_regs->otgsc);
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(true);
- do {
- if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_B_SESSION_VALID))
- break;
- mdelay(1);
- wait -= 1;
- } while(wait);
- if (!wait)
- printk("ERROR!!!!!: the vbus can not be lower then 0.8V for 5 seconds, Pls Check your HW design\n");
- temp = fsl_readl(&dr_regs->otgsc);
- temp |= (OTGSC_B_SESSION_VALID_IRQ_EN );
- fsl_writel(temp, &dr_regs->otgsc);
+ /* Due to mx35/mx25's phy's bug */
+ reset_phy();
+ temp = fsl_readl(&dr_regs->portsc1);
+ temp &= ~PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(temp, &dr_regs->portsc1);
+ }
}
static int dr_controller_setup(struct fsl_udc *udc)
@@ -490,20 +448,23 @@ static void dr_controller_run(struct fsl_udc *udc)
fsl_writel(temp, &dr_regs->usbintr);
- /* enable BSV irq */
- temp = fsl_readl(&dr_regs->otgsc);
- temp |= OTGSC_B_SESSION_VALID_IRQ_EN;
- fsl_writel(temp, &dr_regs->otgsc);
+ if (device_may_wakeup(udc_controller->gadget.dev.parent)) {
+ /* enable BSV irq */
+ temp = fsl_readl(&dr_regs->otgsc);
+ temp |= OTGSC_B_SESSION_VALID_IRQ_EN;
+ fsl_writel(temp, &dr_regs->otgsc);
+ }
/* If vbus not on and used low power mode */
- if (!(temp & OTGSC_B_SESSION_VALID)) {
- /* Set stopped before low power mode */
- udc->stopped = 1;
+ if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_B_SESSION_VALID)
+ && device_may_wakeup(udc_controller->gadget.dev.parent)) {
/* enable wake up */
dr_wake_up_enable(udc, true);
- /* enter lower power mode */
+ /* Set stopped before low power mode */
+ udc->stopped = 1;
+ /* close PHY clock */
dr_phy_low_power_mode(udc, true);
- printk(KERN_INFO "%s: udc enter low power mode \n", __func__);
+ printk(KERN_INFO "udc enter low power mode \n");
} else {
#ifdef CONFIG_ARCH_MX37
/*
@@ -515,11 +476,11 @@ static void dr_controller_run(struct fsl_udc *udc)
#endif
/* Clear stopped bit */
udc->stopped = 0;
-
- /* The usb line has already been connected to pc */
+ /* Set controller to Run */
temp = fsl_readl(&dr_regs->usbcmd);
temp |= USB_CMD_RUN_STOP;
fsl_writel(temp, &dr_regs->usbcmd);
+ printk(KERN_INFO "udc run \n");
}
return;
@@ -2015,36 +1976,15 @@ static void suspend_irq(struct fsl_udc *udc)
udc->driver->suspend(&udc->gadget);
}
-/* Process Wake up interrupt
- * Be careful that some boards will use ID pin to control the VBUS on/off
- * in these case, after the device enter the lowpower mode(clk off,
- * phy lowpower mode, wakeup enable), then an udisk is attaced to the otg port,
- * there will be an Vbus wakeup event and then an ID change wakeup, But the Vbus
- * event is not expected, so there is an workaround that will detect the ID, if ID=0
- * we just need the ID event so we can not disable the wakeup
- *
- * false: host wakeup event
- * true: device wakeup event
-*/
-static bool wake_up_irq(struct fsl_udc *udc)
-{
- /* Because the IC design needs to remove the glitch on ID so the otgsc bit 8 will
- * be delayed max 2 ms to show the real ID pin value
- */
- mdelay(3);
-
- /* if the ID=0, let arc host process the wakeup */
- if (fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) {
- dr_wake_up_enable(udc_controller, false);
- dr_phy_low_power_mode(udc, false);
- printk("device wake up event\n");
- return true;
- }else {/* wakeup is vbus wake event, but not for device so we need to clear b session */
- int irq_src = fsl_readl(&dr_regs->otgsc) & (~OTGSC_ID_CHANGE_IRQ_STS);
- fsl_writel(irq_src, &dr_regs->otgsc);
- printk("The host wakeup event, should be handled by host\n");
- return false;
- }
+/* Process Wake up interrupt */
+static void wake_up_irq(struct fsl_udc *udc)
+{
+ pr_debug("%s\n", __func__);
+
+ /* disable wake up irq */
+ dr_wake_up_enable(udc_controller, false);
+
+ udc->stopped = 0;
}
static void bus_resume(struct fsl_udc *udc)
@@ -2113,48 +2053,43 @@ static void reset_irq(struct fsl_udc *udc)
bool try_wake_up_udc(struct fsl_udc *udc)
{
u32 irq_src;
- bool b_device;
/* when udc is stopped, only handle wake up irq */
if (udc->stopped) {
+ if (!device_may_wakeup(&(udc->pdata->pdev->dev)))
+ return false;
+
+ dr_phy_low_power_mode(udc_controller, false);
+
/* check to see if wake up irq */
irq_src = fsl_readl(&dr_regs->usbctrl);
if (irq_src & USB_CTRL_OTG_WUIR) {
- if (wake_up_irq(udc) == false){
- return false; /* host wakeup event */
- }
+ wake_up_irq(udc);
+ } else {
+ dr_phy_low_power_mode(udc_controller, true);
}
}
+ if (!device_may_wakeup(udc_controller->gadget.dev.parent))
+ return true;
+
/* check if Vbus change irq */
irq_src = fsl_readl(&dr_regs->otgsc);
if (irq_src & OTGSC_B_SESSION_VALID_IRQ_STS) {
u32 tmp;
- /* Because the IC design needs to remove the glitch on ID so the otgsc bit 8 will
- * be delayed max 2 ms to show the real ID pin value, as it needs to use ID to judge
- * host or device
- */
- mdelay(3);
- b_device = (irq_src & OTGSC_STS_USB_ID)? true:false;
fsl_writel(irq_src, &dr_regs->otgsc);
- if (!b_device)
- return false;
tmp = fsl_readl(&dr_regs->usbcmd);
/* check BSV bit to see if fall or rise */
if (irq_src & OTGSC_B_SESSION_VALID) {
- if (udc->suspended) /*let the system pm resume the udc */
- return true;
udc->stopped = 0;
fsl_writel(tmp | USB_CMD_RUN_STOP, &dr_regs->usbcmd);
- printk(KERN_INFO "%s: udc out low power mode\n", __func__);
+ printk(KERN_INFO "udc out low power mode\n");
} else {
- printk(KERN_INFO "%s: udc enter low power mode \n", __func__);
- if (udc->driver)
- udc->driver->disconnect(&udc->gadget);
+ printk(KERN_INFO "udc enter low power mode \n");
fsl_writel(tmp & ~USB_CMD_RUN_STOP, &dr_regs->usbcmd);
- udc->stopped = 1;
/* enable wake up */
dr_wake_up_enable(udc, true);
+ udc->stopped = 1;
/* close USB PHY clock */
dr_phy_low_power_mode(udc, true);
return false;
@@ -2163,6 +2098,7 @@ bool try_wake_up_udc(struct fsl_udc *udc)
return true;
}
+
/*
* USB device controller interrupt handler
*/
@@ -2173,29 +2109,15 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
irqreturn_t status = IRQ_NONE;
unsigned long flags;
- spin_lock_irqsave(&udc->lock, flags);
- if (udc->stopped)
- dr_clk_gate(true);
-
- if (try_wake_up_udc(udc) == false) {
- goto irq_end;
- }
-#ifdef CONFIG_USB_OTG
- /* if no gadget register in this driver, we need do noting */
- if (udc->transceiver->gadget == NULL)
- goto irq_end;
-
- /* only handle device interrupt event */
- if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
- goto irq_end;
- }
-#endif
+ if (try_wake_up_udc(udc) == false)
+ return IRQ_NONE;
+ spin_lock_irqsave(&udc->lock, flags);
irq_src = fsl_readl(&dr_regs->usbsts) & fsl_readl(&dr_regs->usbintr);
/* Clear notification bits */
fsl_writel(irq_src, &dr_regs->usbsts);
- VDBG("0x%x\n", irq_src);
+ /* VDBG("irq_src [0x%8x]", irq_src); */
/* Need to resume? */
if (udc->usb_state == USB_STATE_SUSPENDED)
@@ -2240,24 +2162,12 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
/* Sleep Enable (Suspend) */
if (irq_src & USB_STS_SUSPEND) {
- VDBG("suspend int");
suspend_irq(udc);
status = IRQ_HANDLED;
}
if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
- printk(KERN_ERR "Error IRQ %x ", irq_src);
- if (irq_src & USB_STS_SYS_ERR) {
- printk(KERN_ERR "This error can't be recoveried, \
- please reboot your board\n");
- printk(KERN_ERR "If this error happens frequently, \
- please check your dma buffer\n");
- }
- }
-
-irq_end:
- if (udc->stopped){
- dr_clk_gate(false);
+ VDBG("Error IRQ %x ", irq_src);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -2272,6 +2182,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
int retval = -ENODEV;
unsigned long flags = 0;
+ u32 portsc;
if (!udc_controller)
return -ENODEV;
@@ -2289,18 +2200,17 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
spin_lock_irqsave(&udc_controller->lock, flags);
driver->driver.bus = 0;
- udc_controller->pdata->port_enables = 1;
/* hook up the driver */
udc_controller->driver = driver;
udc_controller->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc_controller->lock, flags);
- dr_clk_gate(true);
- /* It doesn't need to switch usb from low power mode to normal mode
- * at otg mode
- */
- if (!udc_controller->transceiver){
- dr_phy_low_power_mode(udc_controller, false);
- }
+
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(true);
+
+ portsc = fsl_readl(&dr_regs->portsc1);
+ portsc &= ~PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(portsc, &dr_regs->portsc1);
/* bind udc driver to gadget driver */
retval = driver->bind(&udc_controller->gadget);
@@ -2313,30 +2223,30 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (udc_controller->transceiver) {
/* Suspend the controller until OTG enable it */
- udc_controller->suspended = 1;/* let the otg resume it */
+ udc_controller->stopped = 1;
printk(KERN_INFO "Suspend udc for OTG auto detect\n");
dr_wake_up_enable(udc_controller, true);
+ dr_phy_low_power_mode(udc_controller, true);
/* export udc suspend/resume call to OTG */
udc_controller->gadget.dev.driver->suspend = (dev_sus)fsl_udc_suspend;
udc_controller->gadget.dev.driver->resume = (dev_res)fsl_udc_resume;
/* connect to bus through transceiver */
- retval = otg_set_peripheral(udc_controller->transceiver,
- &udc_controller->gadget);
- if (retval < 0) {
- ERR("can't bind to transceiver\n");
- driver->unbind(&udc_controller->gadget);
- udc_controller->gadget.dev.driver = 0;
- udc_controller->driver = 0;
- return retval;
+ if (udc_controller->transceiver) {
+ retval = otg_set_peripheral(udc_controller->transceiver,
+ &udc_controller->gadget);
+ if (retval < 0) {
+ ERR("can't bind to transceiver\n");
+ driver->unbind(&udc_controller->gadget);
+ udc_controller->gadget.dev.driver = 0;
+ udc_controller->driver = 0;
+ return retval;
+ }
}
- //dr_clk_gate(false);
} else {
/* Enable DR IRQ reg and Set usbcmd reg Run bit */
dr_controller_run(udc_controller);
- if (udc_controller->stopped)
- dr_clk_gate(false);
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_dir = 0;
}
@@ -2344,10 +2254,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.name, driver->driver.name);
out:
- if (retval){
+ if (retval)
printk(KERN_DEBUG "retval %d \n", retval);
- udc_controller->pdata->port_enables = 0;
- }
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
@@ -2357,6 +2265,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
struct fsl_ep *loop_ep;
unsigned long flags;
+ u32 portsc;
if (!udc_controller)
return -ENODEV;
@@ -2364,16 +2273,15 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
- if(udc_controller->stopped)
- dr_clk_gate(true);
-
if (udc_controller->transceiver)
(void)otg_set_peripheral(udc_controller->transceiver, 0);
+ /* open phy clock for following operation */
+ dr_phy_low_power_mode(udc_controller, false);
+
/* stop DR, disable intr */
dr_controller_stop(udc_controller);
- udc_controller->pdata->port_enables = 0;
/* in fact, no needed */
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_dir = 0;
@@ -2395,11 +2303,14 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.dev.driver = 0;
udc_controller->driver = 0;
- if (udc_controller->gadget.is_otg) {
- dr_wake_up_enable(udc_controller, true);
- }
+ dr_wake_up_enable(udc_controller, false);
- dr_phy_low_power_mode(udc_controller, true);
+ portsc = fsl_readl(&dr_regs->portsc1);
+ portsc |= PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(portsc, &dr_regs->portsc1);
+
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
printk(KERN_INFO "unregistered gadget driver '%s'\r\n",
driver->driver.name);
@@ -2814,7 +2725,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
ret = -ENODEV;
goto err1a;
}
- udc_controller->gadget.is_otg = 1;
#endif
if ((pdev->dev.parent) &&
@@ -2915,6 +2825,12 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
if (ret < 0)
goto err3;
+ if (udc_controller->transceiver) {
+ udc_controller->gadget.is_otg = 1;
+ /* now didn't support lpm in OTG mode*/
+ device_set_wakeup_capable(&pdev->dev, 0);
+ }
+
/* setup QH and epctrl for ep0 */
ep0_setup(udc_controller);
@@ -2957,29 +2873,24 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
#ifdef POSTPONE_FREE_LAST_DTD
last_free_td = NULL;
#endif
-
#ifndef CONFIG_USB_OTG
/* disable all INTR */
fsl_writel(0, &dr_regs->usbintr);
+
dr_wake_up_enable(udc_controller, false);
-#else
- dr_wake_up_enable(udc_controller, true);
-#endif
+ udc_controller->stopped = 1;
-/*
- * As mx25/mx35 does not implement clk_gate, should not let phy to low
- * power mode due to IC bug
- */
#if !(defined CONFIG_ARCH_MX35 || defined CONFIG_ARCH_MX25)
{
- dr_phy_low_power_mode(udc_controller, true);
+ u32 portsc;
+ portsc = fsl_readl(&dr_regs->portsc1);
+ portsc |= PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(portsc, &dr_regs->portsc1);
}
#endif
- udc_controller->stopped = 1;
-
- /* let the gadget register function open the clk */
- dr_clk_gate(false);
-
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
+#endif
create_proc_file();
return 0;
@@ -3006,6 +2917,9 @@ err1a:
*/
static int __exit fsl_udc_remove(struct platform_device *pdev)
{
+#ifndef CONFIG_USB_OTG
+ struct resource *res;
+#endif
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
DECLARE_COMPLETION(done);
@@ -3014,8 +2928,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
return -ENODEV;
udc_controller->done = &done;
/* open USB PHY clock */
- if (udc_controller->stopped)
- dr_clk_gate(true);
+ dr_phy_low_power_mode(udc_controller, false);
/* DR has been stopped in usb_gadget_unregister_driver() */
remove_proc_file();
@@ -3038,11 +2951,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
iounmap((u8 __iomem *)dr_regs);
#ifndef CONFIG_USB_OTG
-{
- struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
-}
#endif
device_unregister(&udc_controller->gadget.dev);
@@ -3056,8 +2966,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
if (pdata->platform_uninit)
pdata->platform_uninit(pdata);
- if (udc_controller->stopped)
- dr_clk_gate(false);
return 0;
}
@@ -3065,19 +2973,10 @@ static int udc_suspend(struct fsl_udc *udc)
{
u32 mode, usbcmd;
- /*
- * When it is the PM suspend routine and the device has no
- * abilities to wakeup system, it should not set wakeup enable.
- * Otherwise, the system will wakeup even the user only wants to
- * charge using usb
- */
- if (udc_controller->gadget.dev.parent->power.status
- == DPM_SUSPENDING) {
- if (!device_may_wakeup(udc_controller->gadget.dev.parent))
- dr_wake_up_enable(udc, false);
- else
- dr_wake_up_enable(udc, true);
- }
+ /* open clock for register access */
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(true);
+
mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK;
usbcmd = fsl_readl(&dr_regs->usbcmd);
@@ -3088,8 +2987,9 @@ static int udc_suspend(struct fsl_udc *udc)
* PM suspend. Remember this fact, so that we will leave the
* controller stopped at PM resume time.
*/
- if (udc->suspended) {
+ if (udc->stopped) {
pr_debug("gadget already stopped, leaving early\n");
+ udc->already_stopped = 1;
goto out;
}
@@ -3098,30 +2998,22 @@ static int udc_suspend(struct fsl_udc *udc)
goto out;
}
- /* For some buggy hardware designs, see comment of this function for detail */
- udc_wait_b_session_low();
-
udc->stopped = 1;
-
- /* stop the controller */
- usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
- fsl_writel(usbcmd, &dr_regs->usbcmd);
-
/* if the suspend is not for switch to host in otg mode */
if ((!(udc->gadget.is_otg)) ||
(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
- if (device_may_wakeup(udc_controller->gadget.dev.parent)) {
- dr_wake_up_enable(udc, true);
- }
+ dr_wake_up_enable(udc, true);
+ dr_phy_low_power_mode(udc, true);
}
- dr_phy_low_power_mode(udc, true);
+ /* stop the controller */
+ usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
+ fsl_writel(usbcmd, &dr_regs->usbcmd);
+
printk(KERN_INFO "USB Gadget suspended\n");
out:
- udc->suspended++;
- if (udc->suspended > 2)
- printk("ERROR: suspended times > 2\n");
-
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
return 0;
}
@@ -3131,24 +3023,13 @@ out:
-----------------------------------------------------------------*/
static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
{
- int ret;
-#ifdef CONFIG_USB_OTG
- if (udc_controller->transceiver->gadget == NULL)
- return 0;
-#endif
- if (udc_controller->stopped)
- dr_clk_gate(true);
if (((!(udc_controller->gadget.is_otg)) ||
(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) &&
(udc_controller->usb_state > USB_STATE_POWERED) &&
- (udc_controller->usb_state < USB_STATE_SUSPENDED)) {
- return -EBUSY;/* keep the clk on */
- }
- else
- ret = udc_suspend(udc_controller);
- dr_clk_gate(false);
+ (udc_controller->usb_state < USB_STATE_SUSPENDED))
+ return -EBUSY;
- return ret;
+ return udc_suspend(udc_controller);
}
/*-----------------------------------------------------------------
@@ -3157,54 +3038,30 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
*-----------------------------------------------------------------*/
static int fsl_udc_resume(struct platform_device *pdev)
{
- pr_debug("%s(): stopped %d suspended %d\n", __func__,
- udc_controller->stopped, udc_controller->suspended);
- printk("udc resume\n");
-#ifdef CONFIG_USB_OTG
- if (udc_controller->transceiver->gadget == NULL)
- return 0;
-#endif
- if (udc_controller->stopped)
- dr_clk_gate(true);
+ pr_debug("%s(): stopped %d already_stopped %d\n", __func__,
+ udc_controller->stopped, udc_controller->already_stopped);
+
/*
* If the controller was stopped at suspend time, then
* don't resume it now.
*/
- /*
- * If it is PM resume routine, the udc is at low power mode,
- * and the udc has no abilities to wakeup system, it should
- * set the abilities to wakeup itself. Otherwise, the usb
- * subsystem will not leave from low power mode.
- */
- if (!device_may_wakeup(udc_controller->gadget.dev.parent) &&
- udc_controller->gadget.dev.parent->power.status
- == DPM_RESUMING){
- dr_wake_up_enable(udc_controller, true);
- }
-
- if (--udc_controller->suspended) {
- printk("gadget was already stopped, leaving early\n");
- goto out;
+ if (udc_controller->already_stopped) {
+ udc_controller->already_stopped = 0;
+ pr_debug("gadget was already stopped, leaving early\n");
+ return 0;
}
+
/* Enable DR irq reg and set controller Run */
if (udc_controller->stopped) {
- /* if in host mode, we need to do nothing */
- if ((fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) == 0) {
- goto out;
- }
dr_wake_up_enable(udc_controller, false);
dr_phy_low_power_mode(udc_controller, false);
- mdelay(10);
+ mdelay(1);
+
dr_controller_setup(udc_controller);
dr_controller_run(udc_controller);
}
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_dir = 0;
-out:
- /* if udc is resume by otg id change and no device
- * connecting to the otg, otg will enter low power mode*/
- if (udc_controller->stopped)
- dr_clk_gate(false);
printk(KERN_INFO "USB Gadget resumed\n");
return 0;
diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h
index 8d344acb8fef..4574954bf4f4 100644
--- a/drivers/usb/gadget/arcotg_udc.h
+++ b/drivers/usb/gadget/arcotg_udc.h
@@ -266,7 +266,6 @@ struct usb_sys_interface {
#define PORTSCX_SPEED_BIT_POS (26)
/* OTGSC Register Bit Masks */
-#define OTGSC_ID_CHANGE_IRQ_STS (1 << 16)
#define OTGSC_B_SESSION_VALID_IRQ_EN (1 << 27)
#define OTGSC_B_SESSION_VALID_IRQ_STS (1 << 19)
#define OTGSC_B_SESSION_VALID (1 << 11)
@@ -594,15 +593,9 @@ struct fsl_udc {
struct otg_transceiver *transceiver;
unsigned softconnect:1;
unsigned vbus_active:1;
- unsigned remote_wakeup:1;
- /* we must distinguish the stopped and suspended state,
- * stopped means the udc enter lowpower mode, suspended
- * means the udc is suspended by system pm or by otg
- * switching to host mode.if the udc in suspended state
- * it also in the stopped state, while if the udc in
- * stopped state,it may not be in the suspended state*/
unsigned stopped:1;
- int suspended;
+ unsigned remote_wakeup:1;
+ unsigned already_stopped:1;
struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */
struct fsl_req *status_req; /* ep0 status request */
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 2e79b8c389a4..59e85234fa0a 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -236,7 +236,6 @@ static int config_buf(struct usb_configuration *config,
int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
struct usb_function *f;
int status;
- int interfaceCount = 0;
/* write the config descriptor */
c = buf;
@@ -267,16 +266,8 @@ static int config_buf(struct usb_configuration *config,
descriptors = f->hs_descriptors;
else
descriptors = f->descriptors;
- if (f->hidden || !descriptors || descriptors[0] == NULL) {
- for (; f != config->interface[interfaceCount];) {
- interfaceCount++;
- c->bNumInterfaces--;
- }
+ if (!descriptors)
continue;
- }
- for (; f != config->interface[interfaceCount];)
- interfaceCount++;
-
status = usb_descriptor_fillbuf(next, len,
(const struct usb_descriptor_header **) descriptors);
if (status < 0)
@@ -765,11 +756,11 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
- if (cdev->config) {
+ if (cdev->config)
*(u8 *)req->buf = cdev->config->bConfigurationValue;
- value = min(w_length, (u16) 1);
- } else
+ else
*(u8 *)req->buf = 0;
+ value = min(w_length, (u16) 1);
break;
/* function drivers must handle get/set altsetting; if there's
@@ -819,9 +810,6 @@ unknown:
*/
if ((ctrl->bRequestType & USB_RECIP_MASK)
== USB_RECIP_INTERFACE) {
- if (cdev->config == NULL)
- return value;
-
f = cdev->config->interface[intf];
if (f && f->setup)
value = f->setup(f, ctrl);
@@ -836,25 +824,6 @@ unknown:
value = c->setup(c, ctrl);
}
- /* If the vendor request is not processed (value < 0),
- * call all device registered configure setup callbacks
- * to process it.
- * This is used to handle the following cases:
- * - vendor request is for the device and arrives before
- * setconfiguration.
- * - Some devices are required to handle vendor request before
- * setconfiguration such as MTP, USBNET.
- */
-
- if (value < 0) {
- struct usb_configuration *cfg;
-
- list_for_each_entry(cfg, &cdev->configs, list) {
- if (cfg && cfg->setup)
- value = cfg->setup(cfg, ctrl);
- }
- }
-
goto done;
}
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 7dd1a8bbe382..7953948bfe4a 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -761,12 +761,3 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
kfree(acm);
return status;
}
-
-int __init acm_function_add(struct usb_composite_dev *cdev,
- struct usb_configuration *c)
-{
- int ret = acm_bind_config(c, 0);
- if (ret == 0)
- gserial_setup(c->cdev->gadget, 1);
- return ret;
-}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 8b0a13202573..66105ce49672 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -728,7 +728,6 @@ struct fsg_dev {
#include "fsl_updater.h"
#endif
-static int do_set_interface(struct fsg_dev *fsg, int altsetting);
typedef void (*fsg_routine_t)(struct fsg_dev *);
static int exception_in_progress(struct fsg_dev *fsg)
@@ -1109,14 +1108,6 @@ static void fsg_disconnect(struct usb_gadget *gadget)
struct fsg_dev *fsg = get_gadget_data(gadget);
DBG(fsg, "disconnect or port reset\n");
- /*
- * The disconnect exception will call do_set_config, and therefore will
- * visit controller registers. However it is a delayed event, and will be
- * handled at another process, so the controller maybe have already close the
- * usb clock.*/
- if (fsg->new_config)
- do_set_interface(fsg, -1);/* disable the interface */
-
raise_exception(fsg, FSG_STATE_DISCONNECT);
}
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c
index 5cfcf169e7c7..21133fb8e47a 100644
--- a/drivers/usb/host/ehci-arc.c
+++ b/drivers/usb/host/ehci-arc.c
@@ -23,28 +23,9 @@
#include <linux/fsl_devices.h>
#include <linux/usb/otg.h>
-#include "../core/usb.h"
#include "ehci-fsl.h"
#include <mach/fsl_usb.h>
-extern int usb_host_wakeup_irq(struct device *wkup_dev);
-extern void usb_host_set_wakeup(struct device *wkup_dev, bool para);
-static void fsl_usb_lowpower_mode(struct fsl_usb2_platform_data *pdata, bool enable)
-{
- if (enable){
- if (pdata->phy_lowpower_suspend)
- pdata->phy_lowpower_suspend(true);
- } else {
- if (pdata->phy_lowpower_suspend)
- pdata->phy_lowpower_suspend(false);
- }
-}
-
-static void fsl_usb_clk_gate(struct fsl_usb2_platform_data *pdata, bool enable)
-{
- if (pdata->usb_clock_for_pm)
- pdata->usb_clock_for_pm(enable);
-}
#undef EHCI_PROC_PTC
#ifdef EHCI_PROC_PTC /* /proc PORTSC:PTC support */
/*
@@ -109,39 +90,8 @@ static int ehci_testmode_init(struct ehci_hcd *ehci)
#endif /* /proc PORTSC:PTC support */
-/*
- * This irq is used to open the hw access and let usb_hcd_irq process the usb event
- * ehci_fsl_pre_irq will be called before usb_hcd_irq
- */
-static irqreturn_t ehci_fsl_pre_irq(int irq, void *dev)
-{
- struct platform_device *pdev = (struct platform_device *)dev;
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct fsl_usb2_platform_data *pdata;
-
- pdata = hcd->self.controller->platform_data;
-
- /* if it is an otg module and in b device mode, we need to do noting here */
- if (ehci->transceiver && !ehci->transceiver->default_a)
- return IRQ_NONE;
-
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- /* Need to open clk for accessing the register */
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- /* if receive a remote wakeup interrrupt after suspend */
- if (usb_host_wakeup_irq(hcd->self.controller)) {
- printk("host wakeup event happens\n");
- /* disable remote wake up irq */
- usb_host_set_wakeup(hcd->self.controller, false);
- fsl_usb_lowpower_mode(pdata, false);
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- }else {
- fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
- }
- }
- return IRQ_NONE;
-}
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
/**
* usb_hcd_fsl_probe - initialize FSL-based HCDs
@@ -232,18 +182,9 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
fsl_platform_set_host_mode(hcd);
hcd->power_budget = pdata->power_budget;
- /*
- * The ehci_fsl_pre_irq must be registered before usb_hcd_irq, in that case
- * it can be called before usb_hcd_irq when irq occurs
- */
- retval = request_irq(irq, ehci_fsl_pre_irq, IRQF_SHARED,
- "fsl ehci pre interrupt", (void *)pdev);
- if (retval != 0)
- goto err4;
-
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (retval != 0)
- goto err5;
+ goto err4;
fsl_platform_set_vbus_power(pdata, 1);
@@ -258,7 +199,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
if (!ehci->transceiver) {
printk(KERN_ERR "can't find transceiver\n");
retval = -ENODEV;
- goto err5;
+ goto err4;
}
retval = otg_set_host(ehci->transceiver, &ehci_to_hcd(ehci)->self);
@@ -275,8 +216,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
fsl_platform_set_ahb_burst(hcd);
ehci_testmode_init(hcd_to_ehci(hcd));
return retval;
-err5:
- free_irq(irq, (void *)pdev);
+
err4:
iounmap(hcd->regs);
err3:
@@ -291,6 +231,9 @@ err1:
return retval;
}
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
/**
* usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs
* @dev: USB Host Controller being removed
@@ -381,59 +324,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci)
return 0;
}
-static int ehci_fsl_bus_suspend(struct usb_hcd *hcd)
-{
- int ret = 0;
- struct fsl_usb2_platform_data *pdata;
- pdata = hcd->self.controller->platform_data;
- pr_debug("%s, %s\n", __func__, pdata->name);
-
- /* the host is already at low power mode */
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- return 0;
- }
-
- pr_debug("%s, it is the host mode, %s\n", __func__, pdata->name);
-
- ehci_bus_suspend(hcd);
-
- if (pdata->platform_suspend)
- pdata->platform_suspend(pdata);
-
- usb_host_set_wakeup(hcd->self.controller, true);
- fsl_usb_lowpower_mode(pdata, true);
- fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
- return ret;
-}
-
-static int ehci_fsl_bus_resume(struct usb_hcd *hcd)
-{
- int ret = 0;
- struct fsl_usb2_platform_data *pdata;
-
- pdata = hcd->self.controller->platform_data;
- pr_debug("%s, %s\n", __func__, pdata->name);
-
- /* if it is a remote wakeup, it will open clock and clear PHCD automatically */
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- usb_host_set_wakeup(hcd->self.controller, false);
- fsl_usb_lowpower_mode(pdata, false);
- }
-
- if (pdata->platform_resume)
- pdata->platform_resume(pdata);
- ret = ehci_bus_resume(hcd);
- if (ret)
- return ret;
-
- return ret;
-}
-
-
/* called during probe() after chip reset completes */
static int ehci_fsl_setup(struct usb_hcd *hcd)
{
@@ -506,8 +396,8 @@ static const struct hc_driver ehci_fsl_hc_driver = {
*/
.hub_status_data = ehci_hub_status_data,
.hub_control = ehci_hub_control,
- .bus_suspend = ehci_fsl_bus_suspend,
- .bus_resume = ehci_fsl_bus_resume,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
.start_port_reset = ehci_start_port_reset,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
@@ -548,36 +438,13 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev,
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct usb_device *roothub = hcd->self.root_hub;
- u32 port_status;
+ u32 tmp, port_status;
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- /* Only handles OTG mode switch event, system suspend event will be done in bus suspend */
- if (pdev->dev.power.status == DPM_SUSPENDING){
- pr_debug("%s, system pm event \n", __func__);
- if (!device_may_wakeup(&(pdev->dev))){
- /* Need open clock for register access */
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- usb_host_set_wakeup(hcd->self.controller, false);
- fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
- }
- return 0;
- }
- /* only the otg host can go here */
- /* wait for all usb device on the hcd dettached */
- while(roothub->children[0] != NULL)
- msleep(1);
- if ((pdata->operating_mode != FSL_USB2_MPH_HOST) && (!(hcd->state & HC_STATE_SUSPENDED)))
- {
- usb_lock_device(roothub);
- usb_external_suspend_device(roothub, PMSG_USER_SUSPEND);
- usb_unlock_device(roothub);
- }
-
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ if (device_may_wakeup(&(pdev->dev))) {
+ /* Need open clock for register access */
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(true);
}
#ifdef DEBUG
@@ -590,9 +457,27 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev,
pdata->suspended, pdata->already_suspended, mode, tmp);
#endif
+ /*
+ * If the controller is already suspended, then this must be a
+ * PM suspend. Remember this fact, so that we will leave the
+ * controller suspended at PM resume time.
+ */
+ if (pdata->suspended) {
+ pr_debug("%s: already suspended, leaving early\n", __func__);
+ pdata->already_suspended = 1;
+ goto err1;
+ }
+
+ pr_debug("%s: suspending...\n", __func__);
+
printk(KERN_INFO "USB Host suspended\n");
port_status = ehci_readl(ehci, &ehci->regs->port_status[0]);
+ pdev->dev.power.power_state = PMSG_SUSPEND;
+
+ /* ignore non-host interrupts */
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
/* save EHCI registers */
pdata->pm_command = ehci_readl(ehci, &ehci->regs->command);
pdata->pm_command &= ~CMD_RUN;
@@ -611,11 +496,25 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev,
/* clear PHCD bit */
pdata->pm_portsc &= ~PORT_PHCD;
- if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- //fsl_usb_lowpower_mode(pdata ,true);
- //usb_host_set_wakeup(hcd->self.controller, true);
- fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ pdata->suspended = 1;
+
+ if (!device_may_wakeup(&(pdev->dev))) {
+ /* clear PP to cut power to the port */
+ tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);
+ tmp &= ~PORT_POWER;
+ ehci_writel(ehci, tmp, &ehci->regs->port_status[0]);
+ goto err1;
+ }
+
+ tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);
+
+ if (pdata->platform_suspend)
+ pdata->platform_suspend(pdata);
+err1:
+ if (device_may_wakeup(&(pdev->dev))) {
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(false);
}
return 0;
}
@@ -624,35 +523,47 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct usb_device *roothub = hcd->self.root_hub;
u32 tmp;
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- /* Only handles OTG mode switch event */
- if (pdev->dev.power.status == DPM_RESUMING){
- pr_debug("%s, system pm event \n", __func__);
- if (hcd->self.is_b_host) {
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- }
- usb_host_set_wakeup(hcd->self.controller, true);
-
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
- }
- }
+
+ pr_debug("%s('%s'): suspend=%d already_suspended=%d\n", __func__,
+ pdata->name, pdata->suspended, pdata->already_suspended);
+
+ /*
+ * If the controller was already suspended at suspend time,
+ * then don't resume it now.
+ */
+ if (pdata->already_suspended) {
+ pr_debug("already suspended, leaving early\n");
+ pdata->already_suspended = 0;
return 0;
}
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- //usb_host_set_wakeup(hcd->self.controller, false);
- //fsl_usb_lowpower_mode(pdata, false);
+
+ if (!pdata->suspended) {
+ pr_debug("not suspended, leaving early\n");
+ return 0;
}
- printk("USB Host resume ... %s\n", pdata->name);
+ /* If hcd is resumed by non-usb wakeup events,
+ * then usb clocks are still not open when come here */
+ if (device_may_wakeup(&(pdev->dev))) {
+ /* Need open clock for register access */
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(true);
+ }
+
+ tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);
+
+ pdata->suspended = 0;
+
+ pr_debug("%s resuming...\n", __func__);
+
/* set host mode */
fsl_platform_set_host_mode(hcd);
+ if (pdata->platform_resume)
+ pdata->platform_resume(pdata);
+
/* restore EHCI registers */
ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);
ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
@@ -664,21 +575,32 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev)
ehci_writel(ehci, pdata->pm_configured_flag,
&ehci->regs->configured_flag);
+ /* set bit should be done by wakeup irq routine if may wakeup */
+ if (!device_may_wakeup(&(pdev->dev)))
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ else
+ while (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ msleep(1);
+
+ pdev->dev.power.power_state = PMSG_ON;
tmp = ehci_readl(ehci, &ehci->regs->command);
tmp |= CMD_RUN;
ehci_writel(ehci, tmp, &ehci->regs->command);
- if ((hcd->state & HC_STATE_SUSPENDED)){
- usb_lock_device(roothub);
- usb_external_resume_device(roothub, PMSG_USER_RESUME);
- usb_unlock_device(roothub);
+ usb_hcd_resume_root_hub(hcd);
+
+ printk(KERN_INFO "USB Host resumed\n");
+
+ if (device_may_wakeup(&(pdev->dev))) {
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(false);
}
- printk(KERN_INFO "USB Host resume ok\n");
return 0;
}
-#endif
+#endif /* CONFIG_USB_OTG */
+
MODULE_ALIAS("platform:fsl-ehci");
static struct platform_driver ehci_fsl_driver = {
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 1a9266e7e798..f0d6627fb981 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -28,6 +28,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
+#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
@@ -660,6 +661,7 @@ static int ehci_run (struct usb_hcd *hcd)
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
msleep(5);
up_write(&ehci_cf_port_reset_rwsem);
+ ehci->last_periodic_enable = ktime_get_real();
temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci_info (ehci,
@@ -767,9 +769,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* start 20 msec resume signaling from this port,
* and make khubd collect PORT_STAT_C_SUSPEND to
- * stop that signaling.
+ * stop that signaling. Use 5 ms extra for safety,
+ * like usb_port_resume() does.
*/
- ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+ ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 44ff32306362..2eac68f54ccd 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -112,7 +112,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
int port;
int mask;
- printk("%s\n", __func__);
ehci_dbg(ehci, "suspend root hub\n");
if (time_before (jiffies, ehci->next_statechange))
@@ -120,9 +119,26 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
del_timer_sync(&ehci->watchdog);
del_timer_sync(&ehci->iaa_watchdog);
- port = HCS_N_PORTS (ehci->hcs_params);
spin_lock_irq (&ehci->lock);
+ /* Once the controller is stopped, port resumes that are already
+ * in progress won't complete. Hence if remote wakeup is enabled
+ * for the root hub and any ports are in the middle of a resume or
+ * remote wakeup, we must fail the suspend.
+ */
+ if (hcd->self.root_hub->do_remote_wakeup) {
+ port = HCS_N_PORTS(ehci->hcs_params);
+ while (port--) {
+ if (ehci->reset_done[port] != 0) {
+ spin_unlock_irq(&ehci->lock);
+ ehci_dbg(ehci, "suspend failed because "
+ "port %d is resuming\n",
+ port + 1);
+ return -EBUSY;
+ }
+ }
+ }
+
/* stop schedules, clean any completed work */
if (HC_IS_RUNNING(hcd->state)) {
ehci_quiesce (ehci);
@@ -138,6 +154,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
*/
ehci->bus_suspended = 0;
ehci->owned_ports = 0;
+ port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index c2f1b7df918c..c757a706843c 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -72,6 +72,12 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
int retval;
switch (pdev->vendor) {
+ case PCI_VENDOR_ID_INTEL:
+ if (pdev->device == 0x27cc) {
+ ehci->broken_periodic = 1;
+ ehci_info(ehci, "using broken periodic workaround\n");
+ }
+ break;
case PCI_VENDOR_ID_TOSHIBA_2:
/* celleb's companion chip */
if (pdev->device == 0x01b5) {
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 7673554fa64d..1ae9faf1f8c2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -475,8 +475,20 @@ halt:
* we must clear the TT buffer (11.17.5).
*/
if (unlikely(last_status != -EINPROGRESS &&
- last_status != -EREMOTEIO))
- ehci_clear_tt_buffer(ehci, qh, urb, token);
+ last_status != -EREMOTEIO)) {
+ /* The TT's in some hubs malfunction when they
+ * receive this request following a STALL (they
+ * stop sending isochronous packets). Since a
+ * STALL can't leave the TT buffer in a busy
+ * state (if you believe Figures 11-48 - 11-51
+ * in the USB 2.0 spec), we won't clear the TT
+ * buffer in this case. Strictly speaking this
+ * is a violation of the spec.
+ */
+ if (last_status != -EPIPE)
+ ehci_clear_tt_buffer(ehci, qh, urb,
+ token);
+ }
}
/* if we're removing something not at the queue head,
@@ -790,9 +802,10 @@ qh_make (
* But interval 1 scheduling is simpler, and
* includes high bandwidth.
*/
- dbg ("intr period %d uframes, NYET!",
- urb->interval);
- goto done;
+ urb->interval = 1;
+ } else if (qh->period > ehci->periodic_size) {
+ qh->period = ehci->periodic_size;
+ urb->interval = qh->period << 3;
}
} else {
int think_time;
@@ -815,6 +828,10 @@ qh_make (
usb_calc_bus_time (urb->dev->speed,
is_input, 0, max_packet (maxp)));
qh->period = urb->interval;
+ if (qh->period > ehci->periodic_size) {
+ qh->period = ehci->periodic_size;
+ urb->interval = qh->period;
+ }
}
}
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index edd61ee90323..c340f1f4b881 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -456,6 +456,8 @@ static int enable_periodic (struct ehci_hcd *ehci)
/* make sure ehci_work scans these */
ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index)
% (ehci->periodic_size << 3);
+ if (unlikely(ehci->broken_periodic))
+ ehci->last_periodic_enable = ktime_get_real();
return 0;
}
@@ -467,6 +469,16 @@ static int disable_periodic (struct ehci_hcd *ehci)
if (--ehci->periodic_sched)
return 0;
+ if (unlikely(ehci->broken_periodic)) {
+ /* delay experimentally determined */
+ ktime_t safe = ktime_add_us(ehci->last_periodic_enable, 1000);
+ ktime_t now = ktime_get_real();
+ s64 delay = ktime_us_delta(safe, now);
+
+ if (unlikely(delay > 0))
+ udelay(delay);
+ }
+
/* did setting PSE not take effect yet?
* takes effect only at frame boundaries...
*/
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 4b81f5e77c8b..7a412652cb5d 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -118,6 +118,7 @@ struct ehci_hcd { /* one per controller */
unsigned stamp;
unsigned random_frame;
unsigned long next_statechange;
+ ktime_t last_periodic_enable;
u32 command;
/* SILICON QUIRKS */
@@ -126,6 +127,7 @@ struct ehci_hcd { /* one per controller */
unsigned big_endian_mmio:1;
unsigned big_endian_desc:1;
unsigned has_amcc_usb23:1;
+ unsigned broken_periodic:1;
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 58151687d351..1ed2a16a61de 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -88,6 +88,7 @@ static int ohci_restart (struct ohci_hcd *ohci);
#ifdef CONFIG_PCI
static void quirk_amd_pll(int state);
static void amd_iso_dev_put(void);
+static void sb800_prefetch(struct ohci_hcd *ohci, int on);
#else
static inline void quirk_amd_pll(int state)
{
@@ -97,6 +98,10 @@ static inline void amd_iso_dev_put(void)
{
return;
}
+static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
+{
+ return;
+}
#endif
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index d2ba04dd785e..b8a1148f248e 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -177,6 +177,13 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
return 0;
pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+
+ /* SB800 needs pre-fetch fix */
+ if ((rev >= 0x40) && (rev <= 0x4f)) {
+ ohci->flags |= OHCI_QUIRK_AMD_PREFETCH;
+ ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
+ }
+
if ((rev > 0x3b) || (rev < 0x30)) {
pci_dev_put(amd_smbus_dev);
amd_smbus_dev = NULL;
@@ -262,6 +269,19 @@ static void amd_iso_dev_put(void)
}
+static void sb800_prefetch(struct ohci_hcd *ohci, int on)
+{
+ struct pci_dev *pdev;
+ u16 misc;
+
+ pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller);
+ pci_read_config_word(pdev, 0x50, &misc);
+ if (on == 0)
+ pci_write_config_word(pdev, 0x50, misc & 0xfcff);
+ else
+ pci_write_config_word(pdev, 0x50, misc | 0x0300);
+}
+
/* List of quirks for OHCI */
static const struct pci_device_id ohci_pci_quirks[] = {
{
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index c2d80f80448b..2c7409b09e8b 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -49,9 +49,12 @@ __acquires(ohci->lock)
switch (usb_pipetype (urb->pipe)) {
case PIPE_ISOCHRONOUS:
ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
- if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
- && quirk_amdiso(ohci))
- quirk_amd_pll(1);
+ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
+ if (quirk_amdiso(ohci))
+ quirk_amd_pll(1);
+ if (quirk_amdprefetch(ohci))
+ sb800_prefetch(ohci, 0);
+ }
break;
case PIPE_INTERRUPT:
ohci_to_hcd(ohci)->self.bandwidth_int_reqs--;
@@ -680,9 +683,12 @@ static void td_submit_urb (
data + urb->iso_frame_desc [cnt].offset,
urb->iso_frame_desc [cnt].length, urb, cnt);
}
- if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
- && quirk_amdiso(ohci))
- quirk_amd_pll(0);
+ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
+ if (quirk_amdiso(ohci))
+ quirk_amd_pll(0);
+ if (quirk_amdprefetch(ohci))
+ sb800_prefetch(ohci, 1);
+ }
periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0
&& ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0;
break;
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 222011f6172c..5bf15fed0d9f 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -402,6 +402,7 @@ struct ohci_hcd {
#define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */
#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
+#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
// there are also chip quirks/bugs in init logic
struct work_struct nec_work; /* Worker for NEC quirk */
@@ -433,6 +434,10 @@ static inline int quirk_amdiso(struct ohci_hcd *ohci)
{
return ohci->flags & OHCI_QUIRK_AMD_ISO;
}
+static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
+{
+ return ohci->flags & OHCI_QUIRK_AMD_PREFETCH;
+}
#else
static inline int quirk_nec(struct ohci_hcd *ohci)
{
@@ -446,6 +451,10 @@ static inline int quirk_amdiso(struct ohci_hcd *ohci)
{
return 0;
}
+static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
+{
+ return 0;
+}
#endif
/* convert between an hcd pointer and the corresponding ohci_hcd */
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a949259f18b9..5b22a4d1c9e4 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -719,8 +719,12 @@ retry:
/* port status seems weird until after reset, so
* force the reset and make khubd clean up later.
*/
- sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION)
- | (1 << USB_PORT_FEAT_CONNECTION);
+ if (sl811->stat_insrmv & 1)
+ sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION;
+ else
+ sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION);
+
+ sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION;
} else if (irqstat & SL11H_INTMASK_RD) {
if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) {
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 274751b4409c..eb37d86bafef 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
spin_lock_irq(&uhci->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
rc = -ESHUTDOWN;
- else if (!uhci->dead)
+ else if (uhci->dead)
+ ; /* Dead controllers tell no tales */
+
+ /* Once the controller is stopped, port resumes that are already
+ * in progress won't complete. Hence if remote wakeup is enabled
+ * for the root hub and any ports are in the middle of a resume or
+ * remote wakeup, we must fail the suspend.
+ */
+ else if (hcd->self.root_hub->do_remote_wakeup &&
+ uhci->resuming_ports) {
+ dev_dbg(uhci_dev(uhci), "suspend failed because a port "
+ "is resuming\n");
+ rc = -EBUSY;
+ } else
suspend_rh(uhci, UHCI_RH_SUSPENDED);
spin_unlock_irq(&uhci->lock);
return rc;
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 885b585360b9..8270055848ca 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -167,7 +167,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
/* Port received a wakeup request */
set_bit(port, &uhci->resuming_ports);
uhci->ports_timeout = jiffies +
- msecs_to_jiffies(20);
+ msecs_to_jiffies(25);
/* Make sure we see the port again
* after the resuming period is over. */
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 705e34324156..33128d52f212 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -413,7 +413,8 @@ void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
int i;
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
- dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx);
+ dma_addr_t dma = ctx->dma +
+ ((unsigned long)slot_ctx - (unsigned long)ctx->bytes);
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
xhci_dbg(xhci, "Slot Context:\n");
@@ -459,7 +460,7 @@ void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
for (i = 0; i < last_ep_ctx; ++i) {
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
dma_addr_t dma = ctx->dma +
- ((unsigned long)ep_ctx - (unsigned long)ctx);
+ ((unsigned long)ep_ctx - (unsigned long)ctx->bytes);
xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index 816c39caca1c..e478a63488fb 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -22,12 +22,18 @@
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include "xhci.h"
#define DRIVER_AUTHOR "Sarah Sharp"
#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
+/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
+static int link_quirk;
+module_param(link_quirk, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
+
/* TODO: copied from ehci-hcd.c - can this be refactored? */
/*
* handshake - spin reading hc until handshake completes or fails
@@ -214,6 +220,12 @@ int xhci_init(struct usb_hcd *hcd)
xhci_dbg(xhci, "xhci_init\n");
spin_lock_init(&xhci->lock);
+ if (link_quirk) {
+ xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n");
+ xhci->quirks |= XHCI_LINK_TRB_QUIRK;
+ } else {
+ xhci_dbg(xhci, "xHCI doesn't need link TRB QUIRK\n");
+ }
retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg(xhci, "Finished xhci_init\n");
@@ -555,13 +567,22 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc)
return 1 << (xhci_get_endpoint_index(desc) + 1);
}
+/* Find the flag for this endpoint (for use in the control context). Use the
+ * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is
+ * bit 1, etc.
+ */
+unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
+{
+ return 1 << (ep_index + 1);
+}
+
/* Compute the last valid endpoint context index. Basically, this is the
* endpoint index plus one. For slot contexts with more than valid endpoint,
* we find the most significant bit set in the added contexts flags.
* e.g. ep 1 IN (with epnum 0x81) => added_ctxs = 0b1000
* fls(0b1000) = 4, but the endpoint context index is 3, so subtract one.
*/
-static inline unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
+unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
{
return fls(added_ctxs) - 1;
}
@@ -589,6 +610,70 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
return 1;
}
+static int xhci_configure_endpoint(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev,
+ bool ctx_change);
+
+/*
+ * Full speed devices may have a max packet size greater than 8 bytes, but the
+ * USB core doesn't know that until it reads the first 8 bytes of the
+ * descriptor. If the usb_device's max packet size changes after that point,
+ * we need to issue an evaluate context command and wait on it.
+ */
+static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
+ unsigned int ep_index, struct urb *urb)
+{
+ struct xhci_container_ctx *in_ctx;
+ struct xhci_container_ctx *out_ctx;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_ep_ctx *ep_ctx;
+ int max_packet_size;
+ int hw_max_packet_size;
+ int ret = 0;
+
+ out_ctx = xhci->devs[slot_id]->out_ctx;
+ ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
+ hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
+ max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
+ if (hw_max_packet_size != max_packet_size) {
+ xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
+ xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
+ max_packet_size);
+ xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n",
+ hw_max_packet_size);
+ xhci_dbg(xhci, "Issuing evaluate context command.\n");
+
+ /* Set up the modified control endpoint 0 */
+ xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
+ in_ctx = xhci->devs[slot_id]->in_ctx;
+ ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
+ ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
+ ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
+
+ /* Set up the input context flags for the command */
+ /* FIXME: This won't work if a non-default control endpoint
+ * changes max packet sizes.
+ */
+ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ ctrl_ctx->add_flags = EP0_FLAG;
+ ctrl_ctx->drop_flags = 0;
+
+ xhci_dbg(xhci, "Slot %d input context\n", slot_id);
+ xhci_dbg_ctx(xhci, in_ctx, ep_index);
+ xhci_dbg(xhci, "Slot %d output context\n", slot_id);
+ xhci_dbg_ctx(xhci, out_ctx, ep_index);
+
+ ret = xhci_configure_endpoint(xhci, urb->dev,
+ xhci->devs[slot_id], true);
+
+ /* Clean up the input context for later use by bandwidth
+ * functions.
+ */
+ ctrl_ctx->add_flags = SLOT_FLAG;
+ }
+ return ret;
+}
+
/*
* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
@@ -600,13 +685,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
int ret = 0;
unsigned int slot_id, ep_index;
+
if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
return -EINVAL;
slot_id = urb->dev->slot_id;
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
- spin_lock_irqsave(&xhci->lock, flags);
if (!xhci->devs || !xhci->devs[slot_id]) {
if (!in_interrupt())
dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
@@ -619,19 +704,38 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
ret = -ESHUTDOWN;
goto exit;
}
- if (usb_endpoint_xfer_control(&urb->ep->desc))
+ if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+ /* Check to see if the max packet size for the default control
+ * endpoint changed during FS device enumeration
+ */
+ if (urb->dev->speed == USB_SPEED_FULL) {
+ ret = xhci_check_maxpacket(xhci, slot_id,
+ ep_index, urb);
+ if (ret < 0)
+ return ret;
+ }
+
/* We have a spinlock and interrupts disabled, so we must pass
* atomic context to this function, which may allocate memory.
*/
+ spin_lock_irqsave(&xhci->lock, flags);
ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
- else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
+ spin_lock_irqsave(&xhci->lock, flags);
ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
- else
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
+ spin_lock_irqsave(&xhci->lock, flags);
+ ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
+ slot_id, ep_index);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else {
ret = -EINVAL;
+ }
exit:
- spin_unlock_irqrestore(&xhci->lock, flags);
return ret;
}
@@ -930,6 +1034,122 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
}
}
+static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev)
+{
+ int ret;
+
+ switch (virt_dev->cmd_status) {
+ case COMP_ENOMEM:
+ dev_warn(&udev->dev, "Not enough host controller resources "
+ "for new device state.\n");
+ ret = -ENOMEM;
+ /* FIXME: can we allocate more resources for the HC? */
+ break;
+ case COMP_BW_ERR:
+ dev_warn(&udev->dev, "Not enough bandwidth "
+ "for new device state.\n");
+ ret = -ENOSPC;
+ /* FIXME: can we go back to the old state? */
+ break;
+ case COMP_TRB_ERR:
+ /* the HCD set up something wrong */
+ dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, "
+ "add flag = 1, "
+ "and endpoint is not disabled.\n");
+ ret = -EINVAL;
+ break;
+ case COMP_SUCCESS:
+ dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
+ ret = 0;
+ break;
+ default:
+ xhci_err(xhci, "ERROR: unexpected command completion "
+ "code 0x%x.\n", virt_dev->cmd_status);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev)
+{
+ int ret;
+
+ switch (virt_dev->cmd_status) {
+ case COMP_EINVAL:
+ dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
+ "context command.\n");
+ ret = -EINVAL;
+ break;
+ case COMP_EBADSLT:
+ dev_warn(&udev->dev, "WARN: slot not enabled for"
+ "evaluate context command.\n");
+ case COMP_CTX_STATE:
+ dev_warn(&udev->dev, "WARN: invalid context state for "
+ "evaluate context command.\n");
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
+ ret = -EINVAL;
+ break;
+ case COMP_SUCCESS:
+ dev_dbg(&udev->dev, "Successful evaluate context command\n");
+ ret = 0;
+ break;
+ default:
+ xhci_err(xhci, "ERROR: unexpected command completion "
+ "code 0x%x.\n", virt_dev->cmd_status);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+/* Issue a configure endpoint command or evaluate context command
+ * and wait for it to finish.
+ */
+static int xhci_configure_endpoint(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev,
+ bool ctx_change)
+{
+ int ret;
+ int timeleft;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ if (!ctx_change)
+ ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
+ udev->slot_id);
+ else
+ ret = xhci_queue_evaluate_context(xhci, virt_dev->in_ctx->dma,
+ udev->slot_id);
+ if (ret < 0) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
+ return -ENOMEM;
+ }
+ xhci_ring_cmd_db(xhci);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ /* Wait for the configure endpoint command to complete */
+ timeleft = wait_for_completion_interruptible_timeout(
+ &virt_dev->cmd_completion,
+ USB_CTRL_SET_TIMEOUT);
+ if (timeleft <= 0) {
+ xhci_warn(xhci, "%s while waiting for %s command\n",
+ timeleft == 0 ? "Timeout" : "Signal",
+ ctx_change == 0 ?
+ "configure endpoint" :
+ "evaluate context");
+ /* FIXME cancel the configure endpoint command */
+ return -ETIME;
+ }
+
+ if (!ctx_change)
+ return xhci_configure_endpoint_result(xhci, udev, virt_dev);
+ return xhci_evaluate_context_result(xhci, udev, virt_dev);
+}
+
/* Called after one or more calls to xhci_add_endpoint() or
* xhci_drop_endpoint(). If this call fails, the USB core is expected
* to call xhci_reset_bandwidth().
@@ -944,8 +1164,6 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
int i;
int ret = 0;
- int timeleft;
- unsigned long flags;
struct xhci_hcd *xhci;
struct xhci_virt_device *virt_dev;
struct xhci_input_control_ctx *ctrl_ctx;
@@ -975,56 +1193,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
- spin_lock_irqsave(&xhci->lock, flags);
- ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
- udev->slot_id);
- if (ret < 0) {
- spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
- return -ENOMEM;
- }
- xhci_ring_cmd_db(xhci);
- spin_unlock_irqrestore(&xhci->lock, flags);
-
- /* Wait for the configure endpoint command to complete */
- timeleft = wait_for_completion_interruptible_timeout(
- &virt_dev->cmd_completion,
- USB_CTRL_SET_TIMEOUT);
- if (timeleft <= 0) {
- xhci_warn(xhci, "%s while waiting for configure endpoint command\n",
- timeleft == 0 ? "Timeout" : "Signal");
- /* FIXME cancel the configure endpoint command */
- return -ETIME;
- }
-
- switch (virt_dev->cmd_status) {
- case COMP_ENOMEM:
- dev_warn(&udev->dev, "Not enough host controller resources "
- "for new device state.\n");
- ret = -ENOMEM;
- /* FIXME: can we allocate more resources for the HC? */
- break;
- case COMP_BW_ERR:
- dev_warn(&udev->dev, "Not enough bandwidth "
- "for new device state.\n");
- ret = -ENOSPC;
- /* FIXME: can we go back to the old state? */
- break;
- case COMP_TRB_ERR:
- /* the HCD set up something wrong */
- dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, add flag = 1, "
- "and endpoint is not disabled.\n");
- ret = -EINVAL;
- break;
- case COMP_SUCCESS:
- dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
- break;
- default:
- xhci_err(xhci, "ERROR: unexpected command completion "
- "code 0x%x.\n", virt_dev->cmd_status);
- ret = -EINVAL;
- break;
- }
+ ret = xhci_configure_endpoint(xhci, udev, virt_dev, false);
if (ret) {
/* Callee should call reset_bandwidth() */
return ret;
@@ -1075,6 +1244,75 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
xhci_zero_in_ctx(xhci, virt_dev);
}
+void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+ struct xhci_dequeue_state *deq_state)
+{
+ struct xhci_container_ctx *in_ctx;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_ep_ctx *ep_ctx;
+ u32 added_ctxs;
+ dma_addr_t addr;
+
+ xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
+ in_ctx = xhci->devs[slot_id]->in_ctx;
+ ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
+ addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
+ deq_state->new_deq_ptr);
+ if (addr == 0) {
+ xhci_warn(xhci, "WARN Cannot submit config ep after "
+ "reset ep command\n");
+ xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
+ deq_state->new_deq_seg,
+ deq_state->new_deq_ptr);
+ return;
+ }
+ ep_ctx->deq = addr | deq_state->new_cycle_state;
+
+ xhci_slot_copy(xhci, xhci->devs[slot_id]);
+
+ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
+ ctrl_ctx->add_flags = added_ctxs | SLOT_FLAG;
+ ctrl_ctx->drop_flags = added_ctxs;
+
+ xhci_dbg(xhci, "Slot ID %d Input Context:\n", slot_id);
+ xhci_dbg_ctx(xhci, in_ctx, ep_index);
+}
+
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ unsigned int ep_index, struct xhci_ring *ep_ring)
+{
+ struct xhci_dequeue_state deq_state;
+
+ xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
+ /* We need to move the HW's dequeue pointer past this TD,
+ * or it will attempt to resend it on the next doorbell ring.
+ */
+ xhci_find_new_dequeue_state(xhci, udev->slot_id,
+ ep_index, ep_ring->stopped_td,
+ &deq_state);
+
+ /* HW with the reset endpoint quirk will use the saved dequeue state to
+ * issue a configure endpoint command later.
+ */
+ if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
+ xhci_dbg(xhci, "Queueing new dequeue state\n");
+ xhci_queue_new_dequeue_state(xhci, ep_ring,
+ udev->slot_id,
+ ep_index, &deq_state);
+ } else {
+ /* Better hope no one uses the input context between now and the
+ * reset endpoint completion!
+ */
+ xhci_dbg(xhci, "Setting up input context for "
+ "configure endpoint command\n");
+ xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
+ ep_index, &deq_state);
+ }
+}
+
/* Deal with stalled endpoints. The core should have sent the control message
* to clear the halt condition. However, we need to make the xHCI hardware
* reset its sequence number, since a device will expect a sequence number of
@@ -1089,7 +1327,6 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
unsigned int ep_index;
unsigned long flags;
int ret;
- struct xhci_dequeue_state deq_state;
struct xhci_ring *ep_ring;
xhci = hcd_to_xhci(hcd);
@@ -1106,6 +1343,10 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
ep->desc.bEndpointAddress);
return;
}
+ if (usb_endpoint_xfer_control(&ep->desc)) {
+ xhci_dbg(xhci, "Control endpoint stall already handled.\n");
+ return;
+ }
xhci_dbg(xhci, "Queueing reset endpoint command\n");
spin_lock_irqsave(&xhci->lock, flags);
@@ -1116,16 +1357,7 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
* command. Better hope that last command worked!
*/
if (!ret) {
- xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
- /* We need to move the HW's dequeue pointer past this TD,
- * or it will attempt to resend it on the next doorbell ring.
- */
- xhci_find_new_dequeue_state(xhci, udev->slot_id,
- ep_index, ep_ring->stopped_td, &deq_state);
- xhci_dbg(xhci, "Queueing new dequeue state\n");
- xhci_queue_new_dequeue_state(xhci, ep_ring,
- udev->slot_id,
- ep_index, &deq_state);
+ xhci_cleanup_stalled_ring(xhci, udev, ep_index, ep_ring);
kfree(ep_ring->stopped_td);
xhci_ring_cmd_db(xhci);
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index e6b9a1c6002d..21146486fdb2 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -94,6 +94,9 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
val &= ~TRB_TYPE_BITMASK;
val |= TRB_TYPE(TRB_LINK);
+ /* Always set the chain bit with 0.95 hardware */
+ if (xhci_link_trb_quirk(xhci))
+ val |= TRB_CHAIN;
prev->trbs[TRBS_PER_SEGMENT-1].link.control = val;
}
xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n",
@@ -398,15 +401,28 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
/* Step 5 */
ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP);
/*
- * See section 4.3 bullet 6:
- * The default Max Packet size for ep0 is "8 bytes for a USB2
- * LS/FS/HS device or 512 bytes for a USB3 SS device"
* XXX: Not sure about wireless USB devices.
*/
- if (udev->speed == USB_SPEED_SUPER)
+ switch (udev->speed) {
+ case USB_SPEED_SUPER:
ep0_ctx->ep_info2 |= MAX_PACKET(512);
- else
+ break;
+ case USB_SPEED_HIGH:
+ /* USB core guesses at a 64-byte max packet first for FS devices */
+ case USB_SPEED_FULL:
+ ep0_ctx->ep_info2 |= MAX_PACKET(64);
+ break;
+ case USB_SPEED_LOW:
ep0_ctx->ep_info2 |= MAX_PACKET(8);
+ break;
+ case USB_SPEED_VARIABLE:
+ xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
+ return -EINVAL;
+ break;
+ default:
+ /* New speed? */
+ BUG();
+ }
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
ep0_ctx->ep_info2 |= MAX_BURST(0);
ep0_ctx->ep_info2 |= ERROR_COUNT(3);
@@ -598,6 +614,44 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
*/
}
+/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy.
+ * Useful when you want to change one particular aspect of the endpoint and then
+ * issue a configure endpoint command.
+ */
+void xhci_endpoint_copy(struct xhci_hcd *xhci,
+ struct xhci_virt_device *vdev, unsigned int ep_index)
+{
+ struct xhci_ep_ctx *out_ep_ctx;
+ struct xhci_ep_ctx *in_ep_ctx;
+
+ out_ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ in_ep_ctx = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
+
+ in_ep_ctx->ep_info = out_ep_ctx->ep_info;
+ in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2;
+ in_ep_ctx->deq = out_ep_ctx->deq;
+ in_ep_ctx->tx_info = out_ep_ctx->tx_info;
+}
+
+/* Copy output xhci_slot_ctx to the input xhci_slot_ctx.
+ * Useful when you want to change one particular aspect of the endpoint and then
+ * issue a configure endpoint command. Only the context entries field matters,
+ * but we'll copy the whole thing anyway.
+ */
+void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev)
+{
+ struct xhci_slot_ctx *in_slot_ctx;
+ struct xhci_slot_ctx *out_slot_ctx;
+
+ in_slot_ctx = xhci_get_slot_ctx(xhci, vdev->in_ctx);
+ out_slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
+
+ in_slot_ctx->dev_info = out_slot_ctx->dev_info;
+ in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2;
+ in_slot_ctx->tt_info = out_slot_ctx->tt_info;
+ in_slot_ctx->dev_state = out_slot_ctx->dev_state;
+}
+
/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
{
@@ -702,9 +756,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
int i;
/* Free the Event Ring Segment Table and the actual Event Ring */
- xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
+ if (xhci->ir_set) {
+ xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
+ xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
+ xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
+ }
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries)
pci_free_consistent(pdev, size,
@@ -741,9 +797,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->dcbaa, xhci->dcbaa->dma);
xhci->dcbaa = NULL;
+ scratchpad_free(xhci);
xhci->page_size = 0;
xhci->page_shift = 0;
- scratchpad_free(xhci);
}
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 592fe7e623f7..8fb308d43bc1 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -24,6 +24,10 @@
#include "xhci.h"
+/* Device for a quirk */
+#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
+#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+
static const char hcd_name[] = "xhci_hcd";
/* called after powerup, by probe or system-pm "wakeup" */
@@ -62,6 +66,15 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
xhci_print_registers(xhci);
+ /* Look for vendor-specific quirks */
+ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+ pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+ pdev->revision == 0x0) {
+ xhci->quirks |= XHCI_RESET_EP_QUIRK;
+ xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
+ " endpoint cmd after reset endpoint\n");
+ }
+
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index aa88a067148b..9874d9a60080 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -172,8 +172,9 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
* have their chain bit cleared (so that each Link TRB is a separate TD).
*
* Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit
- * set, but other sections talk about dealing with the chain bit set.
- * Assume section 6.4.4.1 is wrong, and the chain bit can be set in a Link TRB.
+ * set, but other sections talk about dealing with the chain bit set. This was
+ * fixed in the 0.96 specification errata, but we have to assume that all 0.95
+ * xHCI hardware can't handle the chain bit being cleared on a link TRB.
*/
static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
{
@@ -191,8 +192,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
while (last_trb(xhci, ring, ring->enq_seg, next)) {
if (!consumer) {
if (ring != xhci->event_ring) {
- next->link.control &= ~TRB_CHAIN;
- next->link.control |= chain;
+ /* If we're not dealing with 0.95 hardware,
+ * carry over the chain bit of the previous TRB
+ * (which may mean the chain bit is cleared).
+ */
+ if (!xhci_link_trb_quirk(xhci)) {
+ next->link.control &= ~TRB_CHAIN;
+ next->link.control |= chain;
+ }
/* Give this link TRB to the hardware */
wmb();
if (next->link.control & TRB_CYCLE)
@@ -462,7 +469,6 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
* ring running.
*/
ep_ring->state |= SET_DEQ_PENDING;
- xhci_ring_cmd_db(xhci);
}
/*
@@ -531,6 +537,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
xhci_queue_new_dequeue_state(xhci, ep_ring,
slot_id, ep_index, &deq_state);
+ xhci_ring_cmd_db(xhci);
} else {
/* Otherwise just ring the doorbell to restart the ring */
ring_ep_doorbell(xhci, slot_id, ep_index);
@@ -644,18 +651,31 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
{
int slot_id;
unsigned int ep_index;
+ struct xhci_ring *ep_ring;
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+ ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
/* This command will only fail if the endpoint wasn't halted,
* but we don't care.
*/
xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
(unsigned int) GET_COMP_CODE(event->status));
- /* Clear our internal halted state and restart the ring */
- xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED;
- ring_ep_doorbell(xhci, slot_id, ep_index);
+ /* HW with the reset endpoint quirk needs to have a configure endpoint
+ * command complete before the endpoint can be used. Queue that here
+ * because the HW can't handle two commands being queued in a row.
+ */
+ if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
+ xhci_dbg(xhci, "Queueing configure endpoint command\n");
+ xhci_queue_configure_endpoint(xhci,
+ xhci->devs[slot_id]->in_ctx->dma, slot_id);
+ xhci_ring_cmd_db(xhci);
+ } else {
+ /* Clear our internal halted state and restart the ring */
+ ep_ring->state &= ~EP_HALTED;
+ ring_ep_doorbell(xhci, slot_id, ep_index);
+ }
}
static void handle_cmd_completion(struct xhci_hcd *xhci,
@@ -664,6 +684,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
int slot_id = TRB_TO_SLOT_ID(event->flags);
u64 cmd_dma;
dma_addr_t cmd_dequeue_dma;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ unsigned int ep_index;
+ struct xhci_ring *ep_ring;
+ unsigned int ep_state;
cmd_dma = event->cmd_trb;
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
@@ -691,6 +715,41 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
xhci_free_virt_device(xhci, slot_id);
break;
case TRB_TYPE(TRB_CONFIG_EP):
+ /*
+ * Configure endpoint commands can come from the USB core
+ * configuration or alt setting changes, or because the HW
+ * needed an extra configure endpoint command after a reset
+ * endpoint command. In the latter case, the xHCI driver is
+ * not waiting on the configure endpoint command.
+ */
+ ctrl_ctx = xhci_get_input_control_ctx(xhci,
+ xhci->devs[slot_id]->in_ctx);
+ /* Input ctx add_flags are the endpoint index plus one */
+ ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
+ ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
+ if (!ep_ring) {
+ /* This must have been an initial configure endpoint */
+ xhci->devs[slot_id]->cmd_status =
+ GET_COMP_CODE(event->status);
+ complete(&xhci->devs[slot_id]->cmd_completion);
+ break;
+ }
+ ep_state = ep_ring->state;
+ xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, "
+ "state = %d\n", ep_index, ep_state);
+ if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
+ ep_state & EP_HALTED) {
+ /* Clear our internal halted state and restart ring */
+ xhci->devs[slot_id]->ep_rings[ep_index]->state &=
+ ~EP_HALTED;
+ ring_ep_doorbell(xhci, slot_id, ep_index);
+ } else {
+ xhci->devs[slot_id]->cmd_status =
+ GET_COMP_CODE(event->status);
+ complete(&xhci->devs[slot_id]->cmd_completion);
+ }
+ break;
+ case TRB_TYPE(TRB_EVAL_CONTEXT):
xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
complete(&xhci->devs[slot_id]->cmd_completion);
break;
@@ -763,9 +822,11 @@ static struct xhci_segment *trb_in_td(
cur_seg = start_seg;
do {
+ if (start_dma == 0)
+ return 0;
/* We may get an event for a Link TRB in the middle of a TD */
end_seg_dma = xhci_trb_virt_to_dma(cur_seg,
- &start_seg->trbs[TRBS_PER_SEGMENT - 1]);
+ &cur_seg->trbs[TRBS_PER_SEGMENT - 1]);
/* If the end TRB isn't in this segment, this is set to 0 */
end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb);
@@ -792,8 +853,9 @@ static struct xhci_segment *trb_in_td(
}
cur_seg = cur_seg->next;
start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]);
- } while (1);
+ } while (cur_seg != start_seg);
+ return 0;
}
/*
@@ -806,6 +868,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
{
struct xhci_virt_device *xdev;
struct xhci_ring *ep_ring;
+ unsigned int slot_id;
int ep_index;
struct xhci_td *td = 0;
dma_addr_t event_dma;
@@ -814,9 +877,11 @@ static int handle_tx_event(struct xhci_hcd *xhci,
struct urb *urb = 0;
int status = -EINPROGRESS;
struct xhci_ep_ctx *ep_ctx;
+ u32 trb_comp_code;
xhci_dbg(xhci, "In %s\n", __func__);
- xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
+ slot_id = TRB_TO_SLOT_ID(event->flags);
+ xdev = xhci->devs[slot_id];
if (!xdev) {
xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
return -ENODEV;
@@ -870,7 +935,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
(unsigned int) event->flags);
/* Look for common error cases */
- switch (GET_COMP_CODE(event->transfer_len)) {
+ trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ switch (trb_comp_code) {
/* Skip codes that require special handling depending on
* transfer type
*/
@@ -913,7 +979,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
/* Was this a control transfer? */
if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
xhci_debug_trb(xhci, xhci->event_ring->dequeue);
- switch (GET_COMP_CODE(event->transfer_len)) {
+ switch (trb_comp_code) {
case COMP_SUCCESS:
if (event_trb == ep_ring->dequeue) {
xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n");
@@ -928,8 +994,39 @@ static int handle_tx_event(struct xhci_hcd *xhci,
break;
case COMP_SHORT_TX:
xhci_warn(xhci, "WARN: short transfer on control ep\n");
- status = -EREMOTEIO;
+ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+ status = -EREMOTEIO;
+ else
+ status = 0;
break;
+ case COMP_BABBLE:
+ /* The 0.96 spec says a babbling control endpoint
+ * is not halted. The 0.96 spec says it is. Some HW
+ * claims to be 0.95 compliant, but it halts the control
+ * endpoint anyway. Check if a babble halted the
+ * endpoint.
+ */
+ if (ep_ctx->ep_info != EP_STATE_HALTED)
+ break;
+ /* else fall through */
+ case COMP_STALL:
+ /* Did we transfer part of the data (middle) phase? */
+ if (event_trb != ep_ring->dequeue &&
+ event_trb != td->last_trb)
+ td->urb->actual_length =
+ td->urb->transfer_buffer_length
+ - TRB_LEN(event->transfer_len);
+ else
+ td->urb->actual_length = 0;
+
+ ep_ring->stopped_td = td;
+ ep_ring->stopped_trb = event_trb;
+ xhci_queue_reset_ep(xhci, slot_id, ep_index);
+ xhci_cleanup_stalled_ring(xhci,
+ td->urb->dev,
+ ep_index, ep_ring);
+ xhci_ring_cmd_db(xhci);
+ goto td_cleanup;
default:
/* Others already handled above */
break;
@@ -943,7 +1040,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (event_trb == td->last_trb) {
if (td->urb->actual_length != 0) {
/* Don't overwrite a previously set error code */
- if (status == -EINPROGRESS || status == 0)
+ if ((status == -EINPROGRESS ||
+ status == 0) &&
+ (td->urb->transfer_flags
+ & URB_SHORT_NOT_OK))
/* Did we already see a short data stage? */
status = -EREMOTEIO;
} else {
@@ -952,7 +1052,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
}
} else {
/* Maybe the event was for the data stage? */
- if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
+ if (trb_comp_code != COMP_STOP_INVAL) {
/* We didn't stop on a link TRB in the middle */
td->urb->actual_length =
td->urb->transfer_buffer_length -
@@ -964,7 +1064,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
}
}
} else {
- switch (GET_COMP_CODE(event->transfer_len)) {
+ switch (trb_comp_code) {
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
if (event_trb != td->last_trb) {
@@ -975,7 +1075,12 @@ static int handle_tx_event(struct xhci_hcd *xhci,
else
status = 0;
} else {
- xhci_dbg(xhci, "Successful bulk transfer!\n");
+ if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
+ xhci_dbg(xhci, "Successful bulk "
+ "transfer!\n");
+ else
+ xhci_dbg(xhci, "Successful interrupt "
+ "transfer!\n");
status = 0;
}
break;
@@ -1001,11 +1106,17 @@ static int handle_tx_event(struct xhci_hcd *xhci,
td->urb->actual_length =
td->urb->transfer_buffer_length -
TRB_LEN(event->transfer_len);
- if (td->urb->actual_length < 0) {
+ if (td->urb->transfer_buffer_length <
+ td->urb->actual_length) {
xhci_warn(xhci, "HC gave bad length "
"of %d bytes left\n",
TRB_LEN(event->transfer_len));
td->urb->actual_length = 0;
+ if (td->urb->transfer_flags &
+ URB_SHORT_NOT_OK)
+ status = -EREMOTEIO;
+ else
+ status = 0;
}
/* Don't overwrite a previously set error code */
if (status == -EINPROGRESS) {
@@ -1041,14 +1152,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
/* If the ring didn't stop on a Link or No-op TRB, add
* in the actual bytes transferred from the Normal TRB
*/
- if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
+ if (trb_comp_code != COMP_STOP_INVAL)
td->urb->actual_length +=
TRB_LEN(cur_trb->generic.field[2]) -
TRB_LEN(event->transfer_len);
}
}
- if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
- GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
+ if (trb_comp_code == COMP_STOP_INVAL ||
+ trb_comp_code == COMP_STOP) {
/* The Endpoint Stop Command completion will take care of any
* stopped TDs. A stopped TD may be restarted, so don't update
* the ring dequeue pointer or take this TD off any lists yet.
@@ -1056,7 +1167,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_ring->stopped_td = td;
ep_ring->stopped_trb = event_trb;
} else {
- if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
+ if (trb_comp_code == COMP_STALL ||
+ trb_comp_code == COMP_BABBLE) {
/* The transfer is completed from the driver's
* perspective, but we need to issue a set dequeue
* command for this stalled endpoint to move the dequeue
@@ -1072,16 +1184,41 @@ static int handle_tx_event(struct xhci_hcd *xhci,
inc_deq(xhci, ep_ring, false);
}
+td_cleanup:
/* Clean up the endpoint's TD list */
urb = td->urb;
+ /* Do one last check of the actual transfer length.
+ * If the host controller said we transferred more data than
+ * the buffer length, urb->actual_length will be a very big
+ * number (since it's unsigned). Play it safe and say we didn't
+ * transfer anything.
+ */
+ if (urb->actual_length > urb->transfer_buffer_length) {
+ xhci_warn(xhci, "URB transfer length is wrong, "
+ "xHC issue? req. len = %u, "
+ "act. len = %u\n",
+ urb->transfer_buffer_length,
+ urb->actual_length);
+ urb->actual_length = 0;
+ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+ status = -EREMOTEIO;
+ else
+ status = 0;
+ }
list_del(&td->td_list);
/* Was this TD slated to be cancelled but completed anyway? */
if (!list_empty(&td->cancelled_td_list)) {
list_del(&td->cancelled_td_list);
ep_ring->cancels_pending--;
}
- /* Leave the TD around for the reset endpoint function to use */
- if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
+ /* Leave the TD around for the reset endpoint function to use
+ * (but only if it's not a control endpoint, since we already
+ * queued the Set TR dequeue pointer command for stalled
+ * control endpoints).
+ */
+ if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+ (trb_comp_code != COMP_STALL &&
+ trb_comp_code != COMP_BABBLE)) {
kfree(td);
}
urb->hcpriv = NULL;
@@ -1094,7 +1231,7 @@ cleanup:
if (urb) {
usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
- urb, td->urb->actual_length, status);
+ urb, urb->actual_length, status);
spin_unlock(&xhci->lock);
usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
spin_lock(&xhci->lock);
@@ -1335,6 +1472,47 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
ring_ep_doorbell(xhci, slot_id, ep_index);
}
+/*
+ * xHCI uses normal TRBs for both bulk and interrupt. When the interrupt
+ * endpoint is to be serviced, the xHC will consume (at most) one TD. A TD
+ * (comprised of sg list entries) can take several service intervals to
+ * transmit.
+ */
+int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+ struct urb *urb, int slot_id, unsigned int ep_index)
+{
+ struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci,
+ xhci->devs[slot_id]->out_ctx, ep_index);
+ int xhci_interval;
+ int ep_interval;
+
+ xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
+ ep_interval = urb->interval;
+ /* Convert to microframes */
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL)
+ ep_interval *= 8;
+ /* FIXME change this to a warning and a suggestion to use the new API
+ * to set the polling interval (once the API is added).
+ */
+ if (xhci_interval != ep_interval) {
+ if (!printk_ratelimit())
+ dev_dbg(&urb->dev->dev, "Driver uses different interval"
+ " (%d microframe%s) than xHCI "
+ "(%d microframe%s)\n",
+ ep_interval,
+ ep_interval == 1 ? "" : "s",
+ xhci_interval,
+ xhci_interval == 1 ? "" : "s");
+ urb->interval = xhci_interval;
+ /* Convert back to frames for LS/FS devices */
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL)
+ urb->interval /= 8;
+ }
+ return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+}
+
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
{
@@ -1733,6 +1911,15 @@ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
}
+/* Queue an evaluate context command TRB */
+int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id)
+{
+ return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+ upper_32_bits(in_ctx_ptr), 0,
+ TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id));
+}
+
int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
unsigned int ep_index)
{
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index d31d32206ba3..808584153579 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -581,6 +581,7 @@ struct xhci_ep_ctx {
/* bit 15 is Linear Stream Array */
/* Interval - period between requests to an endpoint - 125u increments. */
#define EP_INTERVAL(p) ((p & 0xff) << 16)
+#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff))
/* ep_info2 bitmasks */
/*
@@ -589,6 +590,7 @@ struct xhci_ep_ctx {
*/
#define FORCE_EVENT (0x1)
#define ERROR_COUNT(p) (((p) & 0x3) << 1)
+#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7)
#define EP_TYPE(p) ((p) << 3)
#define ISOC_OUT_EP 1
#define BULK_OUT_EP 2
@@ -601,6 +603,8 @@ struct xhci_ep_ctx {
/* bit 7 is Host Initiate Disable - for disabling stream selection */
#define MAX_BURST(p) (((p)&0xff) << 8)
#define MAX_PACKET(p) (((p)&0xffff) << 16)
+#define MAX_PACKET_MASK (0xffff << 16)
+#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff)
/**
@@ -926,6 +930,12 @@ struct xhci_td {
union xhci_trb *last_trb;
};
+struct xhci_dequeue_state {
+ struct xhci_segment *new_deq_seg;
+ union xhci_trb *new_deq_ptr;
+ int new_cycle_state;
+};
+
struct xhci_ring {
struct xhci_segment *first_seg;
union xhci_trb *enqueue;
@@ -952,12 +962,6 @@ struct xhci_ring {
u32 cycle_state;
};
-struct xhci_dequeue_state {
- struct xhci_segment *new_deq_seg;
- union xhci_trb *new_deq_ptr;
- int new_cycle_state;
-};
-
struct xhci_erst_entry {
/* 64-bit event ring segment address */
u64 seg_addr;
@@ -1058,6 +1062,9 @@ struct xhci_hcd {
int noops_submitted;
int noops_handled;
int error_bitmask;
+ unsigned int quirks;
+#define XHCI_LINK_TRB_QUIRK (1 << 0)
+#define XHCI_RESET_EP_QUIRK (1 << 1)
};
/* For testing purposes */
@@ -1136,6 +1143,13 @@ static inline void xhci_write_64(struct xhci_hcd *xhci,
writel(val_hi, ptr + 1);
}
+static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
+{
+ u32 temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
+ return ((HC_VERSION(temp) == 0x95) &&
+ (xhci->quirks & XHCI_LINK_TRB_QUIRK));
+}
+
/* xHCI debugging */
void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
void xhci_print_registers(struct xhci_hcd *xhci);
@@ -1158,7 +1172,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
+unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
+unsigned int xhci_last_valid_endpoint(u32 added_ctxs);
void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
+void xhci_endpoint_copy(struct xhci_hcd *xhci,
+ struct xhci_virt_device *vdev, unsigned int ep_index);
+void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev);
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
struct usb_device *udev, struct usb_host_endpoint *ep,
gfp_t mem_flags);
@@ -1205,8 +1224,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
int slot_id, unsigned int ep_index);
int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
int slot_id, unsigned int ep_index);
+int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
+ int slot_id, unsigned int ep_index);
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id);
+int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id);
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
unsigned int ep_index);
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
@@ -1215,6 +1238,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
struct xhci_ring *ep_ring, unsigned int slot_id,
unsigned int ep_index, struct xhci_dequeue_state *deq_state);
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ unsigned int ep_index, struct xhci_ring *ep_ring);
+void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+ struct xhci_dequeue_state *deq_state);
/* xHCI roothub code */
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 1d8e39a557d9..62ff5e729110 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -72,8 +72,8 @@ struct appledisplay {
struct usb_device *udev; /* usb device */
struct urb *urb; /* usb request block */
struct backlight_device *bd; /* backlight device */
- char *urbdata; /* interrupt URB data buffer */
- char *msgdata; /* control message data buffer */
+ u8 *urbdata; /* interrupt URB data buffer */
+ u8 *msgdata; /* control message data buffer */
struct delayed_work work;
int button_pressed;
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 602ee05ba9ff..59860b328534 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -167,7 +167,7 @@ static int emi62_load_firmware (struct usb_device *dev)
err("%s - error loading firmware: error = %d", __func__, err);
goto wraperr;
}
- } while (i > 0);
+ } while (rec);
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 0f7a30b7d2d1..fb1dd27be76d 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -350,12 +350,12 @@ static unsigned int mon_buff_area_alloc_contiguous(struct mon_reader_bin *rp,
/*
* Return a few (kilo-)bytes to the head of the buffer.
- * This is used if a DMA fetch fails.
+ * This is used if a data fetch fails.
*/
static void mon_buff_area_shrink(struct mon_reader_bin *rp, unsigned int size)
{
- size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
+ /* size &= ~(PKT_ALIGN-1); -- we're called with aligned size */
rp->b_cnt -= size;
if (rp->b_in < size)
rp->b_in += rp->b_size;
@@ -442,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
unsigned int urb_length;
unsigned int offset;
unsigned int length;
+ unsigned int delta;
unsigned int ndesc, lendesc;
unsigned char dir;
struct mon_bin_hdr *ep;
@@ -546,8 +547,10 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
if (length != 0) {
ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */
- ep->len_cap = 0;
- mon_buff_area_shrink(rp, length);
+ delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
+ ep->len_cap -= length;
+ delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
+ mon_buff_area_shrink(rp, delta);
}
} else {
ep->flag_data = data_tag;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 8b3c4e2ed7b8..74073f9a43f0 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -4,6 +4,7 @@
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
* Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2009 MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -436,14 +437,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
csr |= MUSB_TXCSR_P_WZC_BITS;
csr &= ~MUSB_TXCSR_P_SENTSTALL;
musb_writew(epio, MUSB_TXCSR, csr);
- if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
- dma->status = MUSB_DMA_STATUS_CORE_ABORT;
- musb->dma_controller->channel_abort(dma);
- }
-
- if (request)
- musb_g_giveback(musb_ep, request, -EPIPE);
-
break;
}
@@ -582,15 +575,25 @@ void musb_g_tx(struct musb *musb, u8 epnum)
*/
static void rxstate(struct musb *musb, struct musb_request *req)
{
- u16 csr = 0;
const u8 epnum = req->epnum;
struct usb_request *request = &req->request;
struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
void __iomem *epio = musb->endpoints[epnum].regs;
unsigned fifo_count = 0;
u16 len = musb_ep->packet_sz;
+ u16 csr = musb_readw(epio, MUSB_RXCSR);
- csr = musb_readw(epio, MUSB_RXCSR);
+ /* We shouldn't get here while DMA is active, but we do... */
+ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
+ DBG(4, "DMA pending...\n");
+ return;
+ }
+
+ if (csr & MUSB_RXCSR_P_SENDSTALL) {
+ DBG(5, "%s stalling, RXCSR %04x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
if (is_cppi_enabled() && musb_ep->dma) {
struct dma_controller *c = musb->dma_controller;
@@ -761,19 +764,10 @@ void musb_g_rx(struct musb *musb, u8 epnum)
csr, dma ? " (dma)" : "", request);
if (csr & MUSB_RXCSR_P_SENTSTALL) {
- if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
- dma->status = MUSB_DMA_STATUS_CORE_ABORT;
- (void) musb->dma_controller->channel_abort(dma);
- request->actual += musb_ep->dma->actual_len;
- }
-
csr |= MUSB_RXCSR_P_WZC_BITS;
csr &= ~MUSB_RXCSR_P_SENTSTALL;
musb_writew(epio, MUSB_RXCSR, csr);
-
- if (request)
- musb_g_giveback(musb_ep, request, -EPIPE);
- goto done;
+ return;
}
if (csr & MUSB_RXCSR_P_OVERRUN) {
@@ -795,7 +789,7 @@ void musb_g_rx(struct musb *musb, u8 epnum)
DBG((csr & MUSB_RXCSR_DMAENAB) ? 4 : 1,
"%s busy, csr %04x\n",
musb_ep->end_point.name, csr);
- goto done;
+ return;
}
if (dma && (csr & MUSB_RXCSR_DMAENAB)) {
@@ -826,22 +820,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
if ((request->actual < request->length)
&& (musb_ep->dma->actual_len
== musb_ep->packet_sz))
- goto done;
+ return;
#endif
musb_g_giveback(musb_ep, request, 0);
request = next_request(musb_ep);
if (!request)
- goto done;
-
- /* don't start more i/o till the stall clears */
- musb_ep_select(mbase, epnum);
- csr = musb_readw(epio, MUSB_RXCSR);
- if (csr & MUSB_RXCSR_P_SENDSTALL)
- goto done;
+ return;
}
-
/* analyze request if the ep is hot */
if (request)
rxstate(musb, to_musb_request(request));
@@ -849,8 +836,6 @@ void musb_g_rx(struct musb *musb, u8 epnum)
DBG(3, "packet waiting for %s%s request\n",
musb_ep->desc ? "" : "inactive ",
musb_ep->end_point.name);
-
-done:
return;
}
@@ -1244,7 +1229,7 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
void __iomem *mbase;
unsigned long flags;
u16 csr;
- struct musb_request *request = NULL;
+ struct musb_request *request;
int status = 0;
if (!ep)
@@ -1260,24 +1245,29 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
musb_ep_select(mbase, epnum);
- /* cannot portably stall with non-empty FIFO */
request = to_musb_request(next_request(musb_ep));
- if (value && musb_ep->is_in) {
- csr = musb_readw(epio, MUSB_TXCSR);
- if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
- DBG(3, "%s fifo busy, cannot halt\n", ep->name);
- spin_unlock_irqrestore(&musb->lock, flags);
- return -EAGAIN;
+ if (value) {
+ if (request) {
+ DBG(3, "request in progress, cannot halt %s\n",
+ ep->name);
+ status = -EAGAIN;
+ goto done;
+ }
+ /* Cannot portably stall with non-empty FIFO */
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ DBG(3, "FIFO busy, cannot halt %s\n", ep->name);
+ status = -EAGAIN;
+ goto done;
+ }
}
-
}
/* set/clear the stall and toggle bits */
DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear");
if (musb_ep->is_in) {
csr = musb_readw(epio, MUSB_TXCSR);
- if (csr & MUSB_TXCSR_FIFONOTEMPTY)
- csr |= MUSB_TXCSR_FLUSHFIFO;
csr |= MUSB_TXCSR_P_WZC_BITS
| MUSB_TXCSR_CLRDATATOG;
if (value)
@@ -1300,14 +1290,13 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
musb_writew(epio, MUSB_RXCSR, csr);
}
-done:
-
/* maybe start the first request in the queue */
if (!musb_ep->busy && !value && request) {
DBG(3, "restarting the request\n");
musb_ep_restart(musb, request);
}
+done:
spin_unlock_irqrestore(&musb->lock, flags);
return status;
}
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 7a6778675ad3..677cc2ee9fd3 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -199,7 +199,6 @@ service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req)
{
musb_g_giveback(&musb->endpoints[0].ep_in, req, 0);
- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
}
/*
@@ -647,7 +646,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
break;
default:
- ERR("SetupEnd came in a wrong ep0stage %s",
+ ERR("SetupEnd came in a wrong ep0stage %s\n",
decode_ep0stage(musb->ep0_state));
}
csr = musb_readw(regs, MUSB_CSR0);
@@ -770,12 +769,18 @@ setup:
handled = service_zero_data_request(
musb, &setup);
+ /*
+ * We're expecting no data in any case, so
+ * always set the DATAEND bit -- doing this
+ * here helps avoid SetupEnd interrupt coming
+ * in the idle stage when we're stalling...
+ */
+ musb->ackpend |= MUSB_CSR0_P_DATAEND;
+
/* status stage might be immediate */
- if (handled > 0) {
- musb->ackpend |= MUSB_CSR0_P_DATAEND;
+ if (handled > 0)
musb->ep0_state =
MUSB_EP0_STAGE_STATUSIN;
- }
break;
/* sequence #1 (IN to host), includes GET_STATUS
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index 81a2985632b6..6941e0565c03 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -34,7 +34,6 @@
#include <linux/init.h>
#include <linux/reboot.h>
#include <linux/timer.h>
-#include <linux/jiffies.h>
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/device.h>
@@ -62,8 +61,6 @@
#define DRIVER_DESC "Freescale USB OTG Driver"
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
-#define TIMER_FREQ 1000 /* 100 ms*/
-#define IDLE_TIME 5000 /* 1000 ms */
MODULE_DESCRIPTION("Freescale USB OTG Transceiver Driver");
@@ -93,13 +90,6 @@ static struct fsl_otg_config fsl_otg_initdata = {
.otg_port = 1,
};
-/* the timer is used to monitor the otg loading, if idle for some times
- * we will close the otg clk
- */
-static unsigned long last_busy;
-static bool clk_stopped;
-static struct timer_list monitor_timer;
-
int write_ulpi(u8 addr, u8 data)
{
u32 temp;
@@ -149,6 +139,15 @@ void fsl_otg_dischrg_vbus(int on)
/* A-device driver vbus, controlled through PP bit in PORTSC */
void fsl_otg_drv_vbus(struct fsl_usb2_platform_data *pdata, int on)
{
+/* if (on)
+ usb_dr_regs->portsc =
+ cpu_to_le32((le32_to_cpu(usb_dr_regs->portsc) &
+ ~PORTSC_W1C_BITS) | PORTSC_PORT_POWER);
+ else
+ usb_dr_regs->portsc =
+ cpu_to_le32(le32_to_cpu(usb_dr_regs->portsc) &
+ ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER);
+*/
if (pdata->xcvr_ops && pdata->xcvr_ops->set_vbus_power)
pdata->xcvr_ops->set_vbus_power(pdata->xcvr_ops, pdata, on);
}
@@ -399,61 +398,6 @@ int fsl_otg_tick_timer(void)
return expired;
}
-static void fsl_otg_clk_gate(bool on)
-{
- struct device *dev = fsl_otg_dev->otg.dev;
- struct fsl_usb2_platform_data *pdata;
-
- if (dev) {
- pdata = dev->platform_data;
- if (pdata && pdata->usb_clock_for_pm)
- pdata->usb_clock_for_pm(on);
- }
-}
-
-static void fsl_otg_clk_ctl(void)
-{
- if (clk_stopped){
- fsl_otg_clk_gate(true);
- clk_stopped = false;
- }
- last_busy = jiffies;
-}
-
-static void fsl_otg_loading_monitor(unsigned long data)
-{
- unsigned long now = jiffies;
- if (!clk_stopped){
- if (time_after(now, last_busy + msecs_to_jiffies(IDLE_TIME))){
- printk("otg is idle for some times,so we close the clock %x\n", le32_to_cpu(usb_dr_regs->otgsc));
- clk_stopped = true;
- fsl_otg_clk_gate(false);
- printk("close otg clk ok\n");
- }
- }
- mod_timer(&monitor_timer, jiffies + msecs_to_jiffies(TIMER_FREQ));
-}
-
-/**
- * Enable vbus interrupt
- * The otg cares USB_ID interrupt
- * The device cares B Sesstion Valid
- */
-static void b_session_irq_enable(bool enable)
-{
- int osc = le32_to_cpu(usb_dr_regs->otgsc);
- /* The other interrupts' status should not be cleared */
- osc &= ~(OTGSC_INTSTS_USB_ID | OTGSC_INTSTS_A_VBUS_VALID
- | OTGSC_INTSTS_A_SESSION_VALID | OTGSC_INTSTS_B_SESSION_VALID);
- osc |= OTGSC_INTSTS_B_SESSION_VALID;
-
- if (enable)
- osc |= OTGSC_INTR_B_SESSION_VALID_EN;
- else
- osc &= ~OTGSC_INTR_B_SESSION_VALID_EN;
- usb_dr_regs->otgsc = cpu_to_le32(osc);
-}
-
/* Reset controller, not reset the bus */
void otg_reset_controller(void)
{
@@ -540,6 +484,7 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
struct device *dev;
struct platform_driver *gadget_pdrv;
struct platform_device *gadget_pdev;
+
if (!xceiv->gadget || !xceiv->gadget->dev.parent)
return -ENODEV;
@@ -575,6 +520,7 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host)
if (host) {
VDBG("host off......\n");
+
otg_p->host->otg_port = fsl_otg_initdata.otg_port;
otg_p->host->is_b_host = otg_dev->fsm.id;
/* must leave time for khubd to finish its thing
@@ -691,29 +637,11 @@ static void fsl_otg_event(struct work_struct *work)
{
struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work);
struct otg_fsm *fsm = &og->fsm;
- struct otg_transceiver *otg = &og->otg;
-
- otg->default_a = (fsm->id == 0);
- /* clear conn information */
- if (fsm->id)
- fsm->b_conn = 0;
- else
- fsm->a_conn = 0;
-
- if (otg->host)
- otg->host->is_b_host = fsm->id;
- if (otg->gadget)
- otg->gadget->is_a_peripheral = !fsm->id;
if (fsm->id) { /* switch to gadget */
- b_session_irq_enable(true);
fsl_otg_start_host(fsm, 0);
otg_drv_vbus(fsm, 0);
fsl_otg_start_gadget(fsm, 1);
- }else { /* switch to host */
- fsl_otg_start_gadget(fsm, 0);
- otg_drv_vbus(fsm, 1);
- fsl_otg_start_host(fsm, 1);
}
}
@@ -753,13 +681,13 @@ irqreturn_t fsl_otg_isr_gpio(int irq, void *dev_id)
struct otg_fsm *fsm;
struct fsl_usb2_platform_data *pdata =
(struct fsl_usb2_platform_data *)dev_id;
- struct fsl_otg *f_otg;
+ struct fsl_otg *p_otg;
struct otg_transceiver *otg_trans = otg_get_transceiver();
int value;
- f_otg = container_of(otg_trans, struct fsl_otg, otg);
- fsm = &f_otg->fsm;
- fsl_otg_clk_ctl();
+ p_otg = container_of(otg_trans, struct fsl_otg, otg);
+ fsm = &p_otg->fsm;
+
if (pdata->id_gpio == 0)
return IRQ_NONE;
@@ -771,25 +699,35 @@ irqreturn_t fsl_otg_isr_gpio(int irq, void *dev_id)
set_irq_type(gpio_to_irq(pdata->id_gpio), IRQ_TYPE_LEVEL_HIGH);
- if (value == f_otg->fsm.id)
+ if (value == p_otg->fsm.id)
return IRQ_HANDLED;
- f_otg->fsm.id = value;
+ p_otg->fsm.id = value;
- cancel_delayed_work(&f_otg->otg_event);
- schedule_delayed_work(&f_otg->otg_event, msecs_to_jiffies(10));
- /* if host mode, we should clear B_SESSION_VLD event and disable
- * B_SESSION_VLD irq
- */
- if (!f_otg->fsm.id) {
- b_session_irq_enable(false);
- }else {
- //b_session_irq_enable(true);
- }
+ otg_trans->default_a = (fsm->id == 0);
+ /* clear conn information */
+ if (fsm->id)
+ fsm->b_conn = 0;
+ else
+ fsm->a_conn = 0;
+ if (otg_trans->host)
+ otg_trans->host->is_b_host = fsm->id;
+ if (otg_trans->gadget)
+ otg_trans->gadget->is_a_peripheral = !fsm->id;
+
+ VDBG("ID int (ID is %d)\n", fsm->id);
+ if (fsm->id) { /* switch to gadget */
+ schedule_delayed_work(&p_otg->otg_event, 100);
+
+ } else { /* switch to host */
+ cancel_delayed_work(&p_otg->otg_event);
+ fsl_otg_start_gadget(fsm, 0);
+ otg_drv_vbus(fsm, 1);
+ fsl_otg_start_host(fsm, 1);
+ }
return IRQ_HANDLED;
}
-
/* Interrupt handler. OTG/host/peripheral share the same int line.
* OTG driver clears OTGSC interrupts and leaves USB interrupts
* intact. It needs to have knowledge of some USB interrupts
@@ -797,65 +735,71 @@ irqreturn_t fsl_otg_isr_gpio(int irq, void *dev_id)
*/
irqreturn_t fsl_otg_isr(int irq, void *dev_id)
{
- struct fsl_otg *fotg = (struct fsl_otg *)dev_id;
- struct otg_transceiver *otg = &fotg->otg;
+ struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
+ struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg;
u32 otg_int_src, otg_sc;
- irqreturn_t ret = IRQ_NONE;
- fsl_otg_clk_ctl();
otg_sc = le32_to_cpu(usb_dr_regs->otgsc);
otg_int_src = otg_sc & OTGSC_INTSTS_MASK & (otg_sc >> 8);
- /* Only clear otg interrupts, expect B_SESSION_VALID,
- * Leave it to be handled by arcotg_udc */
- usb_dr_regs->otgsc = ((usb_dr_regs->otgsc | cpu_to_le32(otg_sc & OTGSC_INTSTS_MASK))&
- (~OTGSC_INTSTS_B_SESSION_VALID));
+ /* Only clear otg interrupts */
+ usb_dr_regs->otgsc |= cpu_to_le32(otg_sc & OTGSC_INTSTS_MASK);
/*FIXME: ID change not generate when init to 0 */
- fotg->fsm.id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
- otg->default_a = (fotg->fsm.id == 0);
+ fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
+ otg->default_a = (fsm->id == 0);
/* process OTG interrupts */
if (otg_int_src) {
if (otg_int_src & OTGSC_INTSTS_USB_ID) {
- fotg->fsm.id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
-
- printk("ID int (ID is %d)\n", fotg->fsm.id);
-
- cancel_delayed_work(&fotg->otg_event);
- schedule_delayed_work(&fotg->otg_event, msecs_to_jiffies(10));
- /* if host mode, we should clear B_SESSION_VLD event and disable
- * B_SESSION_VLD irq
- */
- if (!fotg->fsm.id) {
- b_session_irq_enable(false);
- }else {
- //b_session_irq_enable(true);
+ fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
+ otg->default_a = (fsm->id == 0);
+ /* clear conn information */
+ if (fsm->id)
+ fsm->b_conn = 0;
+ else
+ fsm->a_conn = 0;
+
+ if (otg->host)
+ otg->host->is_b_host = fsm->id;
+ if (otg->gadget)
+ otg->gadget->is_a_peripheral = !fsm->id;
+ VDBG("ID int (ID is %d)\n", fsm->id);
+
+ if (fsm->id) { /* switch to gadget */
+ schedule_delayed_work(&((struct fsl_otg *)
+ dev_id)->otg_event,
+ 100);
+ } else { /* switch to host */
+ cancel_delayed_work(&
+ ((struct fsl_otg *)dev_id)->
+ otg_event);
+ fsl_otg_start_gadget(fsm, 0);
+ otg_drv_vbus(fsm, 1);
+ fsl_otg_start_host(fsm, 1);
}
- ret = IRQ_HANDLED;
+
+ return IRQ_HANDLED;
}
}
- return ret;
+ return IRQ_NONE;
}
static void fsl_otg_fsm_drv_vbus(int on)
{
struct otg_fsm *fsm = &(fsl_otg_dev->fsm);
struct otg_transceiver *xceiv = fsm->transceiver;
+ struct device *dev = NULL;
- struct device *dev;
- /*
- * The host is assigned at otg_set_host
- */
- if (!xceiv->host)
+ if (!xceiv->host) {
return;
- /*
- * The dev is assigned at usb_create_hcd which is called earlier
- * than otg_set_host at host driver's probe
- */
+ }
+
dev = xceiv->host->controller;
+
fsl_otg_drv_vbus(dev->platform_data, on);
+
}
static struct otg_fsm_ops fsl_otg_ops = {
@@ -913,7 +857,6 @@ static int fsl_otg_conf(struct platform_device *pdev)
fsl_otg_tc->otg.set_power = fsl_otg_set_power;
fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp;
fsl_otg_tc->otg.start_srp = fsl_otg_start_srp;
- fsl_otg_tc->otg.dev = &pdev->dev;
fsl_otg_dev = fsl_otg_tc;
@@ -980,8 +923,6 @@ int usb_otg_start(struct platform_device *pdev)
if (pdata->platform_init && pdata->platform_init(pdev) != 0)
return -EINVAL;
- clk_stopped = false; /* platform_init will open the otg clk */
-
/* stop the controller */
temp = readl(&p_otg->dr_mem_map->usbcmd);
temp &= ~USB_CMD_RUN_STOP;
@@ -1308,10 +1249,6 @@ static int __init fsl_otg_probe(struct platform_device *pdev)
return -EIO;
}
- last_busy = jiffies;
- setup_timer(&monitor_timer, fsl_otg_loading_monitor, (unsigned long)pdev);
- mod_timer(&monitor_timer, jiffies + msecs_to_jiffies(TIMER_FREQ));
-
create_proc_file();
return status;
}
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index aec61880f36c..1a50beb32029 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -35,11 +35,6 @@ static struct usb_device_id id_table [] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-struct ark3116_private {
- spinlock_t lock;
- u8 termios_initialized;
-};
-
static inline void ARK3116_SND(struct usb_serial *serial, int seq,
__u8 request, __u8 requesttype,
__u16 value, __u16 index)
@@ -82,22 +77,11 @@ static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
static int ark3116_attach(struct usb_serial *serial)
{
char *buf;
- struct ark3116_private *priv;
- int i;
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
- spin_lock_init(&priv->lock);
-
- usb_set_serial_port_data(serial->port[i], priv);
- }
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
dbg("error kmalloc -> out of mem?");
- goto cleanup;
+ return -ENOMEM;
}
/* 3 */
@@ -149,13 +133,16 @@ static int ark3116_attach(struct usb_serial *serial)
kfree(buf);
return 0;
+}
-cleanup:
- for (--i; i >= 0; --i) {
- kfree(usb_get_serial_port_data(serial->port[i]));
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+static void ark3116_init_termios(struct tty_struct *tty)
+{
+ struct ktermios *termios = tty->termios;
+ *termios = tty_std_termios;
+ termios->c_cflag = B9600 | CS8
+ | CREAD | HUPCL | CLOCAL;
+ termios->c_ispeed = 9600;
+ termios->c_ospeed = 9600;
}
static void ark3116_set_termios(struct tty_struct *tty,
@@ -163,10 +150,8 @@ static void ark3116_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
- struct ark3116_private *priv = usb_get_serial_port_data(port);
struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
- unsigned long flags;
int baud;
int ark3116_baud;
char *buf;
@@ -176,16 +161,6 @@ static void ark3116_set_termios(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *termios = tty_std_termios;
- termios->c_cflag = B9600 | CS8
- | CREAD | HUPCL | CLOCAL;
- termios->c_ispeed = 9600;
- termios->c_ospeed = 9600;
- priv->termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
cflag = termios->c_cflag;
termios->c_cflag &= ~(CMSPAR|CRTSCTS);
@@ -455,6 +430,7 @@ static struct usb_serial_driver ark3116_device = {
.num_ports = 1,
.attach = ark3116_attach,
.set_termios = ark3116_set_termios,
+ .init_termios = ark3116_init_termios,
.ioctl = ark3116_ioctl,
.tiocmget = ark3116_tiocmget,
.open = ark3116_open,
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 0e4f2e41ace5..3e49b2ed0266 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/console.h>
+#include <linux/serial.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -63,7 +64,7 @@ static int usb_console_setup(struct console *co, char *options)
char *s;
struct usb_serial *serial;
struct usb_serial_port *port;
- int retval = 0;
+ int retval;
struct tty_struct *tty = NULL;
struct ktermios *termios = NULL, dummy;
@@ -116,13 +117,17 @@ static int usb_console_setup(struct console *co, char *options)
return -ENODEV;
}
- port = serial->port[0];
+ retval = usb_autopm_get_interface(serial->interface);
+ if (retval)
+ goto error_get_interface;
+
+ port = serial->port[co->index - serial->minor];
tty_port_tty_set(&port->port, NULL);
info->port = port;
++port->port.count;
- if (port->port.count == 1) {
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
if (serial->type->set_termios) {
/*
* allocate a fake tty so the driver can initialize
@@ -168,6 +173,7 @@ static int usb_console_setup(struct console *co, char *options)
kfree(termios);
kfree(tty);
}
+ set_bit(ASYNCB_INITIALIZED, &port->port.flags);
}
/* Now that any required fake tty operations are completed restore
* the tty port count */
@@ -175,18 +181,22 @@ static int usb_console_setup(struct console *co, char *options)
/* The console is special in terms of closing the device so
* indicate this port is now acting as a system console. */
port->console = 1;
- retval = 0;
-out:
+ mutex_unlock(&serial->disc_mutex);
return retval;
-free_termios:
+
+ free_termios:
kfree(termios);
tty_port_tty_set(&port->port, NULL);
-free_tty:
+ free_tty:
kfree(tty);
-reset_open_count:
+ reset_open_count:
port->port.count = 0;
- goto out;
+ usb_autopm_put_interface(serial->interface);
+ error_get_interface:
+ usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
+ return retval;
}
static void usb_console_write(struct console *co,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 985cbcf48bda..2367325e80b0 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -51,6 +51,8 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
static void cp210x_disconnect(struct usb_serial *);
+static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
+static int cp210x_carrier_raised(struct usb_serial_port *p);
static int debug;
@@ -114,6 +116,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
@@ -143,6 +146,8 @@ static struct usb_serial_driver cp210x_device = {
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
.disconnect = cp210x_disconnect,
+ .dtr_rts = cp210x_dtr_rts,
+ .carrier_raised = cp210x_carrier_raised
};
/* Config request types */
@@ -399,12 +404,6 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port,
/* Configure the termios structure */
cp210x_get_termios(tty, port);
-
- /* Set the DTR and RTS pins low */
- cp210x_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data
- : port,
- NULL, TIOCM_DTR | TIOCM_RTS, 0);
-
return 0;
}
@@ -753,6 +752,14 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
return cp210x_set_config(port, CP210X_SET_MHS, &control, 2);
}
+static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
+{
+ if (on)
+ cp210x_tiocmset_port(p, NULL, TIOCM_DTR|TIOCM_RTS, 0);
+ else
+ cp210x_tiocmset_port(p, NULL, 0, TIOCM_DTR|TIOCM_RTS);
+}
+
static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
{
struct usb_serial_port *port = tty->driver_data;
@@ -775,6 +782,15 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
return result;
}
+static int cp210x_carrier_raised(struct usb_serial_port *p)
+{
+ unsigned int control;
+ cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1);
+ if (control & CONTROL_DCD)
+ return 1;
+ return 0;
+}
+
static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 59adfe123110..27b5a271fe4a 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -659,15 +659,7 @@ static int cypress_open(struct tty_struct *tty,
spin_unlock_irqrestore(&priv->lock, flags);
/* Set termios */
- result = cypress_write(tty, port, NULL, 0);
-
- if (result) {
- dev_err(&port->dev,
- "%s - failed setting the control lines - error %d\n",
- __func__, result);
- return result;
- } else
- dbg("%s - success setting the control lines", __func__);
+ cypress_send(port);
if (tty)
cypress_set_termios(tty, port, &priv->tmp_termios);
@@ -1005,6 +997,8 @@ static void cypress_set_termios(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
+ /* We can't clean this one up as we don't know the device type
+ early enough */
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
*(tty->termios) = tty_std_termios;
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index f4808091c47c..9bd82b487005 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -899,16 +899,16 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
spin_lock_irqsave(&priv->dp_port_lock, flags);
- /* turn throttle off */
- priv->dp_throttled = 0;
- priv->dp_throttle_restart = 0;
-
/* restart read chain */
if (priv->dp_throttle_restart) {
port->read_urb->dev = port->serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
}
+ /* turn throttle off */
+ priv->dp_throttled = 0;
+ priv->dp_throttle_restart = 0;
+
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret)
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 80cb3471adbe..3433f9db4418 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -90,8 +90,7 @@ static int empeg_chars_in_buffer(struct tty_struct *tty);
static void empeg_throttle(struct tty_struct *tty);
static void empeg_unthrottle(struct tty_struct *tty);
static int empeg_startup(struct usb_serial *serial);
-static void empeg_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port, struct ktermios *old_termios);
+static void empeg_init_termios(struct tty_struct *tty);
static void empeg_write_bulk_callback(struct urb *urb);
static void empeg_read_bulk_callback(struct urb *urb);
@@ -123,7 +122,7 @@ static struct usb_serial_driver empeg_device = {
.throttle = empeg_throttle,
.unthrottle = empeg_unthrottle,
.attach = empeg_startup,
- .set_termios = empeg_set_termios,
+ .init_termios = empeg_init_termios,
.write = empeg_write,
.write_room = empeg_write_room,
.chars_in_buffer = empeg_chars_in_buffer,
@@ -150,9 +149,6 @@ static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- /* Force default termio settings */
- empeg_set_termios(tty, port, NULL) ;
-
bytes_in = 0;
bytes_out = 0;
@@ -425,11 +421,9 @@ static int empeg_startup(struct usb_serial *serial)
}
-static void empeg_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port, struct ktermios *old_termios)
+static void empeg_init_termios(struct tty_struct *tty)
{
struct ktermios *termios = tty->termios;
- dbg("%s - port %d", __func__, port->number);
/*
* The empeg-car player wants these particular tty settings.
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 8fec5d4455c9..84102014ed5b 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -76,13 +76,7 @@ struct ftdi_private {
unsigned long last_dtr_rts; /* saved modem control outputs */
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
char prev_status, diff_status; /* Used for TIOCMIWAIT */
- __u8 rx_flags; /* receive state flags (throttling) */
- spinlock_t rx_lock; /* spinlock for receive state */
- struct delayed_work rx_work;
struct usb_serial_port *port;
- int rx_processed;
- unsigned long rx_bytes;
-
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
(0 for FT232/245) */
@@ -176,6 +170,9 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -694,6 +691,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(DE_VID, WHT_PID) },
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -702,6 +701,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
+ { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -730,10 +731,6 @@ static const char *ftdi_chip_name[] = {
/* Constants for read urb and write urb */
#define BUFSZ 512
-/* rx_flags */
-#define THROTTLED 0x01
-#define ACTUALLY_THROTTLED 0x02
-
/* Used for TIOCMIWAIT */
#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
@@ -757,7 +754,7 @@ static int ftdi_write_room(struct tty_struct *tty);
static int ftdi_chars_in_buffer(struct tty_struct *tty);
static void ftdi_write_bulk_callback(struct urb *urb);
static void ftdi_read_bulk_callback(struct urb *urb);
-static void ftdi_process_read(struct work_struct *work);
+static void ftdi_process_read(struct usb_serial_port *port);
static void ftdi_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static int ftdi_tiocmget(struct tty_struct *tty, struct file *file);
@@ -1228,7 +1225,6 @@ static int set_serial_info(struct tty_struct *tty,
(new_serial.flags & ASYNC_FLAGS));
priv->custom_divisor = new_serial.custom_divisor;
- tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
write_latency_timer(port);
check_and_exit:
@@ -1521,7 +1517,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
}
kref_init(&priv->kref);
- spin_lock_init(&priv->rx_lock);
spin_lock_init(&priv->tx_lock);
init_waitqueue_head(&priv->delta_msr_wait);
/* This will push the characters through immediately rather
@@ -1543,7 +1538,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
port->read_urb->transfer_buffer_length = BUFSZ;
}
- INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read);
priv->port = port;
/* Free port's existing write urb and transfer buffer. */
@@ -1680,6 +1674,26 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
return 0;
}
+static int ftdi_submit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
+{
+ struct urb *urb = port->read_urb;
+ struct usb_serial *serial = port->serial;
+ int result;
+
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ urb->transfer_buffer,
+ urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
+ result = usb_submit_urb(urb, mem_flags);
+ if (result)
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
+ return result;
+}
+
static int ftdi_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
{ /* ftdi_open */
@@ -1695,12 +1709,6 @@ static int ftdi_open(struct tty_struct *tty,
spin_lock_irqsave(&priv->tx_lock, flags);
priv->tx_bytes = 0;
spin_unlock_irqrestore(&priv->tx_lock, flags);
- spin_lock_irqsave(&priv->rx_lock, flags);
- priv->rx_bytes = 0;
- spin_unlock_irqrestore(&priv->rx_lock, flags);
-
- if (tty)
- tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
write_latency_timer(port);
@@ -1720,23 +1728,14 @@ static int ftdi_open(struct tty_struct *tty,
ftdi_set_termios(tty, port, tty->termios);
/* Not throttled */
- spin_lock_irqsave(&priv->rx_lock, flags);
- priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
- spin_unlock_irqrestore(&priv->rx_lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->throttled = 0;
+ port->throttle_req = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
/* Start reading from the device */
- priv->rx_processed = 0;
- usb_fill_bulk_urb(port->read_urb, dev,
- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- ftdi_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result)
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, result);
- else
+ result = ftdi_submit_read_urb(port, GFP_KERNEL);
+ if (!result)
kref_get(&priv->kref);
return result;
@@ -1782,10 +1781,6 @@ static void ftdi_close(struct usb_serial_port *port)
dbg("%s", __func__);
-
- /* cancel any scheduled reading */
- cancel_delayed_work_sync(&priv->rx_work);
-
/* shutdown our bulk read */
usb_kill_urb(port->read_urb);
kref_put(&priv->kref, ftdi_sio_priv_release);
@@ -1944,7 +1939,7 @@ static void ftdi_write_bulk_callback(struct urb *urb)
return;
}
/* account for transferred data */
- countback = urb->actual_length;
+ countback = urb->transfer_buffer_length;
data_offset = priv->write_offset;
if (data_offset > 0) {
/* Subtract the control bytes */
@@ -1957,7 +1952,6 @@ static void ftdi_write_bulk_callback(struct urb *urb)
if (status) {
dbg("nonzero write bulk status received: %d", status);
- return;
}
usb_serial_port_softint(port);
@@ -2008,271 +2002,121 @@ static int ftdi_chars_in_buffer(struct tty_struct *tty)
return buffered;
}
-static void ftdi_read_bulk_callback(struct urb *urb)
+static int ftdi_process_packet(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ftdi_private *priv,
+ char *packet, int len)
{
- struct usb_serial_port *port = urb->context;
- struct tty_struct *tty;
- struct ftdi_private *priv;
- unsigned long countread;
- unsigned long flags;
- int status = urb->status;
-
- if (urb->number_of_packets > 0) {
- dev_err(&port->dev, "%s transfer_buffer_length %d "
- "actual_length %d number of packets %d\n", __func__,
- urb->transfer_buffer_length,
- urb->actual_length, urb->number_of_packets);
- dev_err(&port->dev, "%s transfer_flags %x\n", __func__,
- urb->transfer_flags);
- }
+ int i;
+ char status;
+ char flag;
+ char *ch;
dbg("%s - port %d", __func__, port->number);
- if (port->port.count <= 0)
- return;
-
- tty = tty_port_tty_get(&port->port);
- if (!tty) {
- dbg("%s - bad tty pointer - exiting", __func__);
- return;
+ if (len < 2) {
+ dbg("malformed packet");
+ return 0;
}
- priv = usb_get_serial_port_data(port);
- if (!priv) {
- dbg("%s - bad port private data pointer - exiting", __func__);
- goto out;
+ /* Compare new line status to the old one, signal if different/
+ N.B. packet may be processed more than once, but differences
+ are only processed once. */
+ status = packet[0] & FTDI_STATUS_B0_MASK;
+ if (status != priv->prev_status) {
+ priv->diff_status |= status ^ priv->prev_status;
+ wake_up_interruptible(&priv->delta_msr_wait);
+ priv->prev_status = status;
}
- if (urb != port->read_urb)
- dev_err(&port->dev, "%s - Not my urb!\n", __func__);
-
- if (status) {
- /* This will happen at close every time so it is a dbg not an
- err */
- dbg("(this is ok on close) nonzero read bulk status received: %d", status);
- goto out;
+ /*
+ * Although the device uses a bitmask and hence can have multiple
+ * errors on a packet - the order here sets the priority the error is
+ * returned to the tty layer.
+ */
+ flag = TTY_NORMAL;
+ if (packet[1] & FTDI_RS_OE) {
+ flag = TTY_OVERRUN;
+ dbg("OVERRRUN error");
+ }
+ if (packet[1] & FTDI_RS_BI) {
+ flag = TTY_BREAK;
+ dbg("BREAK received");
+ usb_serial_handle_break(port);
+ }
+ if (packet[1] & FTDI_RS_PE) {
+ flag = TTY_PARITY;
+ dbg("PARITY error");
+ }
+ if (packet[1] & FTDI_RS_FE) {
+ flag = TTY_FRAME;
+ dbg("FRAMING error");
}
- /* count data bytes, but not status bytes */
- countread = urb->actual_length;
- countread -= 2 * DIV_ROUND_UP(countread, priv->max_packet_size);
- spin_lock_irqsave(&priv->rx_lock, flags);
- priv->rx_bytes += countread;
- spin_unlock_irqrestore(&priv->rx_lock, flags);
-
- ftdi_process_read(&priv->rx_work.work);
-out:
- tty_kref_put(tty);
-} /* ftdi_read_bulk_callback */
-
+ len -= 2;
+ if (!len)
+ return 0; /* status only */
+ ch = packet + 2;
+
+ if (!(port->console && port->sysrq) && flag == TTY_NORMAL)
+ tty_insert_flip_string(tty, ch, len);
+ else {
+ for (i = 0; i < len; i++, ch++) {
+ if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+ tty_insert_flip_char(tty, *ch, flag);
+ }
+ }
+ return len;
+}
-static void ftdi_process_read(struct work_struct *work)
-{ /* ftdi_process_read */
- struct ftdi_private *priv =
- container_of(work, struct ftdi_private, rx_work.work);
- struct usb_serial_port *port = priv->port;
- struct urb *urb;
+static void ftdi_process_read(struct usb_serial_port *port)
+{
+ struct urb *urb = port->read_urb;
struct tty_struct *tty;
- char error_flag;
- unsigned char *data;
-
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char *data = (char *)urb->transfer_buffer;
int i;
- int result;
- int need_flip;
- int packet_offset;
- unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
- if (port->port.count <= 0)
- return;
+ int len;
+ int count = 0;
tty = tty_port_tty_get(&port->port);
- if (!tty) {
- dbg("%s - bad tty pointer - exiting", __func__);
+ if (!tty)
return;
- }
- priv = usb_get_serial_port_data(port);
- if (!priv) {
- dbg("%s - bad port private data pointer - exiting", __func__);
- goto out;
- }
-
- urb = port->read_urb;
- if (!urb) {
- dbg("%s - bad read_urb pointer - exiting", __func__);
- goto out;
+ for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
+ len = min_t(int, urb->actual_length - i, priv->max_packet_size);
+ count += ftdi_process_packet(tty, port, priv, &data[i], len);
}
- data = urb->transfer_buffer;
-
- if (priv->rx_processed) {
- dbg("%s - already processed: %d bytes, %d remain", __func__,
- priv->rx_processed,
- urb->actual_length - priv->rx_processed);
- } else {
- /* The first two bytes of every read packet are status */
- if (urb->actual_length > 2)
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
- else
- dbg("Status only: %03oo %03oo", data[0], data[1]);
- }
-
-
- /* TO DO -- check for hung up line and handle appropriately: */
- /* send hangup */
- /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
- /* if CD is dropped and the line is not CLOCAL then we should hangup */
-
- need_flip = 0;
- for (packet_offset = priv->rx_processed;
- packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {
- int length;
-
- /* Compare new line status to the old one, signal if different/
- N.B. packet may be processed more than once, but differences
- are only processed once. */
- char new_status = data[packet_offset + 0] &
- FTDI_STATUS_B0_MASK;
- if (new_status != priv->prev_status) {
- priv->diff_status |=
- new_status ^ priv->prev_status;
- wake_up_interruptible(&priv->delta_msr_wait);
- priv->prev_status = new_status;
- }
-
- length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2;
- if (length < 0) {
- dev_err(&port->dev, "%s - bad packet length: %d\n",
- __func__, length+2);
- length = 0;
- }
-
- if (priv->rx_flags & THROTTLED) {
- dbg("%s - throttled", __func__);
- break;
- }
- if (tty_buffer_request_room(tty, length) < length) {
- /* break out & wait for throttling/unthrottling to
- happen */
- dbg("%s - receive room low", __func__);
- break;
- }
-
- /* Handle errors and break */
- error_flag = TTY_NORMAL;
- /* Although the device uses a bitmask and hence can have
- multiple errors on a packet - the order here sets the
- priority the error is returned to the tty layer */
-
- if (data[packet_offset+1] & FTDI_RS_OE) {
- error_flag = TTY_OVERRUN;
- dbg("OVERRRUN error");
- }
- if (data[packet_offset+1] & FTDI_RS_BI) {
- error_flag = TTY_BREAK;
- dbg("BREAK received");
- usb_serial_handle_break(port);
- }
- if (data[packet_offset+1] & FTDI_RS_PE) {
- error_flag = TTY_PARITY;
- dbg("PARITY error");
- }
- if (data[packet_offset+1] & FTDI_RS_FE) {
- error_flag = TTY_FRAME;
- dbg("FRAMING error");
- }
- if (length > 0) {
- for (i = 2; i < length+2; i++) {
- /* Note that the error flag is duplicated for
- every character received since we don't know
- which character it applied to */
- if (!usb_serial_handle_sysrq_char(tty, port,
- data[packet_offset + i]))
- tty_insert_flip_char(tty,
- data[packet_offset + i],
- error_flag);
- }
- need_flip = 1;
- }
-
-#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
- /* if a parity error is detected you get status packets forever
- until a character is sent without a parity error.
- This doesn't work well since the application receives a
- never ending stream of bad data - even though new data
- hasn't been sent. Therefore I (bill) have taken this out.
- However - this might make sense for framing errors and so on
- so I am leaving the code in for now.
- */
- else {
- if (error_flag != TTY_NORMAL) {
- dbg("error_flag is not normal");
- /* In this case it is just status - if that is
- an error send a bad character */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- tty_flip_buffer_push(tty);
- tty_insert_flip_char(tty, 0xff, error_flag);
- need_flip = 1;
- }
- }
-#endif
- } /* "for(packet_offset=0..." */
-
- /* Low latency */
- if (need_flip)
+ if (count)
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+}
- if (packet_offset < urb->actual_length) {
- /* not completely processed - record progress */
- priv->rx_processed = packet_offset;
- dbg("%s - incomplete, %d bytes processed, %d remain",
- __func__, packet_offset,
- urb->actual_length - packet_offset);
- /* check if we were throttled while processing */
- spin_lock_irqsave(&priv->rx_lock, flags);
- if (priv->rx_flags & THROTTLED) {
- priv->rx_flags |= ACTUALLY_THROTTLED;
- spin_unlock_irqrestore(&priv->rx_lock, flags);
- dbg("%s - deferring remainder until unthrottled",
- __func__);
- goto out;
- }
- spin_unlock_irqrestore(&priv->rx_lock, flags);
- /* if the port is closed stop trying to read */
- if (port->port.count > 0)
- /* delay processing of remainder */
- schedule_delayed_work(&priv->rx_work, 1);
- else
- dbg("%s - port is closed", __func__);
- goto out;
- }
-
- /* urb is completely processed */
- priv->rx_processed = 0;
+static void ftdi_read_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ unsigned long flags;
- /* if the port is closed stop trying to read */
- if (port->port.count > 0) {
- /* Continue trying to always read */
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- ftdi_read_bulk_callback, port);
+ dbg("%s - port %d", __func__, port->number);
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
+ if (urb->status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __func__, urb->status);
+ return;
}
-out:
- tty_kref_put(tty);
-} /* ftdi_process_read */
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+ ftdi_process_read(port);
+
+ spin_lock_irqsave(&port->lock, flags);
+ port->throttled = port->throttle_req;
+ if (!port->throttled) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ ftdi_submit_read_urb(port, GFP_ATOMIC);
+ } else
+ spin_unlock_irqrestore(&port->lock, flags);
+}
static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
{
@@ -2604,33 +2448,31 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
static void ftdi_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave(&priv->rx_lock, flags);
- priv->rx_flags |= THROTTLED;
- spin_unlock_irqrestore(&priv->rx_lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->throttle_req = 1;
+ spin_unlock_irqrestore(&port->lock, flags);
}
-
-static void ftdi_unthrottle(struct tty_struct *tty)
+void ftdi_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct ftdi_private *priv = usb_get_serial_port_data(port);
- int actually_throttled;
+ int was_throttled;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave(&priv->rx_lock, flags);
- actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
- priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
- spin_unlock_irqrestore(&priv->rx_lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ was_throttled = port->throttled;
+ port->throttled = port->throttle_req = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
- if (actually_throttled)
- schedule_delayed_work(&priv->rx_work, 0);
+ /* Resubmit urb if throttled and open. */
+ if (was_throttled && test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ ftdi_submit_read_urb(port, GFP_KERNEL);
}
static int __init ftdi_init(void)
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8c92b88166ae..6f31e0d71898 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -81,6 +81,9 @@
/* OpenDCC (www.opendcc.de) product id */
#define FTDI_OPENDCC_PID 0xBFD8
+#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9
+#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA
+#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB
/* Sprog II (Andrew Crosland's SprogII DCC interface) */
#define FTDI_SPROG_II 0xF0C8
@@ -930,6 +933,7 @@
*/
#define ADI_VID 0x0456
#define ADI_GNICE_PID 0xF000
+#define ADI_GNICEPLUS_PID 0xF001
/*
* JETI SPECTROMETER SPECBOS 1201
@@ -968,6 +972,12 @@
#define MARVELL_OPENRD_PID 0x9e90
/*
+ * Hameg HO820 and HO870 interface (using VID 0x0403)
+ */
+#define HAMEG_HO820_PID 0xed74
+#define HAMEG_HO870_PID 0xed71
+
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_E2_READ
* wValue: 0
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index ce57f6a32bdf..6463fee644b9 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -480,6 +480,8 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
dbg("%s - port %d", __func__, port->number);
if (port->serial->type->max_in_flight_urbs) {
+ kfree(urb->transfer_buffer);
+
spin_lock_irqsave(&port->lock, flags);
--port->urbs_in_flight;
port->tx_bytes_flight -= urb->transfer_buffer_length;
@@ -530,7 +532,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
if (was_throttled) {
/* Resume reading from device */
- usb_serial_generic_resubmit_read_urb(port, GFP_KERNEL);
+ flush_and_resubmit_read_urb(port);
}
}
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 2545d45ce16f..c4d02064e5f1 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -971,6 +971,15 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
static int ipaq_startup(struct usb_serial *serial)
{
dbg("%s", __func__);
+
+ /* Some of the devices in ipaq_id_table[] are composite, and we
+ * shouldn't bind to all the interfaces. This test will rule out
+ * some obviously invalid possibilities.
+ */
+ if (serial->num_bulk_in < serial->num_ports ||
+ serial->num_bulk_out < serial->num_ports)
+ return -ENODEV;
+
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
/*
* FIXME: HP iPaq rx3715, possibly others, have 1 config that
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 96873a7a32b0..af6df6c788b9 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -71,7 +71,6 @@ struct iuu_private {
spinlock_t lock; /* store irq state */
wait_queue_head_t delta_msr_wait;
u8 line_status;
- u8 termios_initialized;
int tiostatus; /* store IUART SIGNAL for tiocmget call */
u8 reset; /* if 1 reset is needed */
int poll; /* number of poll */
@@ -1018,6 +1017,18 @@ static void iuu_close(struct usb_serial_port *port)
}
}
+static void iuu_init_termios(struct tty_struct *tty)
+{
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ | TIOCM_CTS | CSTOPB | PARENB;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
+ tty->termios->c_lflag = 0;
+ tty->termios->c_oflag = 0;
+ tty->termios->c_iflag = 0;
+}
+
static int iuu_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
{
@@ -1025,7 +1036,6 @@ static int iuu_open(struct tty_struct *tty,
u8 *buf;
int result;
u32 actual;
- unsigned long flags;
struct iuu_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
@@ -1064,21 +1074,7 @@ static int iuu_open(struct tty_struct *tty,
port->bulk_in_buffer, 512,
NULL, NULL);
- /* set the termios structure */
- spin_lock_irqsave(&priv->lock, flags);
- if (tty && !priv->termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
- | TIOCM_CTS | CSTOPB | PARENB;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
- tty->termios->c_lflag = 0;
- tty->termios->c_oflag = 0;
- tty->termios->c_iflag = 0;
- priv->termios_initialized = 1;
- priv->poll = 0;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
+ priv->poll = 0;
/* initialize writebuf */
#define FISH(a, b, c, d) do { \
@@ -1201,6 +1197,7 @@ static struct usb_serial_driver iuu_device = {
.tiocmget = iuu_tiocmget,
.tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios,
+ .init_termios = iuu_init_termios,
.attach = iuu_startup,
.release = iuu_release,
};
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 6db0e561f680..46d47d1463c9 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -85,7 +85,7 @@ static void kobil_read_int_callback(struct urb *urb);
static void kobil_write_callback(struct urb *purb);
static void kobil_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
-
+static void kobil_init_termios(struct tty_struct *tty);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },
@@ -120,6 +120,7 @@ static struct usb_serial_driver kobil_device = {
.release = kobil_release,
.ioctl = kobil_ioctl,
.set_termios = kobil_set_termios,
+ .init_termios = kobil_init_termios,
.tiocmget = kobil_tiocmget,
.tiocmset = kobil_tiocmset,
.open = kobil_open,
@@ -210,6 +211,15 @@ static void kobil_release(struct usb_serial *serial)
kfree(usb_get_serial_port_data(serial->port[i]));
}
+static void kobil_init_termios(struct tty_struct *tty)
+{
+ /* Default to echo off and other sane device settings */
+ tty->termios->c_lflag = 0;
+ tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
+ tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
+ tty->termios->c_oflag &= ~ONLCR;
+}
static int kobil_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
@@ -226,16 +236,6 @@ static int kobil_open(struct tty_struct *tty,
/* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
- if (tty) {
-
- /* Default to echo off and other sane device settings */
- tty->termios->c_lflag = 0;
- tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN |
- XCASE);
- tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
- /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
- tty->termios->c_oflag &= ~ONLCR;
- }
/* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c784ddbe7b61..c7b42ca00d56 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -166,6 +166,7 @@ static int option_resume(struct usb_serial *serial);
#define HUAWEI_PRODUCT_E143D 0x143D
#define HUAWEI_PRODUCT_E143E 0x143E
#define HUAWEI_PRODUCT_E143F 0x143F
+#define HUAWEI_PRODUCT_E14AC 0x14AC
#define QUANTA_VENDOR_ID 0x0408
#define QUANTA_PRODUCT_Q101 0xEA02
@@ -292,6 +293,7 @@ static int option_resume(struct usb_serial *serial);
#define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003
+#define TELIT_PRODUCT_UC864G 0x1004
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
@@ -300,12 +302,14 @@ static int option_resume(struct usb_serial *serial);
#define ZTE_PRODUCT_MF626 0x0031
#define ZTE_PRODUCT_CDMA_TECH 0xfffe
#define ZTE_PRODUCT_AC8710 0xfff1
+#define ZTE_PRODUCT_AC2726 0xfff5
#define BENQ_VENDOR_ID 0x04a5
#define BENQ_PRODUCT_H10 0x4068
#define DLINK_VENDOR_ID 0x1186
#define DLINK_PRODUCT_DWM_652 0x3e04
+#define DLINK_PRODUCT_DWM_652_U5 0xce16
#define QISDA_VENDOR_ID 0x1da5
#define QISDA_PRODUCT_H21_4512 0x4512
@@ -313,10 +317,14 @@ static int option_resume(struct usb_serial *serial);
#define QISDA_PRODUCT_H20_4515 0x4515
#define QISDA_PRODUCT_H20_4519 0x4519
+/* TLAYTECH PRODUCTS */
+#define TLAYTECH_VENDOR_ID 0x20B9
+#define TLAYTECH_PRODUCT_TEU800 0x1682
/* TOSHIBA PRODUCTS */
#define TOSHIBA_VENDOR_ID 0x0930
#define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302
+#define TOSHIBA_PRODUCT_G450 0x0d45
#define ALINK_VENDOR_ID 0x1e0e
#define ALINK_PRODUCT_3GU 0x9200
@@ -325,6 +333,13 @@ static int option_resume(struct usb_serial *serial);
#define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S 0x0000
+/* Airplus products */
+#define AIRPLUS_VENDOR_ID 0x1011
+#define AIRPLUS_PRODUCT_MCD650 0x3198
+
+/* Haier products */
+#define HAIER_VENDOR_ID 0x201e
+#define HAIER_PRODUCT_CE100 0x2009
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -423,6 +438,7 @@ static struct usb_device_id option_ids[] = {
{ 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(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
{ 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 */
@@ -503,6 +519,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(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
@@ -564,24 +581,67 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
+ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+ { USB_DEVICE(ALINK_VENDOR_ID, 0xce16) },
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
+ { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
+ { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
+ { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 3cece27325e7..ef34cffabdf8 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -146,6 +146,7 @@ static int oti6858_open(struct tty_struct *tty,
static void oti6858_close(struct usb_serial_port *port);
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
+static void oti6858_init_termios(struct tty_struct *tty);
static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
@@ -186,6 +187,7 @@ static struct usb_serial_driver oti6858_device = {
.write = oti6858_write,
.ioctl = oti6858_ioctl,
.set_termios = oti6858_set_termios,
+ .init_termios = oti6858_init_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
.read_bulk_callback = oti6858_read_bulk_callback,
@@ -206,7 +208,6 @@ struct oti6858_private {
struct {
u8 read_urb_in_use;
u8 write_urb_in_use;
- u8 termios_initialized;
} flags;
struct delayed_work delayed_write_work;
@@ -447,6 +448,14 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty)
return chars;
}
+static void oti6858_init_termios(struct tty_struct *tty)
+{
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 38400;
+ tty->termios->c_ospeed = 38400;
+}
+
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
@@ -464,16 +473,6 @@ static void oti6858_set_termios(struct tty_struct *tty,
return;
}
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->flags.termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 38400;
- tty->termios->c_ospeed = 38400;
- priv->flags.termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
cflag = tty->termios->c_cflag;
spin_lock_irqsave(&priv->lock, flags);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 3e86815b2705..600097de714f 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -96,6 +96,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
+ { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
{ } /* Terminating entry */
};
@@ -994,13 +995,15 @@ static void pl2303_push_data(struct tty_struct *tty,
/* overrun is special, not associated with a char */
if (line_status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- if (port->console && port->sysrq) {
+
+ if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq))
+ tty_insert_flip_string(tty, data, urb->actual_length);
+ else {
int i;
for (i = 0; i < urb->actual_length; ++i)
if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
tty_insert_flip_char(tty, data[i], tty_flag);
- } else
- tty_insert_flip_string(tty, data, urb->actual_length);
+ }
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index ee9505e1dd92..d640dc951568 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -130,3 +130,7 @@
/* Sony, USB data cable for CMD-Jxx mobile phones */
#define SONY_VENDOR_ID 0x054c
#define SONY_QN3USB_PRODUCT_ID 0x0437
+
+/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */
+#define SANWA_VENDOR_ID 0x11ad
+#define SANWA_PRODUCT_ID 0x0001
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index f48d05e0acc1..c5fbaa5dde05 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -287,6 +287,8 @@ static int sierra_send_setup(struct usb_serial_port *port)
struct sierra_port_private *portdata;
__u16 interface = 0;
int val = 0;
+ int do_send = 0;
+ int retval;
dev_dbg(&port->dev, "%s\n", __func__);
@@ -305,10 +307,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
*/
if (port->interrupt_in_urb) {
/* send control message */
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, interface,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
+ do_send = 1;
}
}
@@ -320,12 +319,18 @@ static int sierra_send_setup(struct usb_serial_port *port)
interface = 1;
else if (port->bulk_out_endpointAddress == 5)
interface = 2;
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, interface,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
+
+ do_send = 1;
}
- return 0;
+ if (!do_send)
+ return 0;
+
+ usb_autopm_get_interface(serial->interface);
+ retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ usb_autopm_put_interface(serial->interface);
+
+ return retval;
}
static void sierra_set_termios(struct tty_struct *tty,
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 3c249d8e8b8e..993a6d5a1b7a 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -299,7 +299,6 @@ struct spcp8x5_private {
wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
- u8 termios_initialized;
};
/* desc : when device plug in,this function would be called.
@@ -498,6 +497,15 @@ static void spcp8x5_close(struct usb_serial_port *port)
dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
}
+static void spcp8x5_init_termios(struct tty_struct *tty)
+{
+ /* for the 1st time call this function */
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 115200;
+ tty->termios->c_ospeed = 115200;
+}
+
/* set the serial param for transfer. we should check if we really need to
* transfer. if we set flow control we should do this too. */
static void spcp8x5_set_termios(struct tty_struct *tty,
@@ -514,16 +522,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
int i;
u8 control;
- /* for the 1st time call this function */
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 115200;
- tty->termios->c_ospeed = 115200;
- priv->termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
/* check that they really want us to change something */
if (!tty_termios_hw_change(tty->termios, old_termios))
@@ -1011,6 +1009,7 @@ static struct usb_serial_driver spcp8x5_device = {
.carrier_raised = spcp8x5_carrier_raised,
.write = spcp8x5_write,
.set_termios = spcp8x5_set_termios,
+ .init_termios = spcp8x5_init_termios,
.ioctl = spcp8x5_ioctl,
.tiocmget = spcp8x5_tiocmget,
.tiocmset = spcp8x5_tiocmset,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 99188c92068b..3292e0391e28 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -43,8 +43,6 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
-static void port_free(struct usb_serial_port *port);
-
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
.name = "usbserial",
@@ -68,6 +66,11 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);
+/*
+ * Look up the serial structure. If it is found and it hasn't been
+ * disconnected, return with its disc_mutex held and its refcount
+ * incremented. Otherwise return NULL.
+ */
struct usb_serial *usb_serial_get_by_index(unsigned index)
{
struct usb_serial *serial;
@@ -75,8 +78,15 @@ struct usb_serial *usb_serial_get_by_index(unsigned index)
mutex_lock(&table_lock);
serial = serial_table[index];
- if (serial)
- kref_get(&serial->kref);
+ if (serial) {
+ mutex_lock(&serial->disc_mutex);
+ if (serial->disconnected) {
+ mutex_unlock(&serial->disc_mutex);
+ serial = NULL;
+ } else {
+ kref_get(&serial->kref);
+ }
+ }
mutex_unlock(&table_lock);
return serial;
}
@@ -125,8 +135,10 @@ static void return_serial(struct usb_serial *serial)
dbg("%s", __func__);
+ mutex_lock(&table_lock);
for (i = 0; i < serial->num_ports; ++i)
serial_table[serial->minor + i] = NULL;
+ mutex_unlock(&table_lock);
}
static void destroy_serial(struct kref *kref)
@@ -143,163 +155,160 @@ static void destroy_serial(struct kref *kref)
if (serial->minor != SERIAL_TTY_NO_MINOR)
return_serial(serial);
- serial->type->release(serial);
+ if (serial->attached)
+ serial->type->release(serial);
- for (i = 0; i < serial->num_ports; ++i) {
+ /* Now that nothing is using the ports, they can be freed */
+ for (i = 0; i < serial->num_port_pointers; ++i) {
port = serial->port[i];
- if (port)
+ if (port) {
+ port->serial = NULL;
put_device(&port->dev);
- }
-
- /* If this is a "fake" port, we have to clean it up here, as it will
- * not get cleaned up in port_release() as it was never registered with
- * the driver core */
- if (serial->num_ports < serial->num_port_pointers) {
- for (i = serial->num_ports;
- i < serial->num_port_pointers; ++i) {
- port = serial->port[i];
- if (port)
- port_free(port);
}
}
usb_put_dev(serial->dev);
-
- /* free up any memory that we allocated */
kfree(serial);
}
void usb_serial_put(struct usb_serial *serial)
{
- mutex_lock(&table_lock);
kref_put(&serial->kref, destroy_serial);
- mutex_unlock(&table_lock);
}
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
-static int serial_open (struct tty_struct *tty, struct file *filp)
+
+/**
+ * serial_install - install tty
+ * @driver: the driver (USB in our case)
+ * @tty: the tty being created
+ *
+ * Create the termios objects for this tty. We use the default
+ * USB serial settings but permit them to be overridden by
+ * serial->type->init_termios.
+ *
+ * This is the first place a new tty gets used. Hence this is where we
+ * acquire references to the usb_serial structure and the driver module,
+ * where we store a pointer to the port, and where we do an autoresume.
+ * All these actions are reversed in serial_release().
+ */
+static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
{
+ int idx = tty->index;
struct usb_serial *serial;
struct usb_serial_port *port;
- unsigned int portNumber;
- int retval = 0;
- int first = 0;
+ int retval = -ENODEV;
dbg("%s", __func__);
- /* get the serial object associated with this tty pointer */
- serial = usb_serial_get_by_index(tty->index);
- if (!serial) {
- tty->driver_data = NULL;
- return -ENODEV;
- }
+ serial = usb_serial_get_by_index(idx);
+ if (!serial)
+ return retval;
- mutex_lock(&serial->disc_mutex);
- portNumber = tty->index - serial->minor;
- port = serial->port[portNumber];
- if (!port || serial->disconnected)
- retval = -ENODEV;
- else
- get_device(&port->dev);
- /*
- * Note: Our locking order requirement does not allow port->mutex
- * to be acquired while serial->disc_mutex is held.
- */
- mutex_unlock(&serial->disc_mutex);
+ port = serial->port[idx - serial->minor];
+ if (!port)
+ goto error_no_port;
+ if (!try_module_get(serial->type->driver.owner))
+ goto error_module_get;
+
+ /* perform the standard setup */
+ retval = tty_init_termios(tty);
if (retval)
- goto bailout_serial_put;
+ goto error_init_termios;
- if (mutex_lock_interruptible(&port->mutex)) {
- retval = -ERESTARTSYS;
- goto bailout_port_put;
- }
+ retval = usb_autopm_get_interface(serial->interface);
+ if (retval)
+ goto error_get_interface;
+
+ mutex_unlock(&serial->disc_mutex);
- ++port->port.count;
+ /* allow the driver to update the settings */
+ if (serial->type->init_termios)
+ serial->type->init_termios(tty);
- /* set up our port structure making the tty driver
- * remember our port object, and us it */
tty->driver_data = port;
- tty_port_tty_set(&port->port, tty);
- /* If the console is attached, the device is already open */
- if (port->port.count == 1 && !port->console) {
- first = 1;
- /* lock this module before we call it
- * this may fail, which means we must bail out,
- * safe because we are called with BKL held */
- if (!try_module_get(serial->type->driver.owner)) {
- retval = -ENODEV;
- goto bailout_mutex_unlock;
- }
+ /* Final install (we use the default method) */
+ tty_driver_kref_get(driver);
+ tty->count++;
+ driver->ttys[idx] = tty;
+ return retval;
+ error_get_interface:
+ error_init_termios:
+ module_put(serial->type->driver.owner);
+ error_module_get:
+ error_no_port:
+ usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
+ return retval;
+}
+
+static int serial_open(struct tty_struct *tty, struct file *filp)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+ int retval;
+
+ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irq(&port->port.lock);
+ if (!tty_hung_up_p(filp))
+ ++port->port.count;
+ spin_unlock_irq(&port->port.lock);
+ tty_port_tty_set(&port->port, tty);
+
+ /* Do the device-specific open only if the hardware isn't
+ * already initialized.
+ */
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
+ if (mutex_lock_interruptible(&port->mutex))
+ return -ERESTARTSYS;
mutex_lock(&serial->disc_mutex);
if (serial->disconnected)
retval = -ENODEV;
else
- retval = usb_autopm_get_interface(serial->interface);
- if (retval)
- goto bailout_module_put;
-
- /* only call the device specific open if this
- * is the first time the port is opened */
- retval = serial->type->open(tty, port, filp);
- if (retval)
- goto bailout_interface_put;
+ retval = port->serial->type->open(tty, port, filp);
mutex_unlock(&serial->disc_mutex);
+ mutex_unlock(&port->mutex);
+ if (retval)
+ return retval;
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
}
- mutex_unlock(&port->mutex);
+
/* Now do the correct tty layer semantics */
retval = tty_port_block_til_ready(&port->port, tty, filp);
- if (retval == 0) {
- if (!first)
- usb_serial_put(serial);
- return 0;
- }
- mutex_lock(&port->mutex);
- if (first == 0)
- goto bailout_mutex_unlock;
- /* Undo the initial port actions */
- mutex_lock(&serial->disc_mutex);
-bailout_interface_put:
- usb_autopm_put_interface(serial->interface);
-bailout_module_put:
- mutex_unlock(&serial->disc_mutex);
- module_put(serial->type->driver.owner);
-bailout_mutex_unlock:
- port->port.count = 0;
- tty->driver_data = NULL;
- tty_port_tty_set(&port->port, NULL);
- mutex_unlock(&port->mutex);
-bailout_port_put:
- put_device(&port->dev);
-bailout_serial_put:
- usb_serial_put(serial);
return retval;
}
/**
- * serial_do_down - shut down hardware
- * @port: port to shut down
- *
- * Shut down a USB port unless it is the console. We never shut down the
- * console hardware as it will always be in use.
+ * serial_down - shut down hardware
+ * @port: port to shut down
*
- * Don't free any resources at this point
+ * Shut down a USB serial port unless it is the console. We never
+ * shut down the console hardware as it will always be in use.
*/
-static void serial_do_down(struct usb_serial_port *port)
+static void serial_down(struct usb_serial_port *port)
{
struct usb_serial_driver *drv = port->serial->type;
struct usb_serial *serial;
struct module *owner;
- /* The console is magical, do not hang up the console hardware
- or there will be tears */
+ /*
+ * The console is magical. Do not hang up the console hardware
+ * or there will be tears.
+ */
if (port->console)
return;
+ /* Don't call the close method if the hardware hasn't been
+ * initialized.
+ */
+ if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ return;
+
mutex_lock(&port->mutex);
serial = port->serial;
owner = serial->type->driver.owner;
@@ -310,79 +319,69 @@ static void serial_do_down(struct usb_serial_port *port)
mutex_unlock(&port->mutex);
}
-/**
- * serial_do_free - free resources post close/hangup
- * @port: port to free up
- *
- * Do the resource freeing and refcount dropping for the port. We must
- * be careful about ordering and we must avoid freeing up the console.
- */
-
-static void serial_do_free(struct usb_serial_port *port)
+static void serial_hangup(struct tty_struct *tty)
{
- struct usb_serial *serial;
- struct module *owner;
+ struct usb_serial_port *port = tty->driver_data;
- /* The console is magical, do not hang up the console hardware
- or there will be tears */
- if (port->console)
- return;
+ dbg("%s - port %d", __func__, port->number);
- serial = port->serial;
- owner = serial->type->driver.owner;
- put_device(&port->dev);
- /* Mustn't dereference port any more */
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected)
- usb_autopm_put_interface(serial->interface);
- mutex_unlock(&serial->disc_mutex);
- usb_serial_put(serial);
- /* Mustn't dereference serial any more */
- module_put(owner);
+ serial_down(port);
+ tty_port_hangup(&port->port);
}
static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
- if (!port)
- return;
-
dbg("%s - port %d", __func__, port->number);
- /* FIXME:
- This leaves a very narrow race. Really we should do the
- serial_do_free() on tty->shutdown(), but tty->shutdown can
- be called from IRQ context and serial_do_free can sleep.
-
- The right fix is probably to make the tty free (which is rare)
- and thus tty->shutdown() occur via a work queue and simplify all
- the drivers that use it.
- */
- if (tty_hung_up_p(filp)) {
- /* serial_hangup already called serial_down at this point.
- Another user may have already reopened the port but
- serial_do_free is refcounted */
- serial_do_free(port);
+ if (tty_hung_up_p(filp))
return;
- }
-
if (tty_port_close_start(&port->port, tty, filp) == 0)
return;
-
- serial_do_down(port);
+ serial_down(port);
tty_port_close_end(&port->port, tty);
tty_port_tty_set(&port->port, NULL);
- serial_do_free(port);
}
-static void serial_hangup(struct tty_struct *tty)
+/**
+ * serial_release - free resources post close/hangup
+ * @port: port to free up
+ *
+ * Do the resource freeing and refcount dropping for the port.
+ * Avoid freeing the console.
+ *
+ * Called when the last tty kref is dropped.
+ */
+static void serial_release(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- serial_do_down(port);
- tty_port_hangup(&port->port);
- /* We must not free port yet - the USB serial layer depends on it's
- continued existence */
+ struct usb_serial *serial;
+ struct module *owner;
+
+ /* The console is magical. Do not hang up the console hardware
+ * or there will be tears.
+ */
+ if (port->console)
+ return;
+
+ dbg("%s - port %d", __func__, port->number);
+
+ /* Standard shutdown processing */
+ tty_shutdown(tty);
+
+ tty->driver_data = NULL;
+
+ serial = port->serial;
+ owner = serial->type->driver.owner;
+
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ usb_autopm_put_interface(serial->interface);
+ mutex_unlock(&serial->disc_mutex);
+
+ usb_serial_put(serial);
+ module_put(owner);
}
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
@@ -527,6 +526,7 @@ static int serial_proc_show(struct seq_file *m, void *v)
seq_putc(m, '\n');
usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
}
return 0;
}
@@ -596,14 +596,6 @@ static void usb_serial_port_work(struct work_struct *work)
tty_kref_put(tty);
}
-static void port_release(struct device *dev)
-{
- struct usb_serial_port *port = to_usb_serial_port(dev);
-
- dbg ("%s - %s", __func__, dev_name(dev));
- port_free(port);
-}
-
static void kill_traffic(struct usb_serial_port *port)
{
usb_kill_urb(port->read_urb);
@@ -623,8 +615,12 @@ static void kill_traffic(struct usb_serial_port *port)
usb_kill_urb(port->interrupt_out_urb);
}
-static void port_free(struct usb_serial_port *port)
+static void port_release(struct device *dev)
{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+
+ dbg ("%s - %s", __func__, dev_name(dev));
+
/*
* Stop all the traffic before cancelling the work, so that
* nobody will restart it by calling usb_serial_port_softint.
@@ -935,6 +931,11 @@ int usb_serial_probe(struct usb_interface *interface,
mutex_init(&port->mutex);
INIT_WORK(&port->work, usb_serial_port_work);
serial->port[i] = port;
+ port->dev.parent = &interface->dev;
+ port->dev.driver = NULL;
+ port->dev.bus = &usb_serial_bus_type;
+ port->dev.release = &port_release;
+ device_initialize(&port->dev);
}
/* set up the endpoint information */
@@ -1060,12 +1061,15 @@ int usb_serial_probe(struct usb_interface *interface,
module_put(type->driver.owner);
if (retval < 0)
goto probe_error;
+ serial->attached = 1;
if (retval > 0) {
/* quietly accept this device, but don't bind to a
serial port as it's about to disappear */
serial->num_ports = 0;
goto exit;
}
+ } else {
+ serial->attached = 1;
}
if (get_free_serial(serial, num_ports, &minor) == NULL) {
@@ -1077,15 +1081,10 @@ int usb_serial_probe(struct usb_interface *interface,
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
port = serial->port[i];
- port->dev.parent = &interface->dev;
- port->dev.driver = NULL;
- port->dev.bus = &usb_serial_bus_type;
- port->dev.release = &port_release;
-
dev_set_name(&port->dev, "ttyUSB%d", port->number);
dbg ("%s - registering %s", __func__, dev_name(&port->dev));
port->dev_state = PORT_REGISTERING;
- retval = device_register(&port->dev);
+ retval = device_add(&port->dev);
if (retval) {
dev_err(&port->dev, "Error registering port device, "
"continuing\n");
@@ -1103,39 +1102,7 @@ exit:
return 0;
probe_error:
- for (i = 0; i < num_bulk_in; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->read_urb);
- kfree(port->bulk_in_buffer);
- }
- for (i = 0; i < num_bulk_out; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->write_urb);
- kfree(port->bulk_out_buffer);
- }
- for (i = 0; i < num_interrupt_in; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->interrupt_in_urb);
- kfree(port->interrupt_in_buffer);
- }
- for (i = 0; i < num_interrupt_out; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->interrupt_out_urb);
- kfree(port->interrupt_out_buffer);
- }
-
- /* free up any memory that we allocated */
- for (i = 0; i < serial->num_port_pointers; ++i)
- kfree(serial->port[i]);
- kfree(serial);
+ usb_serial_put(serial);
return -EIO;
}
EXPORT_SYMBOL_GPL(usb_serial_probe);
@@ -1161,10 +1128,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
if (port) {
struct tty_struct *tty = tty_port_tty_get(&port->port);
if (tty) {
- /* The hangup will occur asynchronously but
- the object refcounts will sort out all the
- cleanup */
- tty_hangup(tty);
+ tty_vhangup(tty);
tty_kref_put(tty);
}
kill_traffic(port);
@@ -1189,8 +1153,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
}
serial->type->disconnect(serial);
- /* let the last holder of this object
- * cause it to be cleaned up */
+ /* let the last holder of this object cause it to be cleaned up */
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
@@ -1246,6 +1209,8 @@ static const struct tty_operations serial_ops = {
.chars_in_buffer = serial_chars_in_buffer,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
+ .shutdown = serial_release,
+ .install = serial_install,
.proc_fops = &serial_proc_fops,
};
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 8d126dd7a02e..f7232b1bce51 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -259,7 +259,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
__u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
static int firm_close(struct usb_serial_port *port);
-static int firm_setup_port(struct tty_struct *tty);
+static void firm_setup_port(struct tty_struct *tty);
static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
@@ -1211,7 +1211,7 @@ static int firm_close(struct usb_serial_port *port)
}
-static int firm_setup_port(struct tty_struct *tty)
+static void firm_setup_port(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_port_settings port_settings;
@@ -1286,7 +1286,7 @@ static int firm_setup_port(struct tty_struct *tty)
port_settings.lloop = 0;
/* now send the message to the device */
- return firm_send_command(port, WHITEHEAT_SETUP_PORT,
+ firm_send_command(port, WHITEHEAT_SETUP_PORT,
(__u8 *)&port_settings, sizeof(port_settings));
}
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ec17c96371af..105d900150c1 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -102,5 +102,5 @@ int usb_stor_huawei_e220_init(struct us_data *us)
USB_TYPE_STANDARD | USB_RECIP_DEVICE,
0x01, 0x0, NULL, 0x0, 1000);
US_DEBUGP("Huawei mode set result is %d\n", result);
- return (result ? 0 : -ENODEV);
+ return 0;
}
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 380233bd6a39..80e65f29921c 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -163,7 +163,7 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action)
usb_kill_urb(onetouch->irq);
break;
case US_RESUME:
- if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
+ if (usb_submit_urb(onetouch->irq, GFP_NOIO) != 0)
dev_err(&onetouch->irq->dev->dev,
"usb_submit_urb failed\n");
break;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index e20dc525d177..cc313d16d727 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -666,10 +666,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
* to wait for at least one CHECK_CONDITION to determine
* SANE_SENSE support
*/
- if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) &&
+ if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) &&
result == USB_STOR_TRANSPORT_GOOD &&
!(us->fflags & US_FL_SANE_SENSE) &&
- !(srb->cmnd[2] & 0x20)) {
+ !(us->fflags & US_FL_BAD_SENSE) &&
+ !(srb->cmnd[2] & 0x20))) {
US_DEBUGP("-- SAT supported, increasing auto-sense\n");
us->fflags |= US_FL_SANE_SENSE;
}
@@ -696,7 +697,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* device supports and needs bigger sense buffer */
if (us->fflags & US_FL_SANE_SENSE)
sense_size = ~0;
-
+Retry_Sense:
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
@@ -718,8 +719,30 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
US_DEBUGP("-- auto-sense aborted\n");
srb->result = DID_ABORT << 16;
+
+ /* If SANE_SENSE caused this problem, disable it */
+ if (sense_size != US_SENSE_SIZE) {
+ us->fflags &= ~US_FL_SANE_SENSE;
+ us->fflags |= US_FL_BAD_SENSE;
+ }
goto Handle_Errors;
}
+
+ /* Some devices claim to support larger sense but fail when
+ * trying to request it. When a transport failure happens
+ * using US_FS_SANE_SENSE, we always retry with a standard
+ * (small) sense request. This fixes some USB GSM modems
+ */
+ if (temp_result == USB_STOR_TRANSPORT_FAILED &&
+ sense_size != US_SENSE_SIZE) {
+ US_DEBUGP("-- auto-sense failure, retry small sense\n");
+ sense_size = US_SENSE_SIZE;
+ us->fflags &= ~US_FL_SANE_SENSE;
+ us->fflags |= US_FL_BAD_SENSE;
+ goto Retry_Sense;
+ }
+
+ /* Other failures */
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
US_DEBUGP("-- auto-sense failure\n");
@@ -739,6 +762,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
*/
if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) &&
!(us->fflags & US_FL_SANE_SENSE) &&
+ !(us->fflags & US_FL_BAD_SENSE) &&
(srb->sense_buffer[0] & 0x7C) == 0x70) {
US_DEBUGP("-- SANE_SENSE support enabled\n");
us->fflags |= US_FL_SANE_SENSE;
@@ -768,17 +792,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* set the result so the higher layers expect this data */
srb->result = SAM_STAT_CHECK_CONDITION;
- /* If things are really okay, then let's show that. Zero
- * out the sense buffer so the higher layers won't realize
- * we did an unsolicited auto-sense. */
- if (result == USB_STOR_TRANSPORT_GOOD &&
- /* Filemark 0, ignore EOM, ILI 0, no sense */
+ /* We often get empty sense data. This could indicate that
+ * everything worked or that there was an unspecified
+ * problem. We have to decide which.
+ */
+ if ( /* Filemark 0, ignore EOM, ILI 0, no sense */
(srb->sense_buffer[2] & 0xaf) == 0 &&
/* No ASC or ASCQ */
srb->sense_buffer[12] == 0 &&
srb->sense_buffer[13] == 0) {
- srb->result = SAM_STAT_GOOD;
- srb->sense_buffer[0] = 0x0;
+
+ /* If things are really okay, then let's show that.
+ * Zero out the sense buffer so the higher layers
+ * won't realize we did an unsolicited auto-sense.
+ */
+ if (result == USB_STOR_TRANSPORT_GOOD) {
+ srb->result = SAM_STAT_GOOD;
+ srb->sense_buffer[0] = 0x0;
+
+ /* If there was a problem, report an unspecified
+ * hardware error to prevent the higher layers from
+ * entering an infinite retry loop.
+ */
+ } else {
+ srb->result = DID_ERROR << 16;
+ srb->sense_buffer[2] = HARDWARE_ERROR;
+ }
}
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 7477d411959f..5ef11f435330 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -838,6 +838,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Daniel Kukula <daniel.kuku@gmail.com> */
+UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100,
+ "Prolific Technology, Inc.",
+ "Prolific Storage Gadget",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_BAD_SENSE ),
+
/* Reported by Rogerio Brito <rbrito@ime.usp.br> */
UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
"Prolific Technology, Inc.",
@@ -1820,13 +1827,6 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_GO_SLOW ),
-/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
-UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010,
- "INTOVA",
- "Pixtreme",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
-
/* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>
* Mio Moov 330
*/
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 11dd37de45c7..f3ba49f62408 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -228,6 +228,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
if (data_len<36) // You lose.
return;
+ memset(data+8, ' ', 28);
if(data[0]&0x20) { /* USB device currently not connected. Return
peripheral qualifier 001b ("...however, the
physical device is not currently connected
@@ -237,15 +238,15 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
device, it may return zeros or ASCII spaces
(20h) in those fields until the data is
available from the device."). */
- memset(data+8,0,28);
} else {
u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
- memcpy(data+8, us->unusual_dev->vendorName,
- strlen(us->unusual_dev->vendorName) > 8 ? 8 :
- strlen(us->unusual_dev->vendorName));
- memcpy(data+16, us->unusual_dev->productName,
- strlen(us->unusual_dev->productName) > 16 ? 16 :
- strlen(us->unusual_dev->productName));
+ int n;
+
+ n = strlen(us->unusual_dev->vendorName);
+ memcpy(data+8, us->unusual_dev->vendorName, min(8, n));
+ n = strlen(us->unusual_dev->productName);
+ memcpy(data+16, us->unusual_dev->productName, min(16, n));
+
data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
@@ -432,7 +433,8 @@ static void adjust_quirks(struct us_data *us)
u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
unsigned f = 0;
- unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY |
+ unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
+ US_FL_FIX_CAPACITY |
US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
@@ -462,6 +464,9 @@ static void adjust_quirks(struct us_data *us)
case 'a':
f |= US_FL_SANE_SENSE;
break;
+ case 'b':
+ f |= US_FL_BAD_SENSE;
+ break;
case 'c':
f |= US_FL_FIX_CAPACITY;
break;
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index b6449470106c..a482dd7b0311 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -56,7 +56,7 @@ static int fb_notifier_callback(struct notifier_block *self,
static int lcd_register_fb(struct lcd_device *ld)
{
- memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif));
+ memset(&ld->fb_notif, 0, sizeof(ld->fb_notif));
ld->fb_notif.notifier_call = fb_notifier_callback;
return fb_register_client(&ld->fb_notif);
}
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 2f50a80b413e..979b5a18588c 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -67,16 +67,9 @@ config SGI_NEWPORT_CONSOLE
# bool 'IODC console' CONFIG_IODC_CONSOLE
-config PROM_CONSOLE
- bool "PROM console"
- depends on SPARC
- help
- Say Y to build a console driver for Sun machines that uses the
- terminal emulation built into their console PROMS.
-
config DUMMY_CONSOLE
bool
- depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
+ depends on VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
default y
config DUMMY_CONSOLE_COLUMNS
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index ac46cc3f6a2a..a862e9173ebe 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -22,7 +22,6 @@ font-objs += $(font-objs-y)
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
-obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
@@ -40,14 +39,3 @@ obj-$(CONFIG_FB_STI) += sticore.o font.o
ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
obj-$(CONFIG_USB_SISUSBVGA) += font.o
endif
-
-# Targets that kbuild needs to know about
-targets := promcon_tbl.c
-
-quiet_cmd_conmakehash = CNMKHSH $@
- cmd_conmakehash = scripts/conmakehash $< | \
- sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \
- -e 's/dfont\(_uni.*\]\)/promfont\1 /' > $@
-
-$(obj)/promcon_tbl.c: $(src)/prom.uni
- $(call cmd,conmakehash)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3a44695b9c09..29ff5ea3cc3c 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -114,6 +114,7 @@ static int last_fb_vc = MAX_NR_CONSOLES - 1;
static int fbcon_is_default = 1;
static int fbcon_has_exited;
static int primary_device = -1;
+static int fbcon_has_console_bind;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
static int map_override;
@@ -544,6 +545,8 @@ static int fbcon_takeover(int show_logo)
con2fb_map[i] = -1;
}
info_idx = -1;
+ } else {
+ fbcon_has_console_bind = 1;
}
return err;
@@ -2923,6 +2926,10 @@ static int fbcon_unbind(void)
ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
fbcon_is_default);
+
+ if (!ret)
+ fbcon_has_console_bind = 0;
+
return ret;
}
#else
@@ -2936,6 +2943,9 @@ static int fbcon_fb_unbind(int idx)
{
int i, new_idx = -1, ret = 0;
+ if (!fbcon_has_console_bind)
+ return 0;
+
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map[i] != idx &&
con2fb_map[i] != -1) {
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index d42346e7fdda..3dcb6d218f7c 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -341,7 +341,8 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
M1064_XDVICLKCTRL_C1DVICLKEN |
M1064_XDVICLKCTRL_DVILOOPCTL |
M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
- matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL,tmp);
+ /* Setting this breaks PC systems so don't do it */
+ /* matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL,tmp); */
matroxfb_DAC_out(PMINFO M1064_XPWRCTRL,
xpwrctrl);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 9c4739c8b19c..34e4e7995169 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -35,11 +35,6 @@ EXPORT_SYMBOL_GPL(fb_mode_option);
*/
static const struct fb_videomode modedb[] = {
- {
- /* 800x480 @ 60 Hz, 31.5 kHz hsync */
- "LQ070Y3DG3B", 60, 800, 480, 44000, 0, 50, 25, 10, 128, 10,
- FB_SYNC_EXT,FB_VMODE_NONINTERLACED
- },
{
/* 640x400 @ 70 Hz, 31.5 kHz hsync */
NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
diff --git a/drivers/video/mxc/Kconfig b/drivers/video/mxc/Kconfig
index 42f990ac3499..e86e6d86b978 100644
--- a/drivers/video/mxc/Kconfig
+++ b/drivers/video/mxc/Kconfig
@@ -38,10 +38,6 @@ config FB_MXC_CLAA_WVGA_SYNC_PANEL
depends on FB_MXC_SYNC_PANEL
tristate "CLAA WVGA Panel"
-config FB_MXC_SII9022
- depends on FB_MXC_SYNC_PANEL
- tristate "Si Image SII9022 DVI/HDMI Interface Chip"
-
config FB_MXC_CH7026
depends on FB_MXC_SYNC_PANEL
tristate "Chrontel CH7026 VGA Interface Chip"
diff --git a/drivers/video/mxc/Makefile b/drivers/video/mxc/Makefile
index d823ab29f030..b47b3f77cd80 100644
--- a/drivers/video/mxc/Makefile
+++ b/drivers/video/mxc/Makefile
@@ -21,4 +21,3 @@ obj-$(CONFIG_FB_MXC_TVOUT_TVE) += tve.o
obj-$(CONFIG_FB_MXC_CH7026) += mxcfb_ch7026.o
#obj-$(CONFIG_FB_MODE_HELPERS) += mxc_edid.o
obj-$(CONFIG_VIDEO_AD9389) += ad9389.o
-obj-$(CONFIG_FB_MXC_SII9022) += mxcfb_sii9022.o
diff --git a/drivers/video/mxc/mxc_elcdif_fb.c b/drivers/video/mxc/mxc_elcdif_fb.c
index e163edb7bfb9..44587d28c7f9 100644
--- a/drivers/video/mxc/mxc_elcdif_fb.c
+++ b/drivers/video/mxc/mxc_elcdif_fb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -64,8 +64,7 @@
#define ELCDIF_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R')
struct mxc_elcdif_fb_data {
- int cur_blank;
- int next_blank;
+ int is_blank;
int output_pix_fmt;
int elcdif_mode;
ssize_t mem_size;
@@ -518,7 +517,7 @@ static inline void mxc_init_elcdif(void)
return;
}
-int mxc_elcdif_frame_addr_setup(dma_addr_t phys)
+static inline int mxc_elcdif_dma_init(dma_addr_t phys)
{
int ret = 0;
@@ -807,7 +806,7 @@ static int mxc_elcdif_fb_set_par(struct fb_info *fbi)
return -ENOMEM;
}
- if (data->next_blank != FB_BLANK_UNBLANK)
+ if (data->is_blank)
return 0;
/* init next panel */
@@ -846,7 +845,7 @@ static int mxc_elcdif_fb_set_par(struct fb_info *fbi)
data->output_pix_fmt,
sig_cfg,
1);
- mxc_elcdif_frame_addr_setup(fbi->fix.smem_start);
+ mxc_elcdif_dma_init(fbi->fix.smem_start);
mxc_elcdif_run();
mxc_elcdif_blank_panel(FB_BLANK_UNBLANK);
@@ -951,7 +950,7 @@ static int mxc_elcdif_fb_wait_for_vsync(u32 channel, struct fb_info *info)
(struct mxc_elcdif_fb_data *)info->par;
int ret = 0;
- if (data->cur_blank != FB_BLANK_UNBLANK) {
+ if (data->is_blank) {
dev_err(info->device, "can't wait for VSYNC when fb "
"is blank\n");
return -EINVAL;
@@ -991,15 +990,6 @@ static int mxc_elcdif_fb_ioctl(struct fb_info *info, unsigned int cmd,
if (!get_user(channel, (__u32 __user *) arg))
ret = mxc_elcdif_fb_wait_for_vsync(channel, info);
break;
- case MXCFB_GET_FB_BLANK:
- {
- struct mxc_elcdif_fb_data *data =
- (struct mxc_elcdif_fb_data *)info->par;
-
- if (put_user(data->cur_blank, (__u32 __user *)arg))
- return -EFAULT;
- break;
- }
default:
break;
}
@@ -1012,28 +1002,22 @@ static int mxc_elcdif_fb_blank(int blank, struct fb_info *info)
(struct mxc_elcdif_fb_data *)info->par;
int ret = 0;
- if (data->cur_blank == blank)
+ if (data->is_blank == (blank != FB_BLANK_UNBLANK))
return ret;
- data->next_blank = blank;
-
- if (!g_elcdif_pix_clk_enable) {
- clk_enable(g_elcdif_pix_clk);
- g_elcdif_pix_clk_enable = true;
+ if (blank == FB_BLANK_UNBLANK) {
+ if (!g_elcdif_pix_clk_enable) {
+ clk_enable(g_elcdif_pix_clk);
+ g_elcdif_pix_clk_enable = true;
+ }
}
ret = mxc_elcdif_blank_panel(blank);
if (ret == 0)
- data->cur_blank = blank;
+ data->is_blank = (blank != FB_BLANK_UNBLANK);
else
return ret;
- if (blank == FB_BLANK_UNBLANK) {
- ret = mxc_elcdif_fb_set_par(info);
- if (ret)
- return ret;
- }
-
- if (data->cur_blank != FB_BLANK_UNBLANK) {
+ if (data->is_blank) {
if (g_elcdif_axi_clk_enable) {
clk_disable(g_elcdif_axi_clk);
g_elcdif_axi_clk_enable = false;
@@ -1064,7 +1048,7 @@ static int mxc_elcdif_fb_pan_display(struct fb_var_screeninfo *var,
int ret = 0;
unsigned long base;
- if (data->cur_blank != FB_BLANK_UNBLANK) {
+ if (data->is_blank) {
dev_err(info->device, "can't do pan display when fb "
"is blank\n");
return -EINVAL;
@@ -1187,7 +1171,7 @@ static int mxc_elcdif_fb_probe(struct platform_device *pdev)
}
data = (struct mxc_elcdif_fb_data *)fbi->par;
- data->cur_blank = data->next_blank = FB_BLANK_UNBLANK;
+ data->is_blank = false;
fbi->var.activate = FB_ACTIVATE_NOW;
fbi->fbops = &mxc_elcdif_fb_ops;
@@ -1350,9 +1334,9 @@ static int mxc_elcdif_fb_suspend(struct platform_device *pdev,
acquire_console_sem();
fb_set_suspend(fbi, 1);
- saved_blank = data->cur_blank;
+ saved_blank = data->is_blank;
mxc_elcdif_fb_blank(FB_BLANK_POWERDOWN, fbi);
- data->next_blank = saved_blank;
+ data->is_blank = saved_blank;
if (!g_elcdif_pix_clk_enable) {
clk_enable(g_elcdif_pix_clk);
g_elcdif_pix_clk_enable = true;
@@ -1363,11 +1347,7 @@ static int mxc_elcdif_fb_suspend(struct platform_device *pdev,
clk_disable(g_elcdif_pix_clk);
g_elcdif_pix_clk_enable = false;
}
- if (g_elcdif_axi_clk_enable) {
- clk_disable(g_elcdif_axi_clk);
- g_elcdif_axi_clk_enable = false;
- }
- release_console_sem();
+
return 0;
}
@@ -1377,7 +1357,20 @@ static int mxc_elcdif_fb_resume(struct platform_device *pdev)
struct mxc_elcdif_fb_data *data = (struct mxc_elcdif_fb_data *)fbi->par;
acquire_console_sem();
- mxc_elcdif_fb_blank(data->next_blank, fbi);
+ if (!g_elcdif_pix_clk_enable) {
+ clk_enable(g_elcdif_pix_clk);
+ g_elcdif_pix_clk_enable = true;
+ }
+ mxc_init_elcdif();
+ mxc_elcdif_init_panel();
+ mxc_elcdif_dma_init(fbi->fix.smem_start);
+ mxc_elcdif_run();
+ if (g_elcdif_pix_clk_enable) {
+ clk_disable(g_elcdif_pix_clk);
+ g_elcdif_pix_clk_enable = false;
+ }
+ if (!data->is_blank)
+ mxc_elcdif_fb_blank(FB_BLANK_UNBLANK, fbi);
fb_set_suspend(fbi, 0);
release_console_sem();
diff --git a/drivers/video/mxc/mxc_epdc_fb.c b/drivers/video/mxc/mxc_epdc_fb.c
index e9aa9fc72f9c..27f9faa64e53 100644
--- a/drivers/video/mxc/mxc_epdc_fb.c
+++ b/drivers/video/mxc/mxc_epdc_fb.c
@@ -21,6 +21,8 @@
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
*/
+/*#define NO_POWERDOWN*/
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -55,7 +57,6 @@
/*#define DEFAULT_PANEL_HW_INIT*/
#define NUM_SCREENS 2
-#define NUM_SCREENS_X 16
#define EPDC_NUM_LUTS 16
#define EPDC_MAX_NUM_UPDATES 20
#define INVALID_LUT -1
@@ -71,7 +72,20 @@
#define POWER_STATE_ON 1
static unsigned long default_bpp = 16;
-static unsigned long g_num_screens = NUM_SCREENS;
+
+struct mxc_epdc_platform_fb_entry {
+ char name[16];
+ u16 x_res;
+ u16 y_res;
+ u16 bpp;
+ u32 cycle_time_ns;
+ struct list_head link;
+};
+
+struct mxc_epdc_platform_fb_data {
+ struct list_head list;
+ struct mxc_epdc_platform_fb_entry *cur;
+};
struct update_marker_data {
u32 update_marker;
@@ -99,15 +113,13 @@ struct update_data_list {
struct mxc_epdc_fb_data {
struct fb_info info;
u32 pseudo_palette[16];
- char *fb_panel_str;
struct list_head list;
- struct mxc_epdc_fb_mode *cur_mode;
- struct mxc_epdc_fb_platform_data *pdata;
+ struct mxc_epdc_platform_fb_entry *cur;
int blank;
+ ssize_t mem_size;
ssize_t map_size;
dma_addr_t phys_start;
u32 fb_offset;
- int default_bpp;
int native_width;
int native_height;
int epdc_irq;
@@ -143,10 +155,9 @@ struct mxc_epdc_fb_data {
struct update_marker_data update_marker_array[EPDC_MAX_NUM_UPDATES];
u32 lut_update_type[EPDC_NUM_LUTS];
struct completion updates_done;
- struct delayed_work epdc_done_work;
+ struct work_struct epdc_done_work;
struct mutex power_mutex;
bool powering_down;
- int pwrdown_delay;
/* FB elements related to PxP DMA */
struct completion pxp_tx_cmpl;
@@ -191,12 +202,35 @@ struct mxcfb_waveform_data_file {
void __iomem *epdc_base;
+#define NUM_PANELS 1
+
+static struct fb_videomode panel_modes[NUM_PANELS] = {
+ {
+ /* 800x600 @ 60 Hz , pixel clk @ 20MHz */
+ "E-INK SVGA", 60, 800, 600, 50000, 8, 142, 4, 10, 20, 4,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+/*
+ * This is a temporary placeholder
+ * Ultimately, this declaration will be off in a panel-specific file,
+ * and will include implementations for all of the panel functions
+ */
+static struct mxc_epdc_platform_fb_entry ed060sc4_fb_entry = {
+ .name = "ed060sc4",
+ .x_res = 800,
+ .y_res = 600,
+ .bpp = 16,
+ .cycle_time_ns = 200,
+};
+
/* forward declaration */
static int mxc_epdc_fb_blank(int blank, struct fb_info *info);
static int mxc_epdc_fb_init_hw(struct fb_info *info);
static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
- struct mxcfb_rect *update_region,
- int x_start_offs);
+ struct mxcfb_rect *update_region);
static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat);
static void draw_mode0(struct mxc_epdc_fb_data *fb_data);
@@ -392,6 +426,47 @@ static inline void dump_all_updates(struct mxc_epdc_fb_data *fb_data) {}
#endif
+void check_waveform(u32 *wv_buf_orig, u32 *wv_buf_cur, u32 wv_buf_size)
+{
+ int i;
+ bool is_mismatch = false;
+ for (i = 0; i < wv_buf_size; i++) {
+ if (wv_buf_orig[i] != wv_buf_cur[i]) {
+ is_mismatch = true;
+ printk
+ ("Waveform mismatch - wv_buf_orig[%d] = 0x%x, wv_buf_cur[%d] = 0x%x\n",
+ i, wv_buf_orig[i], i, wv_buf_cur[i]);
+ }
+ }
+
+ if (!is_mismatch)
+ printk("No mismatches!\n");
+}
+
+static struct fb_var_screeninfo mxc_epdc_fb_default __devinitdata = {
+ .activate = FB_ACTIVATE_TEST,
+ .height = -1,
+ .width = -1,
+ .pixclock = 20000,
+ .left_margin = 8,
+ .right_margin = 142,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo mxc_epdc_fb_fix __devinitdata = {
+ .id = "mxc_epdc_fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+ .line_length = 800 * 2,
+};
/********************************************************
* Start Low-Level EPDC Functions
@@ -579,10 +654,9 @@ static void epdc_set_vertical_timing(u32 vert_start, u32 vert_end,
void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
{
- struct mxc_epdc_fb_mode *epdc_mode = fb_data->cur_mode;
+ struct mxc_epdc_platform_fb_entry *pentry = fb_data->cur;
struct fb_var_screeninfo *screeninfo = &fb_data->info.var;
u32 reg_val;
- int num_ce;
/* Reset */
__raw_writel(EPDC_CTRL_SFTRST, EPDC_CTRL_SET);
@@ -624,7 +698,7 @@ void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
epdc_set_temp(8);
/* EPDC_RES */
- epdc_set_screen_res(epdc_mode->vmode->xres, epdc_mode->vmode->yres);
+ epdc_set_screen_res(pentry->x_res, pentry->y_res);
/*
* EPDC_TCE_CTRL
@@ -639,7 +713,7 @@ void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
* PIXELS_PER_SDCLK = 4
*/
reg_val =
- ((epdc_mode->vscan_holdoff << EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) &
+ ((4 << EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) &
EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK)
| EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4;
__raw_writel(reg_val, EPDC_TCE_CTRL);
@@ -657,13 +731,13 @@ void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
/* EPDC_TCE_OE */
reg_val =
- ((epdc_mode->sdoed_width << EPDC_TCE_OE_SDOED_WIDTH_OFFSET) &
+ ((10 << EPDC_TCE_OE_SDOED_WIDTH_OFFSET) &
EPDC_TCE_OE_SDOED_WIDTH_MASK)
- | ((epdc_mode->sdoed_delay << EPDC_TCE_OE_SDOED_DLY_OFFSET) &
+ | ((20 << EPDC_TCE_OE_SDOED_DLY_OFFSET) &
EPDC_TCE_OE_SDOED_DLY_MASK)
- | ((epdc_mode->sdoez_width << EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) &
+ | ((10 << EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) &
EPDC_TCE_OE_SDOEZ_WIDTH_MASK)
- | ((epdc_mode->sdoez_delay << EPDC_TCE_OE_SDOEZ_DLY_OFFSET) &
+ | ((20 << EPDC_TCE_OE_SDOEZ_DLY_OFFSET) &
EPDC_TCE_OE_SDOEZ_DLY_MASK);
__raw_writel(reg_val, EPDC_TCE_OE);
@@ -672,17 +746,17 @@ void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
/* EPDC_TCE_TIMING2 */
reg_val =
- ((epdc_mode->gdclk_hp_offs << EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) &
+ ((480 << EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) &
EPDC_TCE_TIMING2_GDCLK_HP_MASK)
- | ((epdc_mode->gdsp_offs << EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) &
+ | ((20 << EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) &
EPDC_TCE_TIMING2_GDSP_OFFSET_MASK);
__raw_writel(reg_val, EPDC_TCE_TIMING2);
/* EPDC_TCE_TIMING3 */
reg_val =
- ((epdc_mode->gdoe_offs << EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) &
+ ((0 << EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) &
EPDC_TCE_TIMING3_GDOE_OFFSET_MASK)
- | ((epdc_mode->gdclk_offs << EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) &
+ | ((1 << EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) &
EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK);
__raw_writel(reg_val, EPDC_TCE_TIMING3);
@@ -695,14 +769,10 @@ void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
* SDDO_INVERT = DISABLED
* PIXELS_PER_CE = display horizontal resolution
*/
- num_ce = epdc_mode->num_ce;
- if (num_ce == 0)
- num_ce = 1;
reg_val = EPDC_TCE_SDCFG_SDCLK_HOLD | EPDC_TCE_SDCFG_SDSHR
- | ((num_ce << EPDC_TCE_SDCFG_NUM_CE_OFFSET) &
- EPDC_TCE_SDCFG_NUM_CE_MASK)
+ | ((1 << EPDC_TCE_SDCFG_NUM_CE_OFFSET) & EPDC_TCE_SDCFG_NUM_CE_MASK)
| EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS
- | ((epdc_mode->vmode->xres/num_ce << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) &
+ | ((pentry->x_res << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) &
EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK);
__raw_writel(reg_val, EPDC_TCE_SDCFG);
@@ -760,10 +830,6 @@ static void epdc_powerup(struct mxc_epdc_fb_data *fb_data)
dev_dbg(fb_data->dev, "EPDC Powerup\n");
- /* Enable pins used by EPDC */
- if (fb_data->pdata->enable_pins)
- fb_data->pdata->enable_pins();
-
/* Enable clocks to EPDC */
clk_enable(fb_data->epdc_clk_axi);
clk_enable(fb_data->epdc_clk_pix);
@@ -803,10 +869,6 @@ static void epdc_powerdown(struct mxc_epdc_fb_data *fb_data)
clk_disable(fb_data->epdc_clk_pix);
clk_disable(fb_data->epdc_clk_axi);
- /* Disable pins used by EPDC (to prevent leakage current) */
- if (fb_data->pdata->disable_pins)
- fb_data->pdata->disable_pins();
-
fb_data->power_state = POWER_STATE_OFF;
fb_data->powering_down = false;
@@ -1013,7 +1075,7 @@ static int mxc_epdc_fb_set_par(struct fb_info *info)
break;
}
}
- pxp_conf->s0_param.width = screeninfo->xres_virtual;
+ pxp_conf->s0_param.width = screeninfo->xres;
pxp_conf->s0_param.height = screeninfo->yres;
pxp_conf->s0_param.color_key = -1;
pxp_conf->s0_param.color_key_enable = false;
@@ -1032,24 +1094,19 @@ static int mxc_epdc_fb_set_par(struct fb_info *info)
* an initialization request.
*/
if (!fb_data->hw_ready) {
- for (i = 0; i < fb_data->pdata->num_modes; i++) {
- struct fb_videomode *vmode =
- fb_data->pdata->epdc_mode[i].vmode;
- /* Check resolution for a match
- with supported panel types */
- if ((screeninfo->xres != vmode->xres) ||
- (screeninfo->yres != vmode->yres))
+ for (i = 0; i < NUM_PANELS; i++) {
+ /* Check resolution for a match with supported panel types */
+ if ((screeninfo->xres != panel_modes[i].xres) ||
+ (screeninfo->yres != panel_modes[i].yres))
continue;
- fb_data->cur_mode = &fb_data->pdata->epdc_mode[i];
-
/* Found a match - Grab timing params */
- screeninfo->left_margin = vmode->left_margin;
- screeninfo->right_margin = vmode->right_margin;
- screeninfo->upper_margin = vmode->upper_margin;
- screeninfo->lower_margin = vmode->lower_margin;
- screeninfo->hsync_len = vmode->hsync_len;
- screeninfo->vsync_len = vmode->vsync_len;
+ screeninfo->left_margin = panel_modes[i].left_margin;
+ screeninfo->right_margin = panel_modes[i].right_margin;
+ screeninfo->upper_margin = panel_modes[i].upper_margin;
+ screeninfo->lower_margin = panel_modes[i].lower_margin;
+ screeninfo->hsync_len = panel_modes[i].hsync_len;
+ screeninfo->vsync_len = panel_modes[i].vsync_len;
/* Initialize EPDC settings and init panel */
ret =
@@ -1183,13 +1240,15 @@ static int mxc_epdc_fb_check_var(struct fb_var_screeninfo *var,
switch (var->rotate) {
case FB_ROTATE_UR:
case FB_ROTATE_UD:
- var->xres = fb_data->native_width;
+ var->xres = var->xres_virtual = fb_data->native_width;
var->yres = fb_data->native_height;
+ var->yres_virtual = var->yres * 2;
break;
case FB_ROTATE_CW:
case FB_ROTATE_CCW:
- var->xres = fb_data->native_height;
+ var->xres = var->xres_virtual = fb_data->native_height;
var->yres = fb_data->native_width;
+ var->yres_virtual = var->yres * 2;
break;
default:
/* Invalid rotation value */
@@ -1198,9 +1257,6 @@ static int mxc_epdc_fb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
- var->xres_virtual = ALIGN(var->xres, 32);
- var->yres_virtual = ALIGN(var->yres, 128) * g_num_screens;
-
var->height = -1;
var->width = -1;
@@ -1282,7 +1338,7 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
u32 offset_from_8, bytes_per_pixel;
u32 post_rotation_xcoord, post_rotation_ycoord, width_pxp_blocks;
u32 pxp_input_offs, pxp_output_offs, pxp_output_shift;
- int x_start_offs = 0;
+ int adj_left, adj_top;
u32 hist_stat = 0;
int temp_index;
bool wait_for_power = false;
@@ -1384,7 +1440,7 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
src_width = upd_data->alt_buffer_data.width;
src_upd_region = &upd_data->alt_buffer_data.alt_update_region;
} else {
- src_width = fb_data->info.var.xres_virtual;
+ src_width = fb_data->info.var.xres;
src_upd_region = screen_upd_region;
}
@@ -1411,21 +1467,11 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
pxp_upd_region.left = 0;
}
- /*
- * We want PxP processing region to start at the first pixel
- * that we have to process in each row, but PxP alignment
- * restricts the input mem address to be 32-bit aligned
- *
- * We work around this by using x_start_offs to offset
- * to offset from our starting pixel location to the
- * first pixel that is in the relevant update region
- * for each row.
- */
- x_start_offs = pxp_upd_region.left & 0x7;
-
/* Update region to meet 8x8 pixel requirement */
- pxp_upd_region.width = ALIGN(src_upd_region->width, 8);
- pxp_upd_region.height = ALIGN(src_upd_region->height, 8);
+ adj_left = pxp_upd_region.left & 0x7;
+ adj_top = pxp_upd_region.top & 0x7;
+ pxp_upd_region.width = ALIGN(src_upd_region->width + adj_left, 8);
+ pxp_upd_region.height = ALIGN(src_upd_region->height + adj_top, 8);
pxp_upd_region.top &= ~0x7;
pxp_upd_region.left &= ~0x7;
@@ -1484,8 +1530,7 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
mutex_lock(&fb_data->pxp_mutex);
/* This is a blocking call, so upon return PxP tx should be done */
- ret = pxp_process_update(fb_data, &pxp_upd_region,
- x_start_offs);
+ ret = pxp_process_update(fb_data, &pxp_upd_region);
if (ret) {
dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
mutex_unlock(&fb_data->pxp_mutex);
@@ -1644,97 +1689,52 @@ static int mxc_epdc_fb_wait_update_complete(u32 update_marker,
return 0;
}
-static int mxc_epdc_fb_set_pwrdown_delay(u32 pwrdown_delay,
- struct fb_info *info)
-{
- struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
-
- fb_data->pwrdown_delay = pwrdown_delay;
-
- return 0;
-}
-
static int mxc_epdc_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ struct mxcfb_waveform_modes modes;
+ int temperature;
+ u32 auto_mode = 0;
+ struct mxcfb_update_data upd_data;
+ u32 update_marker = 0;
int ret = -EINVAL;
switch (cmd) {
case MXCFB_SET_WAVEFORM_MODES:
- {
- struct mxcfb_waveform_modes modes;
- struct mxc_epdc_fb_data *fb_data =
- (struct mxc_epdc_fb_data *)info;
- if (!copy_from_user(&modes, argp, sizeof(modes))) {
- memcpy(&fb_data->wv_modes, &modes,
- sizeof(modes));
- ret = 0;
- }
- break;
+ if (!copy_from_user(&modes, argp, sizeof(modes))) {
+ memcpy(&fb_data->wv_modes, &modes, sizeof(modes));
+ ret = 0;
}
+ break;
case MXCFB_SET_TEMPERATURE:
- {
- int temperature;
- if (!get_user(temperature, (int32_t __user *) arg))
- ret =
- mxc_epdc_fb_set_temperature(temperature,
- info);
- break;
- }
+ if (!get_user(temperature, (int32_t __user *) arg))
+ ret =
+ mxc_epdc_fb_set_temperature(temperature,
+ info);
+ break;
case MXCFB_SET_AUTO_UPDATE_MODE:
- {
- u32 auto_mode = 0;
- if (!get_user(auto_mode, (__u32 __user *) arg))
- ret =
- mxc_epdc_fb_set_auto_update(auto_mode,
- info);
- break;
- }
+ if (!get_user(auto_mode, (__u32 __user *) arg))
+ ret =
+ mxc_epdc_fb_set_auto_update(auto_mode, info);
+ break;
case MXCFB_SEND_UPDATE:
- {
- struct mxcfb_update_data upd_data;
- if (!copy_from_user(&upd_data, argp,
- sizeof(upd_data))) {
- ret = mxc_epdc_fb_send_update(&upd_data, info);
- if (ret == 0 && copy_to_user(argp, &upd_data,
- sizeof(upd_data)))
- ret = -EFAULT;
- } else {
+ if (!copy_from_user(&upd_data, argp, sizeof(upd_data))) {
+ ret = mxc_epdc_fb_send_update(&upd_data, info);
+ if (ret == 0 && copy_to_user(argp, &upd_data, sizeof(upd_data)))
ret = -EFAULT;
- }
-
- break;
- }
- case MXCFB_WAIT_FOR_UPDATE_COMPLETE:
- {
- u32 update_marker = 0;
- if (!get_user(update_marker, (__u32 __user *) arg))
- ret =
- mxc_epdc_fb_wait_update_complete(update_marker,
- info);
- break;
- }
-
- case MXCFB_SET_PWRDOWN_DELAY:
- {
- int delay = 0;
- if (!get_user(delay, (__u32 __user *) arg))
- ret =
- mxc_epdc_fb_set_pwrdown_delay(delay, info);
- break;
+ } else {
+ ret = -EFAULT;
}
- case MXCFB_GET_PWRDOWN_DELAY:
- {
- struct mxc_epdc_fb_data *fb_data =
- (struct mxc_epdc_fb_data *)info;
- if (put_user(fb_data->pwrdown_delay,
- (int __user *)argp))
- ret = -EFAULT;
- ret = 0;
- break;
- }
+ break;
+ case MXCFB_WAIT_FOR_UPDATE_COMPLETE:
+ if (!get_user(update_marker, (__u32 __user *) arg))
+ ret =
+ mxc_epdc_fb_wait_update_complete(update_marker,
+ info);
+ break;
default:
break;
}
@@ -1833,6 +1833,10 @@ static int mxc_epdc_fb_blank(int blank, struct fb_info *info)
case FB_BLANK_NORMAL:
mxc_epdc_fb_disable(fb_data);
break;
+ case FB_BLANK_UNBLANK:
+ epdc_powerup(fb_data);
+ mxc_epdc_fb_set_par(info);
+ break;
}
return 0;
}
@@ -1841,6 +1845,8 @@ static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ struct mxcfb_update_data update;
+ int ret = 0;
u_int y_bottom;
dev_dbg(info->device, "%s: var->xoffset %d, info->var.xoffset %d\n",
@@ -1867,6 +1873,25 @@ static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var,
fb_data->fb_offset = (var->yoffset * var->xres_virtual + var->xoffset)
* (var->bits_per_pixel) / 8;
+ /* Update to new view of FB */
+ update.update_region.left = 0;
+ update.update_region.width = fb_data->info.var.xres;
+ update.update_region.top = 0;
+ update.update_region.height = fb_data->info.var.yres;
+ update.waveform_mode = WAVEFORM_MODE_AUTO;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.update_marker = PAN_UPDATE_MARKER;
+ update.temp = TEMP_USE_AMBIENT;
+ update.use_alt_buffer = false;
+
+ mxc_epdc_fb_send_update(&update, &fb_data->info);
+
+ /* Block on initial update */
+ ret = mxc_epdc_fb_wait_update_complete(update.update_marker, info);
+ if (ret < 0)
+ dev_err(fb_data->dev,
+ "Wait for update complete failed. Error = 0x%x", ret);
+
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
@@ -1875,7 +1900,7 @@ static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var,
else
info->var.vmode &= ~FB_VMODE_YWRAP;
- return 0;
+ return ret;
}
static struct fb_ops mxc_epdc_fb_ops = {
@@ -1893,15 +1918,14 @@ static struct fb_ops mxc_epdc_fb_ops = {
};
static struct fb_deferred_io mxc_epdc_fb_defio = {
- .delay = HZ,
+ .delay = HZ / 2,
.deferred_io = mxc_epdc_fb_deferred_io,
};
static void epdc_done_work_func(struct work_struct *work)
{
struct mxc_epdc_fb_data *fb_data =
- container_of(work, struct mxc_epdc_fb_data,
- epdc_done_work.work);
+ container_of(work, struct mxc_epdc_fb_data, epdc_done_work);
epdc_powerdown(fb_data);
}
@@ -2015,17 +2039,16 @@ static irqreturn_t mxc_epdc_irq_handler(int irq, void *dev_id)
(fb_data->cur_update == NULL) &&
!epdc_any_luts_active()) {
- if (fb_data->pwrdown_delay != FB_POWERDOWN_DISABLE) {
- /*
- * Set variable to prevent overlapping
- * enable/disable requests
- */
- fb_data->powering_down = true;
-
- /* Schedule task to disable EPDC HW until next update */
- schedule_delayed_work(&fb_data->epdc_done_work,
- msecs_to_jiffies(fb_data->pwrdown_delay));
- }
+#ifndef NO_POWERDOWN
+ /*
+ * Set variable to prevent overlapping
+ * enable/disable requests
+ */
+ fb_data->powering_down = true;
+
+ /* Schedule task to disable EPDC HW until next update */
+ schedule_work(&fb_data->epdc_done_work);
+#endif
if (fb_data->waiting_for_idle)
complete(&fb_data->updates_done);
@@ -2241,25 +2264,15 @@ static void draw_mode0(struct mxc_epdc_fb_data *fb_data)
static int mxc_epdc_fb_init_hw(struct fb_info *info)
{
struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ u32 wv_buf_size;
const struct firmware *fw;
- char *fw_str = "imx/epdc";
struct mxcfb_update_data update;
struct mxcfb_waveform_data_file *wv_file;
int wv_data_offs;
int ret;
int i;
- /*
- * Create fw search string based on ID string in selected videomode.
- * Format is "imx/epdc_[panel string].fw"
- */
- if (fb_data->cur_mode) {
- strcat(fw_str, "_");
- strcat(fw_str, fb_data->cur_mode->vmode->name);
- strcat(fw_str, ".fw");
- }
-
- ret = request_firmware(&fw, fw_str, fb_data->dev);
+ ret = request_firmware(&fw, "imx/epdc.fw", fb_data->dev);
if (ret) {
printk(KERN_ERR "Failed to load image imx/epdc.ihex err %d\n",
ret);
@@ -2280,20 +2293,20 @@ static int mxc_epdc_fb_init_hw(struct fb_info *info)
/* Get offset and size for waveform data */
wv_data_offs = sizeof(wv_file->wdh) + fb_data->trt_entries + 1;
- fb_data->waveform_buffer_size = fw->size - wv_data_offs;
+ wv_buf_size = fw->size - wv_data_offs;
/* Allocate memory for waveform data */
- fb_data->waveform_buffer_virt = dma_alloc_coherent(fb_data->dev,
- fb_data->waveform_buffer_size,
- &fb_data->waveform_buffer_phys,
- GFP_DMA);
+ fb_data->waveform_buffer_virt = dma_alloc_coherent(fb_data->dev, wv_buf_size,
+ &fb_data->waveform_buffer_phys,
+ GFP_DMA);
if (fb_data->waveform_buffer_virt == NULL) {
dev_err(fb_data->dev, "Can't allocate mem for waveform!\n");
ret = -ENOMEM;
}
- memcpy(fb_data->waveform_buffer_virt, (u8 *)(fw->data) + wv_data_offs,
- fb_data->waveform_buffer_size);
+ memcpy(fb_data->waveform_buffer_virt, (u8 *)(fw->data) + wv_data_offs, wv_buf_size);
+ check_waveform((u32 *)(fw->data + wv_data_offs),
+ fb_data->waveform_buffer_virt, wv_buf_size / 4);
release_firmware(fw);
@@ -2302,7 +2315,7 @@ static int mxc_epdc_fb_init_hw(struct fb_info *info)
/* Enable pix clk for EPDC */
clk_enable(fb_data->epdc_clk_pix);
- clk_set_rate(fb_data->epdc_clk_pix, fb_data->cur_mode->vmode->pixclock);
+ clk_set_rate(fb_data->epdc_clk_pix, 17700000);
epdc_init_sequence(fb_data);
@@ -2373,23 +2386,14 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
struct mxc_epdc_fb_data *fb_data;
struct resource *res;
struct fb_info *info;
- char *options, *opt;
- char *panel_str = NULL;
- char name[] = "mxcepdcfb";
- struct fb_videomode *vmode;
- int xres_virt, yres_virt, buf_size;
- struct fb_var_screeninfo *var_info;
- struct fb_fix_screeninfo *fix_info;
+ struct mxc_epdc_platform_fb_data *pdata;
+ struct mxc_epdc_platform_fb_entry *pentry;
struct pxp_config_data *pxp_conf;
struct pxp_proc_data *proc_data;
struct scatterlist *sg;
struct update_data_list *upd_list;
struct update_data_list *plist, *temp_list;
int i;
- unsigned long x_mem_size = 0;
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
- struct mxcfb_update_data update;
-#endif
fb_data = (struct mxc_epdc_fb_data *)framebuffer_alloc(
sizeof(struct mxc_epdc_fb_data), &pdev->dev);
@@ -2398,54 +2402,10 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
goto out;
}
- /* Get platform data and check validity */
- fb_data->pdata = pdev->dev.platform_data;
- if ((fb_data->pdata == NULL) || (fb_data->pdata->num_modes < 1)
- || (fb_data->pdata->epdc_mode == NULL)
- || (fb_data->pdata->epdc_mode->vmode == NULL)) {
- ret = -EINVAL;
- goto out_fbdata;
- }
-
- if (fb_get_options(name, &options)) {
- ret = -ENODEV;
- goto out_fbdata;
- }
-
- if (options)
- while ((opt = strsep(&options, ",")) != NULL) {
- if (!*opt)
- continue;
-
- if (!strncmp(opt, "bpp=", 4))
- fb_data->default_bpp =
- simple_strtoul(opt + 4, NULL, 0);
- else if (!strncmp(opt, "x_mem=", 6))
- x_mem_size =
- simple_strtoul(opt + 6, NULL, 0);
- else
- panel_str = opt;
- }
-
fb_data->dev = &pdev->dev;
-
- if (!fb_data->default_bpp)
- fb_data->default_bpp = 16;
-
- /* Set default (first defined mode) before searching for a match */
- fb_data->cur_mode = &fb_data->pdata->epdc_mode[0];
-
- if (panel_str)
- for (i = 0; i < fb_data->pdata->num_modes; i++)
- if (!strcmp(fb_data->pdata->epdc_mode[i].vmode->name,
- panel_str)) {
- fb_data->cur_mode =
- &fb_data->pdata->epdc_mode[i];
- break;
- }
-
- vmode = fb_data->cur_mode->vmode;
-
+ /* We want to use hard-coded structure defined in this file */
+ pentry = &ed060sc4_fb_entry;
+ fb_data->cur = pentry;
platform_set_drvdata(pdev, fb_data);
info = &fb_data->info;
@@ -2454,24 +2414,12 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
if (ret)
goto out_fbdata;
- dev_dbg(&pdev->dev, "resolution %dx%d, bpp %d\n",
- fb_data->cur_mode->vmode->xres,
- fb_data->cur_mode->vmode->yres, fb_data->default_bpp);
-
- /*
- * GPU alignment restrictions dictate framebuffer parameters:
- * - 32-byte alignment for buffer width
- * - 128-byte alignment for buffer height
- * => 4K buffer alignment for buffer start
- */
- xres_virt = ALIGN(vmode->xres, 32);
- yres_virt = ALIGN(vmode->yres, 128);
- buf_size = xres_virt * yres_virt * fb_data->default_bpp/8;
+ dev_dbg(&pdev->dev, "resolution %dx%d, bpp %d\n", pentry->x_res,
+ pentry->y_res, pentry->bpp);
- if (x_mem_size > 0)
- g_num_screens = NUM_SCREENS_X;
+ fb_data->mem_size = pentry->x_res * pentry->y_res * pentry->bpp/8;
- fb_data->map_size = PAGE_ALIGN(buf_size) * g_num_screens;
+ fb_data->map_size = PAGE_ALIGN(fb_data->mem_size) * NUM_SCREENS;
dev_dbg(&pdev->dev, "memory to allocate: %d\n", fb_data->map_size);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2499,69 +2447,49 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "allocated at %p:0x%x\n", info->screen_base,
fb_data->phys_start);
- var_info = &info->var;
-
- var_info->activate = FB_ACTIVATE_TEST;
- var_info->bits_per_pixel = fb_data->default_bpp;
- var_info->xres = vmode->xres;
- var_info->yres = vmode->yres;
- var_info->xres_virtual = xres_virt;
- /* Additional screens allow for panning and buffer flipping */
- var_info->yres_virtual = yres_virt * g_num_screens;
-
- var_info->pixclock = vmode->pixclock;
- var_info->left_margin = vmode->left_margin;
- var_info->right_margin = vmode->right_margin;
- var_info->upper_margin = vmode->upper_margin;
- var_info->lower_margin = vmode->lower_margin;
- var_info->hsync_len = vmode->hsync_len;
- var_info->vsync_len = vmode->vsync_len;
- var_info->vmode = FB_VMODE_NONINTERLACED;
-
- switch (fb_data->default_bpp) {
+ mxc_epdc_fb_default.bits_per_pixel = pentry->bpp;
+ mxc_epdc_fb_default.xres = pentry->x_res;
+ mxc_epdc_fb_default.yres = pentry->y_res;
+ mxc_epdc_fb_default.xres_virtual = pentry->x_res;
+ mxc_epdc_fb_default.yres_virtual = pentry->y_res * 2; /* FB doubled in virtual space */
+
+ mxc_epdc_fb_fix.smem_start = fb_data->phys_start;
+ mxc_epdc_fb_fix.smem_len = mxc_epdc_fb_default.yres_virtual
+ * pentry->x_res * 2 * pentry->bpp / 8;
+ mxc_epdc_fb_fix.ypanstep = 0;
+
+ switch (pentry->bpp) {
case 32:
case 24:
- var_info->red.offset = 16;
- var_info->red.length = 8;
- var_info->green.offset = 8;
- var_info->green.length = 8;
- var_info->blue.offset = 0;
- var_info->blue.length = 8;
+ mxc_epdc_fb_default.red.offset = 16;
+ mxc_epdc_fb_default.red.length = 8;
+ mxc_epdc_fb_default.green.offset = 8;
+ mxc_epdc_fb_default.green.length = 8;
+ mxc_epdc_fb_default.blue.offset = 0;
+ mxc_epdc_fb_default.blue.length = 8;
break;
case 16:
- var_info->red.offset = 11;
- var_info->red.length = 5;
- var_info->green.offset = 5;
- var_info->green.length = 6;
- var_info->blue.offset = 0;
- var_info->blue.length = 5;
+ mxc_epdc_fb_default.red.offset = 11;
+ mxc_epdc_fb_default.red.length = 5;
+ mxc_epdc_fb_default.green.offset = 5;
+ mxc_epdc_fb_default.green.length = 6;
+ mxc_epdc_fb_default.blue.offset = 0;
+ mxc_epdc_fb_default.blue.length = 5;
break;
default:
- dev_err(&pdev->dev, "unsupported bitwidth %d\n",
- fb_data->default_bpp);
+ dev_err(&pdev->dev, "unsupported bitwidth %d\n", pentry->bpp);
ret = -EINVAL;
goto out_dma_fb;
}
- fix_info = &info->fix;
-
- strcpy(fix_info->id, "mxc_epdc_fb");
- fix_info->type = FB_TYPE_PACKED_PIXELS;
- fix_info->visual = FB_VISUAL_TRUECOLOR;
- fix_info->xpanstep = 0;
- fix_info->ypanstep = 0;
- fix_info->ywrapstep = 0;
- fix_info->accel = FB_ACCEL_NONE;
- fix_info->smem_start = fb_data->phys_start;
- fix_info->smem_len = fb_data->map_size;
- fix_info->ypanstep = 0;
-
- fb_data->native_width = vmode->xres;
- fb_data->native_height = vmode->yres;
+ fb_data->native_width = pentry->x_res;
+ fb_data->native_height = pentry->y_res;
info->fbops = &mxc_epdc_fb_ops;
+ info->var = mxc_epdc_fb_default;
+ info->fix = mxc_epdc_fb_fix;
info->var.activate = FB_ACTIVATE_NOW;
info->pseudo_palette = fb_data->pseudo_palette;
info->screen_size = info->fix.smem_len;
@@ -2633,7 +2561,7 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
upd_list->size, upd_list->phys_addr);
}
- fb_data->working_buffer_size = vmode->yres * vmode->xres * 2;
+ fb_data->working_buffer_size = pentry->y_res * pentry->x_res * 2;
/* Allocate memory for EPDC working buffer */
fb_data->working_buffer_virt =
dma_alloc_coherent(&pdev->dev, fb_data->working_buffer_size,
@@ -2644,13 +2572,11 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
goto out_upd_buffers;
}
- /* Initialize EPDC pins */
- if (fb_data->pdata->get_pins)
- fb_data->pdata->get_pins();
-
fb_data->epdc_clk_axi = clk_get(fb_data->dev, "epdc_axi");
fb_data->epdc_clk_pix = clk_get(fb_data->dev, "epdc_pix");
+ clk_set_rate(fb_data->epdc_clk_axi, 200000000);
+
fb_data->in_init = false;
fb_data->hw_ready = false;
@@ -2691,11 +2617,10 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
fb_data->epdc_irq, ret);
- ret = -ENODEV;
goto out_dma_work_buf;
}
- INIT_DELAYED_WORK(&fb_data->epdc_done_work, epdc_done_work_func);
+ INIT_WORK(&fb_data->epdc_done_work, epdc_done_work_func);
info->fbdefio = &mxc_epdc_fb_defio;
#ifdef CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE
@@ -2706,17 +2631,15 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
fb_data->display_regulator = regulator_get(NULL, "DISPLAY");
if (IS_ERR(fb_data->display_regulator)) {
dev_err(&pdev->dev, "Unable to get display PMIC regulator."
- "err = 0x%x\n", (int)fb_data->display_regulator);
- ret = -ENODEV;
- goto out_irq;
+ "err = 0x%x\n", fb_data->display_regulator);
+ goto out_dma_work_buf;
}
fb_data->vcom_regulator = regulator_get(NULL, "VCOM");
if (IS_ERR(fb_data->vcom_regulator)) {
regulator_put(fb_data->display_regulator);
dev_err(&pdev->dev, "Unable to get VCOM regulator."
- "err = 0x%x\n", (int)fb_data->vcom_regulator);
- ret = -ENODEV;
- goto out_irq;
+ "err = 0x%x\n", fb_data->vcom_regulator);
+ goto out_dma_work_buf;
}
if (device_create_file(info->dev, &fb_attrs[0]))
@@ -2763,7 +2686,7 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
* Parameters should match FB format/width/height
*/
pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
- pxp_conf->s0_param.width = fb_data->info.var.xres_virtual;
+ pxp_conf->s0_param.width = fb_data->info.var.xres;
pxp_conf->s0_param.height = fb_data->info.var.yres;
pxp_conf->s0_param.color_key = -1;
pxp_conf->s0_param.color_key_enable = false;
@@ -2772,7 +2695,7 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
* Initialize OL0 channel parameters
* No overlay will be used for PxP operation
*/
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
pxp_conf->ol_param[i].combine_enable = false;
pxp_conf->ol_param[i].width = 0;
pxp_conf->ol_param[i].height = 0;
@@ -2816,54 +2739,33 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
fb_data->blank = FB_BLANK_UNBLANK;
fb_data->power_state = POWER_STATE_OFF;
fb_data->powering_down = false;
- fb_data->pwrdown_delay = 0;
/* Register FB */
ret = register_framebuffer(info);
if (ret) {
dev_err(&pdev->dev,
"register_framebuffer failed with error %d\n", ret);
- goto out_dmaengine;
+ goto out_irq;
}
#ifdef DEFAULT_PANEL_HW_INIT
ret = mxc_epdc_fb_init_hw((struct fb_info *)fb_data);
if (ret) {
- dev_err(&pdev->dev, "Failed to initialize HW!\n");
+ dev_err(&pdev->dev, "Failed to read firmware!\n");
+ goto out_dmaengine;
}
#endif
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
- /* If FB console included, update display to show logo */
- update.update_region.left = 0;
- update.update_region.width = info->var.xres;
- update.update_region.top = 0;
- update.update_region.height = info->var.yres;
- update.update_mode = UPDATE_MODE_PARTIAL;
- update.waveform_mode = WAVEFORM_MODE_AUTO;
- update.update_marker = INIT_UPDATE_MARKER;
- update.temp = TEMP_USE_AMBIENT;
- update.use_alt_buffer = false;
-
- mxc_epdc_fb_send_update(&update, info);
-
- ret = mxc_epdc_fb_wait_update_complete(update.update_marker, info);
- if (ret < 0)
- dev_err(fb_data->dev,
- "Wait for update complete failed. Error = 0x%x", ret);
-#endif
-
goto out;
out_dmaengine:
dmaengine_put();
+ unregister_framebuffer(&fb_data->info);
out_irq:
free_irq(fb_data->epdc_irq, fb_data);
out_dma_work_buf:
- dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size,
+ dma_free_writecombine(&pdev->dev, pentry->y_res * pentry->x_res / 2,
fb_data->working_buffer_virt, fb_data->working_buffer_phys);
- if (fb_data->pdata->put_pins)
- fb_data->pdata->put_pins();
out_upd_buffers:
list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list->list, list) {
list_del(&plist->list);
@@ -2898,29 +2800,19 @@ static int mxc_epdc_fb_remove(struct platform_device *pdev)
unregister_framebuffer(&fb_data->info);
free_irq(fb_data->epdc_irq, fb_data);
- dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size,
- fb_data->working_buffer_virt,
- fb_data->working_buffer_phys);
- if (fb_data->waveform_buffer_virt != NULL)
- dma_free_writecombine(&pdev->dev, fb_data->waveform_buffer_size,
- fb_data->waveform_buffer_virt,
- fb_data->waveform_buffer_phys);
+ dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size, fb_data->working_buffer_virt,
+ fb_data->working_buffer_phys);
+ dma_free_writecombine(&pdev->dev, fb_data->waveform_buffer_size, fb_data->waveform_buffer_virt,
+ fb_data->waveform_buffer_phys);
list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list->list, list) {
list_del(&plist->list);
dma_free_writecombine(&pdev->dev, plist->size, plist->virt_addr,
plist->phys_addr);
kfree(plist);
}
-#ifdef CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE
- fb_deferred_io_cleanup(&fb_data->info);
-#endif
-
dma_free_writecombine(&pdev->dev, fb_data->map_size, fb_data->info.screen_base,
fb_data->phys_start);
- if (fb_data->pdata->put_pins)
- fb_data->pdata->put_pins();
-
/* Release PxP-related resources */
if (fb_data->pxp_chan != NULL)
dma_release_channel(&fb_data->pxp_chan->dma_chan);
@@ -3011,6 +2903,8 @@ static int pxp_chan_init(struct mxc_epdc_fb_data *fb_data)
fb_data->pxp_chan = to_pxp_channel(chan);
+ dev_dbg(fb_data->dev, "dma_chan = 0x%x\n", fb_data->pxp_chan->dma_chan);
+
fb_data->pxp_chan->client = fb_data;
init_completion(&fb_data->pxp_tx_cmpl);
@@ -3024,8 +2918,7 @@ static int pxp_chan_init(struct mxc_epdc_fb_data *fb_data)
* Note: This is a blocking call, so upon return the PxP tx should be complete.
*/
static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
- struct mxcfb_rect *update_region,
- int x_start_offs)
+ struct mxcfb_rect *update_region)
{
dma_cookie_t cookie;
struct scatterlist *sg = fb_data->sg;
@@ -3035,7 +2928,6 @@ static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
int i, ret;
- int length;
dev_dbg(fb_data->dev, "Starting PxP Send Buffer\n");
@@ -3086,7 +2978,7 @@ static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
* probe() and should not need to be changed.
*/
proc_data->srect.top = update_region->top;
- proc_data->srect.left = update_region->left + x_start_offs;
+ proc_data->srect.left = update_region->left;
proc_data->srect.width = update_region->width;
proc_data->srect.height = update_region->height;
@@ -3108,7 +3000,7 @@ static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
pxp_conf->out_param.height = update_region->height;
desc = to_tx_desc(txd);
- length = desc->len;
+ int length = desc->len;
for (i = 0; i < length; i++) {
if (i == 0) {/* S0 */
memcpy(&desc->proc_data, proc_data, sizeof(struct pxp_proc_data));
diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c
index cc48e62637ca..be907a956365 100644
--- a/drivers/video/mxc/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc/mxc_ipuv3_fb.c
@@ -43,7 +43,6 @@
#include <linux/io.h>
#include <linux/ipu.h>
#include <linux/mxcfb.h>
-#include <linux/earlysuspend.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
@@ -101,10 +100,9 @@ enum {
BOTH_OFF
};
-#define FB_DEVICE_NUM 3
static bool g_dp_in_use;
LIST_HEAD(fb_alloc_list);
-static struct fb_info *mxcfb_info[FB_DEVICE_NUM];
+static struct fb_info *mxcfb_info[3];
static uint32_t bpp_to_pixfmt(struct fb_info *fbi)
{
@@ -172,11 +170,12 @@ static int _setup_disp_channel1(struct fb_info *fbi)
for (i = 0; i < num_registered_fb; i++) {
mxc_fbi_tmp = (struct mxcfb_info *)
- (registered_fb[i]->par);
+ (registered_fb[i]->par);
if (mxc_fbi_tmp->ipu_ch == MEM_BG_SYNC) {
- fbi->var.vmode = registered_fb[i]->var.vmode;
+ fbi->var.vmode =
+ registered_fb[i]->var.vmode;
mxc_fbi->ipu_di_pix_fmt =
- mxc_fbi_tmp->ipu_di_pix_fmt;
+ mxc_fbi_tmp->ipu_di_pix_fmt;
break;
}
}
@@ -233,7 +232,7 @@ static int _setup_disp_channel2(struct fb_info *fbi)
}
mxc_fbi->cur_ipu_buf = 1;
- sema_init(&mxc_fbi->flip_sem, 0);
+ sema_init(&mxc_fbi->flip_sem, 1);
if (mxc_fbi->alpha_chan_en) {
mxc_fbi->cur_ipu_alpha_buf = 1;
sema_init(&mxc_fbi->alpha_flip_sem, 1);
@@ -247,7 +246,8 @@ static int _setup_disp_channel2(struct fb_info *fbi)
IPU_ROTATE_NONE,
fbi->fix.smem_start +
(fbi->fix.line_length * fbi->var.yres),
- fbi->fix.smem_start, 0, 0);
+ fbi->fix.smem_start,
+ 0, 0);
if (retval) {
dev_err(fbi->device,
"ipu_init_channel_buffer error %d\n", retval);
@@ -317,36 +317,30 @@ static int mxcfb_set_par(struct fb_info *fbi)
mxc_fbi->alpha_phy_addr1);
mxc_fbi->alpha_virt_addr0 =
- dma_alloc_coherent(fbi->device,
- alpha_mem_len,
- &mxc_fbi->alpha_phy_addr0,
- GFP_DMA | GFP_KERNEL);
+ dma_alloc_coherent(fbi->device,
+ alpha_mem_len,
+ &mxc_fbi->alpha_phy_addr0,
+ GFP_DMA | GFP_KERNEL);
mxc_fbi->alpha_virt_addr1 =
- dma_alloc_coherent(fbi->device,
- alpha_mem_len,
- &mxc_fbi->alpha_phy_addr1,
- GFP_DMA | GFP_KERNEL);
+ dma_alloc_coherent(fbi->device,
+ alpha_mem_len,
+ &mxc_fbi->alpha_phy_addr1,
+ GFP_DMA | GFP_KERNEL);
if (mxc_fbi->alpha_virt_addr0 == NULL ||
mxc_fbi->alpha_virt_addr1 == NULL) {
dev_err(fbi->device, "mxcfb: dma alloc for"
" alpha buffer failed.\n");
if (mxc_fbi->alpha_virt_addr0)
dma_free_coherent(fbi->device,
- mxc_fbi->
- alpha_mem_len,
- mxc_fbi->
- alpha_virt_addr0,
- mxc_fbi->
- alpha_phy_addr0);
+ mxc_fbi->alpha_mem_len,
+ mxc_fbi->alpha_virt_addr0,
+ mxc_fbi->alpha_phy_addr0);
if (mxc_fbi->alpha_virt_addr1)
dma_free_coherent(fbi->device,
- mxc_fbi->
- alpha_mem_len,
- mxc_fbi->
- alpha_virt_addr1,
- mxc_fbi->
- alpha_phy_addr1);
+ mxc_fbi->alpha_mem_len,
+ mxc_fbi->alpha_virt_addr1,
+ mxc_fbi->alpha_phy_addr1);
return -ENOMEM;
}
mxc_fbi->alpha_mem_len = alpha_mem_len;
@@ -374,7 +368,7 @@ static int mxcfb_set_par(struct fb_info *fbi)
else
out_pixel_fmt = IPU_PIX_FMT_RGB666;
}
- if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
+ if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
sig_cfg.odd_field_first = true;
if ((fbi->var.sync & FB_SYNC_EXT) || mxc_fbi->ipu_ext_clk)
sig_cfg.ext_clk = true;
@@ -482,7 +476,8 @@ static int swap_channels(struct fb_info *fbi)
ch_to = MEM_BG_SYNC;
for (i = 0; i < num_registered_fb; i++) {
- mxc_fbi_to = (struct mxcfb_info *)mxcfb_info[i]->par;
+ mxc_fbi_to =
+ (struct mxcfb_info *)mxcfb_info[i]->par;
if (mxc_fbi_to->ipu_ch == ch_to) {
fbi_to = mxcfb_info[i];
break;
@@ -547,14 +542,14 @@ static int swap_channels(struct fb_info *fbi)
}
if (ipu_request_irq(mxc_fbi_from->ipu_ch_irq, mxcfb_irq_handler, 0,
- MXCFB_NAME, fbi) != 0) {
+ MXCFB_NAME, fbi) != 0) {
dev_err(fbi->device, "Error registering irq %d\n",
mxc_fbi_from->ipu_ch_irq);
return -EBUSY;
}
ipu_disable_irq(mxc_fbi_from->ipu_ch_irq);
if (ipu_request_irq(mxc_fbi_to->ipu_ch_irq, mxcfb_irq_handler, 0,
- MXCFB_NAME, fbi_to) != 0) {
+ MXCFB_NAME, fbi_to) != 0) {
dev_err(fbi_to->device, "Error registering irq %d\n",
mxc_fbi_to->ipu_ch_irq);
return -EBUSY;
@@ -577,35 +572,6 @@ static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
u32 vtotal;
u32 htotal;
- /* fg should not bigger than bg */
- if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
- struct fb_info *fbi_tmp;
- struct mxcfb_info *mxc_fbi_tmp;
- int i, bg_xres, bg_yres;
- int16_t pos_x, pos_y;
-
- bg_xres = var->xres;
- bg_yres = var->yres;
-
- for (i = 0; i < num_registered_fb; i++) {
- fbi_tmp = registered_fb[i];
- mxc_fbi_tmp = (struct mxcfb_info *)
- (fbi_tmp->par);
- if (mxc_fbi_tmp->ipu_ch == MEM_BG_SYNC) {
- bg_xres = fbi_tmp->var.xres;
- bg_yres = fbi_tmp->var.yres;
- break;
- }
- }
-
- ipu_disp_get_window_pos(mxc_fbi->ipu_ch, &pos_x, &pos_y);
-
- if ((var->xres + pos_x) > bg_xres)
- var->xres = bg_xres - pos_x;
- if ((var->yres + pos_y) > bg_yres)
- var->yres = bg_yres - pos_y;
- }
-
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
if (var->yres_virtual < var->yres)
@@ -782,7 +748,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
}
if (ipu_disp_set_global_alpha(mxc_fbi->ipu_ch,
- (bool) ga.enable,
+ (bool)ga.enable,
ga.alpha)) {
retval = -EINVAL;
break;
@@ -809,7 +775,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
}
if (ipu_disp_set_global_alpha(mxc_fbi->ipu_ch,
- !(bool) la.enable, 0)) {
+ !(bool)la.enable, 0)) {
retval = -EINVAL;
break;
}
@@ -824,11 +790,8 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
for (i = 0; i < num_registered_fb; i++) {
char *idstr = registered_fb[i]->fix.id;
- if (strcmp(idstr, video_plane_idstr) ==
- 0) {
- ((struct mxcfb_info
- *)(registered_fb[i]->par))->
- alpha_chan_en = false;
+ if (strcmp(idstr, video_plane_idstr) == 0) {
+ ((struct mxcfb_info *)(registered_fb[i]->par))->alpha_chan_en = false;
break;
}
}
@@ -856,8 +819,8 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
uint32_t ipu_alp_ch_irq;
if (!(((mxc_fbi->ipu_ch == MEM_FG_SYNC) ||
- (mxc_fbi->ipu_ch == MEM_BG_SYNC)) &&
- (mxc_fbi->alpha_chan_en))) {
+ (mxc_fbi->ipu_ch == MEM_BG_SYNC)) &&
+ (mxc_fbi->alpha_chan_en))) {
dev_err(fbi->device,
"Should use background or overlay "
"framebuffer to set the alpha buffer "
@@ -884,10 +847,11 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
down(&mxc_fbi->alpha_flip_sem);
mxc_fbi->cur_ipu_alpha_buf =
- !mxc_fbi->cur_ipu_alpha_buf;
+ !mxc_fbi->cur_ipu_alpha_buf;
if (ipu_update_channel_buffer(mxc_fbi->ipu_ch,
IPU_ALPHA_IN_BUFFER,
- mxc_fbi->cur_ipu_alpha_buf,
+ mxc_fbi->
+ cur_ipu_alpha_buf,
base) == 0) {
ipu_select_buffer(mxc_fbi->ipu_ch,
IPU_ALPHA_IN_BUFFER,
@@ -925,9 +889,9 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
break;
}
retval = ipu_disp_set_gamma_correction(mxc_fbi->ipu_ch,
- gamma.enable,
- gamma.constk,
- gamma.slopek);
+ gamma.enable,
+ gamma.constk,
+ gamma.slopek);
break;
}
case MXCFB_WAIT_FOR_VSYNC:
@@ -937,8 +901,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
int i;
for (i = 0; i < num_registered_fb; i++) {
bg_mxcfbi =
- ((struct mxcfb_info
- *)(registered_fb[i]->par));
+ ((struct mxcfb_info *)(registered_fb[i]->par));
if (bg_mxcfbi->ipu_ch == MEM_BG_SYNC)
break;
@@ -958,10 +921,8 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
ipu_clear_irq(mxc_fbi->ipu_ch_irq);
mxc_fbi->wait4vsync = 1;
ipu_enable_irq(mxc_fbi->ipu_ch_irq);
- retval =
- wait_for_completion_interruptible_timeout(&mxc_fbi->
- vsync_complete,
- 1 * HZ);
+ retval = wait_for_completion_interruptible_timeout(
+ &mxc_fbi->vsync_complete, 1 * HZ);
if (retval == 0) {
dev_err(fbi->device,
"MXCFB_WAIT_FOR_VSYNC: timeout %d\n",
@@ -971,7 +932,6 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
} else if (retval > 0) {
retval = 0;
}
-
break;
}
case FBIO_ALLOC:
@@ -1052,8 +1012,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
for (i = 0; i < num_registered_fb; i++) {
bg_mxcfbi =
- ((struct mxcfb_info *)(registered_fb[i]->
- par));
+ ((struct mxcfb_info *)(registered_fb[i]->par));
if (bg_mxcfbi->ipu_ch == MEM_BG_SYNC) {
bg_fbi = registered_fb[i];
@@ -1072,15 +1031,13 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
if (bg_fbi->var.xres < fbi->var.xres)
pos.x = 0;
else
- pos.x =
- bg_fbi->var.xres - fbi->var.xres;
+ pos.x = bg_fbi->var.xres - fbi->var.xres;
}
if (fbi->var.yres + pos.y > bg_fbi->var.yres) {
if (bg_fbi->var.yres < fbi->var.yres)
pos.y = 0;
else
- pos.y =
- bg_fbi->var.yres - fbi->var.yres;
+ pos.y = bg_fbi->var.yres - fbi->var.yres;
}
retval = ipu_disp_set_window_pos(mxc_fbi->ipu_ch,
@@ -1095,7 +1052,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
case MXCFB_GET_FB_IPU_CHAN:
{
struct mxcfb_info *mxc_fbi =
- (struct mxcfb_info *)fbi->par;
+ (struct mxcfb_info *)fbi->par;
if (put_user(mxc_fbi->ipu_ch, argp))
return -EFAULT;
@@ -1104,7 +1061,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
case MXCFB_GET_DIFMT:
{
struct mxcfb_info *mxc_fbi =
- (struct mxcfb_info *)fbi->par;
+ (struct mxcfb_info *)fbi->par;
if (put_user(mxc_fbi->ipu_di_pix_fmt, argp))
return -EFAULT;
@@ -1113,18 +1070,9 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
case MXCFB_GET_FB_IPU_DI:
{
struct mxcfb_info *mxc_fbi =
- (struct mxcfb_info *)fbi->par;
-
- if (put_user(mxc_fbi->ipu_di, argp))
- return -EFAULT;
- break;
- }
- case MXCFB_GET_FB_BLANK:
- {
- struct mxcfb_info *mxc_fbi =
(struct mxcfb_info *)fbi->par;
- if (put_user(mxc_fbi->cur_blank, argp))
+ if (put_user(mxc_fbi->ipu_di, argp))
return -EFAULT;
break;
}
@@ -1177,7 +1125,7 @@ static int
mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par,
- *mxc_graphic_fbi = NULL;
+ *mxc_graphic_fbi = NULL;
u_int y_bottom;
unsigned long base, active_alpha_phy_addr = 0;
bool loc_alpha_en = false;
@@ -1198,7 +1146,7 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
int j;
for (j = 0; j < num_registered_fb; j++) {
bg_mxcfbi =
- ((struct mxcfb_info *)(registered_fb[j]->par));
+ ((struct mxcfb_info *)(registered_fb[j]->par));
if (bg_mxcfbi->ipu_ch == MEM_BG_SYNC)
break;
@@ -1228,13 +1176,13 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
if ((strcmp(idstr, "DISP3 BG") == 0 ||
strcmp(idstr, "DISP3 FG") == 0) &&
((struct mxcfb_info *)
- (registered_fb[i]->par))->alpha_chan_en) {
+ (registered_fb[i]->par))->alpha_chan_en) {
loc_alpha_en = true;
mxc_graphic_fbi = (struct mxcfb_info *)
- (registered_fb[i]->par);
+ (registered_fb[i]->par);
active_alpha_phy_addr = mxc_fbi->cur_ipu_buf ?
- mxc_graphic_fbi->alpha_phy_addr1 :
- mxc_graphic_fbi->alpha_phy_addr0;
+ mxc_graphic_fbi->alpha_phy_addr1 :
+ mxc_graphic_fbi->alpha_phy_addr0;
dev_dbg(info->device, "Updating SDC graphic "
"buf %d address=0x%08lX\n",
mxc_fbi->cur_ipu_buf,
@@ -1244,7 +1192,7 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
}
}
- init_completion(&mxc_fbi->vsync_complete);
+ down(&mxc_fbi->flip_sem);
mxc_fbi->cur_ipu_buf = !mxc_fbi->cur_ipu_buf;
@@ -1278,7 +1226,6 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
return -EBUSY;
}
- down(&mxc_fbi->flip_sem);
dev_dbg(info->device, "Update complete\n");
info->var.xoffset = var->xoffset;
@@ -1312,9 +1259,9 @@ static int mxcfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
len = fbi->fix.smem_len - offset;
vma->vm_pgoff = (fbi->fix.smem_start + offset) >> PAGE_SHIFT;
} else if ((vma->vm_pgoff ==
- (mxc_fbi->alpha_phy_addr0 >> PAGE_SHIFT)) ||
+ (mxc_fbi->alpha_phy_addr0 >> PAGE_SHIFT)) ||
(vma->vm_pgoff ==
- (mxc_fbi->alpha_phy_addr1 >> PAGE_SHIFT))) {
+ (mxc_fbi->alpha_phy_addr1 >> PAGE_SHIFT))) {
len = mxc_fbi->alpha_mem_len;
} else {
list_for_each_entry(mem, &fb_alloc_list, list) {
@@ -1375,8 +1322,23 @@ static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id)
ipu_disable_irq(irq);
mxc_fbi->wait4vsync = 0;
} else {
- up(&mxc_fbi->flip_sem);
- ipu_disable_irq(irq);
+ if (!ipu_check_buffer_busy(mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, mxc_fbi->cur_ipu_buf)
+ || (mxc_fbi->waitcnt > 2)) {
+ /*
+ * This interrupt come after pan display select
+ * cur_ipu_buf buffer, this buffer should become
+ * idle after show. If it keep busy, clear it manually.
+ */
+ if (mxc_fbi->waitcnt > 2)
+ ipu_clear_buffer_ready(mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER,
+ mxc_fbi->cur_ipu_buf);
+ up(&mxc_fbi->flip_sem);
+ ipu_disable_irq(irq);
+ mxc_fbi->waitcnt = 0;
+ } else
+ mxc_fbi->waitcnt++;
}
return IRQ_HANDLED;
}
@@ -1394,10 +1356,14 @@ static irqreturn_t mxcfb_alpha_irq_handler(int irq, void *dev_id)
/*
* Suspends the framebuffer and blanks the screen. Power management support
*/
-static void mxcfb_suspend_one(struct fb_info *fbi)
+static int mxcfb_suspend(struct platform_device *pdev, pm_message_t state)
{
+ struct fb_info *fbi = platform_get_drvdata(pdev);
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
int saved_blank;
+#ifdef CONFIG_FB_MXC_LOW_PWR_DISPLAY
+ void *fbmem;
+#endif
acquire_console_sem();
fb_set_suspend(fbi, 1);
@@ -1405,44 +1371,26 @@ static void mxcfb_suspend_one(struct fb_info *fbi)
mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
mxc_fbi->next_blank = saved_blank;
release_console_sem();
+
+ return 0;
}
/*
* Resumes the framebuffer and unblanks the screen. Power management support
*/
-static void mxcfb_resume_one(struct fb_info *fbi)
+static int mxcfb_resume(struct platform_device *pdev)
{
+ struct fb_info *fbi = platform_get_drvdata(pdev);
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
acquire_console_sem();
mxcfb_blank(mxc_fbi->next_blank, fbi);
fb_set_suspend(fbi, 0);
release_console_sem();
-}
-
-#ifndef CONFIG_HAS_EARLYSUSPEND
-
-static int mxcfb_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct fb_info *fbi = platform_get_drvdata(pdev);
-
- if (fbi && (strcmp(fbi->fix.id, "DISP3 FG") == 0))
- mxcfb_suspend_one(fbi);
return 0;
}
-static int mxcfb_resume(struct platform_device *pdev)
-{
- struct fb_info *fbi = platform_get_drvdata(pdev);
-
- if (fbi && (strcmp(fbi->fix.id, "DISP3 FG") == 0))
- mxcfb_resume_one(fbi);
-
- return 0;
-}
-#endif
-
/*
* Main framebuffer functions
*/
@@ -1461,12 +1409,12 @@ static int mxcfb_map_video_memory(struct fb_info *fbi)
{
if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
fbi->fix.smem_len = fbi->var.yres_virtual *
- fbi->fix.line_length;
+ fbi->fix.line_length;
fbi->screen_base = dma_alloc_writecombine(fbi->device,
- fbi->fix.smem_len,
- (dma_addr_t *) & fbi->fix.
- smem_start, GFP_DMA);
+ fbi->fix.smem_len,
+ (dma_addr_t *)&fbi->fix.smem_start,
+ GFP_DMA);
if (fbi->screen_base == 0) {
dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
fbi->fix.smem_len = 0;
@@ -1572,13 +1520,15 @@ static ssize_t swap_disp_chan(struct device *dev,
int i;
for (i = 0; i < num_registered_fb; i++) {
- fg_mxcfbi = (struct mxcfb_info *)mxcfb_info[i]->par;
+ fg_mxcfbi =
+ (struct mxcfb_info *)mxcfb_info[i]->par;
if (fg_mxcfbi->ipu_ch == MEM_FG_SYNC)
break;
else
fg_mxcfbi = NULL;
}
- if (!fg_mxcfbi || fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
+ if (!fg_mxcfbi ||
+ fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
dev_err(dev,
"Can not switch while fb2(fb-fg) is on.\n");
release_console_sem();
@@ -1592,7 +1542,6 @@ static ssize_t swap_disp_chan(struct device *dev,
release_console_sem();
return count;
}
-
DEVICE_ATTR(fsl_disp_property, 644, show_disp_chan, swap_disp_chan);
/*!
@@ -1652,7 +1601,7 @@ static int mxcfb_probe(struct platform_device *pdev)
mxcfb_alpha_irq_handler, 0,
MXCFB_NAME, fbi) != 0) {
dev_err(&pdev->dev, "Error registering BG "
- "alpha irq handler.\n");
+ "alpha irq handler.\n");
ret = -EBUSY;
goto err1;
}
@@ -1665,7 +1614,7 @@ static int mxcfb_probe(struct platform_device *pdev)
mxcfb_alpha_irq_handler, 0,
MXCFB_NAME, fbi) != 0) {
dev_err(&pdev->dev, "Error registering BG "
- "alpha irq handler.\n");
+ "alpha irq handler.\n");
ret = -EBUSY;
goto err1;
}
@@ -1683,7 +1632,7 @@ static int mxcfb_probe(struct platform_device *pdev)
mxcfb_alpha_irq_handler, 0,
MXCFB_NAME, fbi) != 0) {
dev_err(&pdev->dev, "Error registering FG alpha irq "
- "handler.\n");
+ "handler.\n");
ret = -EBUSY;
goto err1;
}
@@ -1703,8 +1652,7 @@ static int mxcfb_probe(struct platform_device *pdev)
if (res && res->end) {
fbi->fix.smem_len = res->end - res->start + 1;
fbi->fix.smem_start = res->start;
- fbi->screen_base =
- ioremap(fbi->fix.smem_start, fbi->fix.smem_len);
+ fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len);
}
/* Need dummy values until real panel is configured */
@@ -1729,21 +1677,15 @@ static int mxcfb_probe(struct platform_device *pdev)
mxcfbi->fb_mode_str = plat_data->mode_str;
if (mxcfbi->fb_mode_str) {
-
#ifdef CONFIG_MODULE_CCXMX51
if ((mstr = strstr(mxcfbi->fb_mode_str, "VGA@")) != NULL)
mxcfbi->fb_mode_str = mstr + 4;
#endif
-
- ret =
- fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, NULL, 0,
- NULL, mxcfbi->default_bpp);
- if ((!ret || (ret > 2)) && plat_data && plat_data->mode
- && plat_data->num_modes)
- fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str,
- plat_data->mode, plat_data->num_modes,
- NULL, mxcfbi->default_bpp);
-
+ ret = fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, NULL, 0, NULL,
+ mxcfbi->default_bpp);
+ if ((!ret || (ret > 2)) && plat_data && plat_data->mode && plat_data->num_modes)
+ fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, plat_data->mode,
+ plat_data->num_modes, NULL, mxcfbi->default_bpp);
#ifdef CONFIG_MODULE_CCXMX51
/* This improves the VGA modes on the CCWi-i.MX51 */
if (mstr != NULL) {
@@ -1758,8 +1700,7 @@ static int mxcfb_probe(struct platform_device *pdev)
pm_set_vt_switch(vt_switch);
/* Default Y virtual size is 2x panel size */
- fbi->var.yres_virtual = ((fbi->var.yres + 127) & ~127) * 2;
- fbi->var.xres_virtual = (fbi->var.xres + 31) & ~31;
+ fbi->var.yres_virtual = fbi->var.yres * 3;
mxcfb_set_fix(fbi);
@@ -1780,12 +1721,12 @@ static int mxcfb_probe(struct platform_device *pdev)
return 0;
- err2:
+err2:
ipu_free_irq(mxcfbi->ipu_ch_irq, fbi);
- err1:
+err1:
fb_dealloc_cmap(&fbi->cmap);
framebuffer_release(fbi);
- err0:
+err0:
return ret;
}
@@ -1818,10 +1759,8 @@ static struct platform_driver mxcfb_driver = {
},
.probe = mxcfb_probe,
.remove = mxcfb_remove,
-#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = mxcfb_suspend,
.resume = mxcfb_resume,
-#endif
};
/*
@@ -1886,7 +1825,8 @@ static int mxcfb_option_setup(struct fb_info *info, char *options)
continue;
}
if (!strncmp(opt, "bpp=", 4))
- mxcfbi->default_bpp = simple_strtoul(opt + 4, NULL, 0);
+ mxcfbi->default_bpp =
+ simple_strtoul(opt + 4, NULL, 0);
else
mxcfbi->fb_mode_str = opt;
}
@@ -1894,32 +1834,6 @@ static int mxcfb_option_setup(struct fb_info *info, char *options)
return 0;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mxcfb_early_suspend(struct early_suspend *h)
-{
- int i;
- for (i = FB_DEVICE_NUM - 1; i >= 0; i--) {
- if (mxcfb_info[i])
- mxcfb_suspend_one(mxcfb_info[i]);
- }
-}
-
-static void mxcfb_later_resume(struct early_suspend *h)
-{
- int i;
- for (i = 0; i < FB_DEVICE_NUM; i++) {
- if (mxcfb_info[i])
- mxcfb_resume_one(mxcfb_info[i]);
- }
-}
-
-struct early_suspend fbdrv_earlysuspend = {
- .level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
- .suspend = mxcfb_early_suspend,
- .resume = mxcfb_later_resume,
-};
-#endif
-
/*!
* Main entry function for the framebuffer. The function registers the power
* management callback functions with the kernel and also registers the MXCFB
@@ -1929,17 +1843,11 @@ struct early_suspend fbdrv_earlysuspend = {
*/
int __init mxcfb_init(void)
{
- int ret;
-
- ret = platform_driver_register(&mxcfb_driver);
- if (!ret)
- register_early_suspend(&fbdrv_earlysuspend);
- return ret;
+ return platform_driver_register(&mxcfb_driver);
}
void mxcfb_exit(void)
{
- unregister_early_suspend(&fbdrv_earlysuspend);
platform_driver_unregister(&mxcfb_driver);
}
diff --git a/drivers/video/mxc/tve.c b/drivers/video/mxc/tve.c
index 793b470cdce4..b1982f868e8c 100644
--- a/drivers/video/mxc/tve.c
+++ b/drivers/video/mxc/tve.c
@@ -513,9 +513,12 @@ static irqreturn_t tve_detect_handler(int irq, void *data)
/* Re-construct clk for tve display */
static inline void tve_recfg_fb(struct fb_info *fbi)
{
+ struct fb_var_screeninfo var;
+
+ memset(&var, 0, sizeof(var));
+ fb_videomode_to_var(&var, fbi->mode);
fbi->flags &= ~FBINFO_MISC_USEREVENT;
- fbi->var.activate |= FB_ACTIVATE_FORCE;
- fb_set_var(fbi, &fbi->var);
+ fb_set_var(fbi, &var);
}
int tve_fb_event(struct notifier_block *nb, unsigned long val, void *v)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 5a72083dc67c..adf9632c6b1f 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1036,7 +1036,7 @@ static int s3c_fb_resume(struct platform_device *pdev)
static struct platform_driver s3c_fb_driver = {
.probe = s3c_fb_probe,
- .remove = s3c_fb_remove,
+ .remove = __devexit_p(s3c_fb_remove),
.suspend = s3c_fb_suspend,
.resume = s3c_fb_resume,
.driver = {
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index 705c85360526..bef4aae388d0 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -342,7 +342,7 @@ struct SiS_Private
unsigned short SiS_RY4COE;
unsigned short SiS_LCDHDES;
unsigned short SiS_LCDVDES;
- unsigned short SiS_DDC_Port;
+ SISIOADDRESS SiS_DDC_Port;
unsigned short SiS_DDC_Index;
unsigned short SiS_DDC_Data;
unsigned short SiS_DDC_NData;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index ca5b4643a401..e35232a18571 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -67,12 +67,14 @@ static DEFINE_MUTEX(uvfb_lock);
* find the kernel part of the task struct, copy the registers and
* the buffer contents and then complete the task.
*/
-static void uvesafb_cn_callback(void *data)
+static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
- struct cn_msg *msg = data;
struct uvesafb_task *utask;
struct uvesafb_ktask *task;
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+ return;
+
if (msg->seq >= UVESAFB_TASKS_MAX)
return;
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index a882f2606515..0ffff9ed4eb0 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -281,6 +281,9 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
return NULL;
}
+ /* Only get used array entries after they have been exposed by host. */
+ rmb();
+
i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id;
*len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len;
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index fdf72851c574..45c126fea31d 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -306,9 +306,8 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
return error;
}
-static void w1_cn_callback(void *data)
+static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
- struct cn_msg *msg = data;
struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
struct w1_netlink_cmd *cmd;
struct w1_slave *sl;
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 1e8f02f440e6..d3c824dc2358 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -206,7 +206,7 @@ static int __devinit riowd_probe(struct of_device *op,
dev_set_drvdata(&op->dev, p);
riowd_device = p;
- err = 0;
+ return 0;
out_iounmap:
of_iounmap(&op->resource[0], p->regs, 2);
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index ec2a39b1e26f..7c284342f30f 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,6 +1,9 @@
obj-y += grant-table.o features.o events.o manage.o
obj-y += xenbus/
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_features.o := $(nostackp)
+
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += balloon.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index f5bbd9e83416..1b7123eb5d7b 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -96,11 +96,7 @@ static struct balloon_stats balloon_stats;
/* We increase/decrease in batches which fit in a page */
static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
-/* VM /proc information for memory */
-extern unsigned long totalram_pages;
-
#ifdef CONFIG_HIGHMEM
-extern unsigned long totalhigh_pages;
#define inc_totalhigh_pages() (totalhigh_pages++)
#define dec_totalhigh_pages() (totalhigh_pages--)
#else