summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpi_pad.c36
-rw-r--r--drivers/acpi/acpica/acconfig.h4
-rw-r--r--drivers/acpi/acpica/acevents.h4
-rw-r--r--drivers/acpi/acpica/acglobal.h8
-rw-r--r--drivers/acpi/acpica/achware.h6
-rw-r--r--drivers/acpi/acpica/evgpe.c115
-rw-r--r--drivers/acpi/acpica/evgpeblk.c14
-rw-r--r--drivers/acpi/acpica/evxface.c7
-rw-r--r--drivers/acpi/acpica/evxfevnt.c78
-rw-r--r--drivers/acpi/acpica/exsystem.c8
-rw-r--r--drivers/acpi/acpica/hwgpe.c94
-rw-r--r--drivers/acpi/acpica/hwvalid.c12
-rw-r--r--drivers/acpi/acpica/nsinit.c9
-rw-r--r--drivers/acpi/apei/apei-base.c1
-rw-r--r--drivers/acpi/apei/erst.c2
-rw-r--r--drivers/acpi/atomicio.c1
-rw-r--r--drivers/acpi/battery.c8
-rw-r--r--drivers/acpi/blacklist.c10
-rw-r--r--drivers/acpi/button.c4
-rw-r--r--drivers/acpi/fan.c3
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_driver.c5
-rw-r--r--drivers/acpi/processor_idle.c10
-rw-r--r--drivers/acpi/sleep.c63
-rw-r--r--drivers/acpi/system.c6
-rw-r--r--drivers/acpi/wakeup.c20
-rw-r--r--drivers/amba/bus.c88
-rw-r--r--drivers/ata/ahci.c10
-rw-r--r--drivers/ata/ata_generic.c30
-rw-r--r--drivers/ata/libahci.c5
-rw-r--r--drivers/base/core.c2
-rw-r--r--drivers/block/cciss_scsi.c1
-rw-r--r--drivers/block/cpqarray.c6
-rw-r--r--drivers/block/drbd/drbd_main.c2
-rw-r--r--drivers/block/drbd/drbd_nl.c6
-rw-r--r--drivers/bluetooth/bluecard_cs.c2
-rw-r--r--drivers/bluetooth/hci_bcsp.c2
-rw-r--r--drivers/char/agp/generic.c6
-rw-r--r--drivers/char/agp/intel-gtt.c13
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c23
-rw-r--r--drivers/char/sysrq.c10
-rw-r--r--drivers/char/tpm/tpm.h1
-rw-r--r--drivers/char/tpm/tpm_tis.c9
-rw-r--r--drivers/clocksource/cs5535-clockevt.c2
-rw-r--r--drivers/clocksource/sh_cmt.c2
-rw-r--r--drivers/cpufreq/cpufreq.c12
-rw-r--r--drivers/cpuidle/governors/menu.c4
-rw-r--r--drivers/crypto/talitos.c6
-rw-r--r--drivers/dma/ppc4xx/adma.c4
-rw-r--r--drivers/edac/Kconfig2
-rw-r--r--drivers/edac/amd64_edac.c24
-rw-r--r--drivers/edac/i7core_edac.c55
-rw-r--r--drivers/edac/mpc85xx_edac.c4
-rw-r--r--drivers/gpio/Kconfig2
-rw-r--r--drivers/gpio/Makefile6
-rw-r--r--drivers/gpio/cs5535-gpio.c2
-rw-r--r--drivers/gpio/gpiolib.c7
-rw-r--r--drivers/gpio/pl061.c4
-rw-r--r--drivers/gpu/drm/drm_edid.c4
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c42
-rw-r--r--drivers/gpu/drm/i915/dvo_tfp410.c2
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c5
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c10
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h8
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c18
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c76
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h70
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c6
-rw-r--r--drivers/gpu/drm/i915/intel_display.c169
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c80
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c4
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c27
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c33
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c3
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c2
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c35
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c6
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h3
-rw-r--r--drivers/gpu/drm/radeon/r100.c84
-rw-r--r--drivers/gpu/drm/radeon/r200.c5
-rw-r--r--drivers/gpu/drm/radeon/r300.c8
-rw-r--r--drivers/gpu/drm/radeon/r520.c1
-rw-r--r--drivers/gpu/drm/radeon/r600.c18
-rw-r--r--drivers/gpu/drm/radeon/r600_blit.c5
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon.h5
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c20
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c57
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c27
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c15
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c23
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_tv.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c42
-rw-r--r--drivers/gpu/drm/radeon/reg_srcs/evergreen10
-rw-r--r--drivers/gpu/drm/radeon/rs400.c5
-rw-r--r--drivers/gpu/drm/radeon/rs600.c1
-rw-r--r--drivers/gpu/drm/radeon/rs690.c42
-rw-r--r--drivers/gpu/drm/radeon/rv515.c1
-rw-r--r--drivers/gpu/drm/radeon/rv770.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c76
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c1
-rw-r--r--drivers/hid/Kconfig1
-rw-r--r--drivers/hid/hid-core.c21
-rw-r--r--drivers/hid/hid-debug.c2
-rw-r--r--drivers/hid/hid-ids.h21
-rw-r--r--drivers/hid/hid-ntrig.c36
-rw-r--r--drivers/hid/usbhid/hid-core.c13
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--drivers/hwmon/coretemp.c32
-rw-r--r--drivers/hwmon/i5k_amb.c6
-rw-r--r--drivers/hwmon/it87.c22
-rw-r--r--drivers/hwmon/k10temp.c14
-rw-r--r--drivers/hwmon/k8temp.c12
-rw-r--r--drivers/i2c/busses/i2c-i801.c8
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c4
-rw-r--r--drivers/i2c/i2c-core.c7
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c12
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c31
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h2
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c4
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c12
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h6
-rw-r--r--drivers/infiniband/hw/qib/Makefile2
-rw-r--r--drivers/infiniband/hw/qib/qib.h1
-rw-r--r--drivers/infiniband/hw/qib/qib_7220.h7
-rw-r--r--drivers/infiniband/hw/qib/qib_7322_regs.h48
-rw-r--r--drivers/infiniband/hw/qib/qib_diag.c19
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c3
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c43
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c21
-rw-r--r--drivers/infiniband/hw/qib/qib_pcie.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_sd7220.c56
-rw-r--r--drivers/infiniband/hw/qib/qib_sd7220_img.c1081
-rw-r--r--drivers/infiniband/hw/qib/qib_tx.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c4
-rw-r--r--drivers/input/joystick/gamecon.c5
-rw-r--r--drivers/input/keyboard/Kconfig4
-rw-r--r--drivers/input/keyboard/twl4030_keypad.c17
-rw-r--r--drivers/input/keyboard/w90p910_keypad.c2
-rw-r--r--drivers/input/misc/pcf8574_keypad.c2
-rw-r--r--drivers/input/mouse/Kconfig2
-rw-r--r--drivers/input/mouse/synaptics.c8
-rw-r--r--drivers/input/mouse/synaptics.h3
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h17
-rw-r--r--drivers/input/tablet/wacom_wac.c9
-rw-r--r--drivers/input/touchscreen/ad7877.c7
-rw-r--r--drivers/input/touchscreen/w90p910_ts.c2
-rw-r--r--drivers/isdn/gigaset/asyncdata.c44
-rw-r--r--drivers/isdn/gigaset/capi.c405
-rw-r--r--drivers/isdn/gigaset/common.c36
-rw-r--r--drivers/isdn/gigaset/ev-layer.c4
-rw-r--r--drivers/isdn/gigaset/gigaset.h38
-rw-r--r--drivers/isdn/gigaset/i4l.c21
-rw-r--r--drivers/isdn/gigaset/isocdata.c72
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c3
-rw-r--r--drivers/leds/Kconfig9
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-ns2.c338
-rw-r--r--drivers/md/md.c38
-rw-r--r--drivers/md/md.h3
-rw-r--r--drivers/md/raid0.c21
-rw-r--r--drivers/md/raid0.h3
-rw-r--r--drivers/md/raid10.c46
-rw-r--r--drivers/md/raid10.h5
-rw-r--r--drivers/md/raid5.c150
-rw-r--r--drivers/media/common/tuners/tuner-simple.c1
-rw-r--r--drivers/media/common/tuners/tuner-types.c16
-rw-r--r--drivers/media/video/Kconfig13
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c3
-rw-r--r--drivers/media/video/mem2mem_testdev.c3
-rw-r--r--drivers/media/video/mx2_camera.c1513
-rw-r--r--drivers/media/video/omap/Kconfig4
-rw-r--r--drivers/media/video/omap/Makefile4
-rw-r--r--drivers/media/video/omap/omap_vout.c81
-rw-r--r--drivers/media/video/tveeprom.c15
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c4
-rw-r--r--drivers/misc/Kconfig10
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/arm-charlcd.c396
-rw-r--r--drivers/misc/cs5535-mfgpt.c2
-rw-r--r--drivers/mmc/host/mmci.c156
-rw-r--r--drivers/mmc/host/mmci.h39
-rw-r--r--drivers/mmc/host/mxcmmc.c48
-rw-r--r--drivers/mmc/host/sdhci-s3c.c20
-rw-r--r--drivers/mtd/nand/mxc_nand.c33
-rw-r--r--drivers/mtd/ubi/build.c3
-rw-r--r--drivers/mtd/ubi/eba.c49
-rw-r--r--drivers/mtd/ubi/io.c60
-rw-r--r--drivers/mtd/ubi/scan.c131
-rw-r--r--drivers/mtd/ubi/scan.h19
-rw-r--r--drivers/mtd/ubi/ubi.h10
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/bnx2.c11
-rw-r--r--drivers/net/bnx2x.h4
-rw-r--r--drivers/net/bnx2x_main.c42
-rw-r--r--drivers/net/bonding/bond_alb.c5
-rw-r--r--drivers/net/bonding/bond_main.c33
-rw-r--r--drivers/net/cnic.c55
-rw-r--r--drivers/net/cpmac.c3
-rw-r--r--drivers/net/declance.c6
-rw-r--r--drivers/net/e1000/e1000_main.c17
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c9
-rw-r--r--drivers/net/enic/vnic_dev.c2
-rw-r--r--drivers/net/gianfar.c25
-rw-r--r--drivers/net/ibmveth.c4
-rw-r--r--drivers/net/igb/igb_main.c9
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c37
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c30
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.c2
-rw-r--r--drivers/net/lib82596.c2
-rw-r--r--drivers/net/ll_temac_main.c18
-rw-r--r--drivers/net/macvlan.c10
-rw-r--r--drivers/net/macvtap.c18
-rw-r--r--drivers/net/mipsnet.c2
-rw-r--r--drivers/net/mv643xx_eth.c9
-rw-r--r--drivers/net/ne.c4
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c3
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c4
-rw-r--r--drivers/net/netxen/netxen_nic_init.c13
-rw-r--r--drivers/net/pcmcia/axnet_cs.c7
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c1
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c18
-rw-r--r--drivers/net/phy/lxt.c1
-rw-r--r--drivers/net/phy/marvell.c38
-rw-r--r--drivers/net/qlge/qlge_main.c11
-rw-r--r--drivers/net/r8169.c2
-rw-r--r--drivers/net/s2io.c101
-rw-r--r--drivers/net/s2io.h6
-rw-r--r--drivers/net/sb1250-mac.c1
-rw-r--r--drivers/net/sky2.c19
-rw-r--r--drivers/net/tulip/de2104x.c5
-rw-r--r--drivers/net/tun.c14
-rw-r--r--drivers/net/ucc_geth.c2
-rw-r--r--drivers/net/usb/hso.c1
-rw-r--r--drivers/net/usb/rndis_host.c18
-rw-r--r--drivers/net/usb/usbnet.c5
-rw-r--r--drivers/net/virtio_net.c28
-rw-r--r--drivers/net/vxge/vxge-main.c33
-rw-r--r--drivers/net/wimax/i2400m/i2400m-usb.h1
-rw-r--r--drivers/net/wimax/i2400m/usb.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c15
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c13
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c9
-rw-r--r--drivers/net/wireless/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/p54/p54pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c10
-rw-r--r--drivers/parisc/led.c6
-rw-r--r--drivers/pci/intel-iommu.c14
-rw-r--r--drivers/pci/pci.c1
-rw-r--r--drivers/pci/pcie/pme/pcie_pme.c19
-rw-r--r--drivers/pci/setup-res.c32
-rw-r--r--drivers/pcmcia/ds.c3
-rw-r--r--drivers/pcmcia/pcmcia_resource.c4
-rw-r--r--drivers/pcmcia/pxa2xx_base.c5
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c12
-rw-r--r--drivers/power/ds2782_battery.c31
-rw-r--r--drivers/power/z2_battery.c12
-rw-r--r--drivers/regulator/ab3100.c4
-rw-r--r--drivers/regulator/tps6507x-regulator.c36
-rw-r--r--drivers/regulator/wm8350-regulator.c2
-rw-r--r--drivers/rtc/rtc-davinci.c1
-rw-r--r--drivers/rtc/rtc-ds1307.c4
-rw-r--r--drivers/rtc/rtc-pl031.c2
-rw-r--r--drivers/rtc/rtc-rx8581.c20
-rw-r--r--drivers/s390/block/dasd_devmap.c4
-rw-r--r--drivers/s390/cio/chsc.c2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c8
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c10
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c10
-rw-r--r--drivers/sbus/char/openprom.c4
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c13
-rw-r--r--drivers/scsi/ipr.c51
-rw-r--r--drivers/scsi/ipr.h5
-rw-r--r--drivers/serial/amba-pl010.c2
-rw-r--r--drivers/serial/amba-pl011.c90
-rw-r--r--drivers/serial/atmel_serial.c1
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c143
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/serial/suncore.c4
-rw-r--r--drivers/serial/sunsu.c13
-rw-r--r--drivers/spi/spi_mpc8xxx.c22
-rw-r--r--drivers/staging/batman-adv/bat_sysfs.c24
-rw-r--r--drivers/staging/batman-adv/device.c2
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c9
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c3
-rw-r--r--drivers/staging/hv/channel_mgmt.c41
-rw-r--r--drivers/staging/hv/hv_utils.c28
-rw-r--r--drivers/staging/hv/vmbus.h2
-rw-r--r--drivers/staging/hv/vmbus_drv.c3
-rw-r--r--drivers/staging/mrst-touchscreen/intel-mid-touch.c2
-rw-r--r--drivers/staging/rt2860/usb_main_dev.c1
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c2
-rw-r--r--drivers/staging/rtl8192su/r8192U_core.c43
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c2
-rw-r--r--drivers/staging/tm6000/tm6000-alsa.c1
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c1
-rw-r--r--drivers/staging/tm6000/tm6000-core.c1
-rw-r--r--drivers/staging/tm6000/tm6000-dvb.c1
-rw-r--r--drivers/staging/usbip/usbip_common.c46
-rw-r--r--drivers/staging/wlags49_h2/wl_enc.c1
-rw-r--r--drivers/staging/wlags49_h2/wl_sysfs.h4
-rw-r--r--drivers/usb/class/cdc-acm.c1
-rw-r--r--drivers/usb/core/driver.c13
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/message.c7
-rw-r--r--drivers/usb/core/quirks.c7
-rw-r--r--drivers/usb/gadget/at91_udc.c205
-rw-r--r--drivers/usb/gadget/at91_udc.h3
-rw-r--r--drivers/usb/gadget/f_eem.c3
-rw-r--r--drivers/usb/gadget/f_fs.c2
-rw-r--r--drivers/usb/gadget/f_mass_storage.c194
-rw-r--r--drivers/usb/gadget/f_uvc.c4
-rw-r--r--drivers/usb/gadget/fsl_mxc_udc.c2
-rw-r--r--drivers/usb/gadget/g_ffs.c11
-rw-r--r--drivers/usb/gadget/printer.c32
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c2
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c10
-rw-r--r--drivers/usb/gadget/u_serial.c16
-rw-r--r--drivers/usb/gadget/uvc.h10
-rw-r--r--drivers/usb/gadget/uvc_queue.c153
-rw-r--r--drivers/usb/gadget/uvc_queue.h20
-rw-r--r--drivers/usb/gadget/uvc_v4l2.c2
-rw-r--r--drivers/usb/gadget/uvc_video.c6
-rw-r--r--drivers/usb/gadget/webcam.c4
-rw-r--r--drivers/usb/host/ehci-mxc.c15
-rw-r--r--drivers/usb/host/isp1362-hcd.c15
-rw-r--r--drivers/usb/host/ohci-pxa27x.c2
-rw-r--r--drivers/usb/host/r8a66597-hcd.c2
-rw-r--r--drivers/usb/host/xhci-mem.c26
-rw-r--r--drivers/usb/host/xhci-ring.c73
-rw-r--r--drivers/usb/host/xhci.c2
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c5
-rw-r--r--drivers/usb/musb/musb_core.c13
-rw-r--r--drivers/usb/musb/musb_core.h6
-rw-r--r--drivers/usb/musb/musbhsdma.c13
-rw-r--r--drivers/usb/musb/tusb6010.c13
-rw-r--r--drivers/usb/otg/ulpi.c17
-rw-r--r--drivers/usb/serial/ftdi_sio.c10
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h22
-rw-r--r--drivers/usb/serial/option.c4
-rw-r--r--drivers/usb/serial/qcserial.c5
-rw-r--r--drivers/usb/serial/sierra.c1
-rw-r--r--drivers/usb/storage/transport.c4
-rw-r--r--drivers/vhost/net.c25
-rw-r--r--drivers/vhost/vhost.c86
-rw-r--r--drivers/vhost/vhost.h8
-rw-r--r--drivers/video/aty/radeon_pm.c2
-rw-r--r--drivers/video/au1100fb.c6
-rw-r--r--drivers/video/cyber2000fb.c3
-rw-r--r--drivers/video/gbefb.c16
-rw-r--r--drivers/video/geode/gxfb_core.c20
-rw-r--r--drivers/video/geode/lxfb_core.c18
-rw-r--r--drivers/video/imxfb.c72
-rw-r--r--drivers/video/nuc900fb.c2
-rw-r--r--drivers/video/omap/lcdc.c14
-rw-r--r--drivers/video/omap/rfbi.c5
-rw-r--r--drivers/video/omap2/vram.c33
-rw-r--r--drivers/video/pmag-ba-fb.c6
-rw-r--r--drivers/video/pmagb-b-fb.c12
-rw-r--r--drivers/virtio/virtio_pci.c3
-rw-r--r--drivers/virtio/virtio_ring.c7
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c16
-rw-r--r--drivers/watchdog/imx2_wdt.c1
388 files changed, 6874 insertions, 3550 deletions
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index d269a8f3329c..446aced33aff 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax;
static unsigned char tsc_detected_unstable;
static unsigned char tsc_marked_unstable;
+static unsigned char lapic_detected_unstable;
+static unsigned char lapic_marked_unstable;
static void power_saving_mwait_init(void)
{
@@ -75,9 +77,6 @@ static void power_saving_mwait_init(void)
power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
(highest_subcstate - 1);
- for_each_online_cpu(i)
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
-
#if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
@@ -86,13 +85,15 @@ static void power_saving_mwait_init(void)
* AMD Fam10h TSC will tick in all
* C/P/S0/S1 states when this bit is set.
*/
- if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
- return;
-
- /*FALL THROUGH*/
+ if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ tsc_detected_unstable = 1;
+ if (!boot_cpu_has(X86_FEATURE_ARAT))
+ lapic_detected_unstable = 1;
+ break;
default:
- /* TSC could halt in idle */
+ /* TSC & LAPIC could halt in idle */
tsc_detected_unstable = 1;
+ lapic_detected_unstable = 1;
}
#endif
}
@@ -180,10 +181,20 @@ static int power_saving_thread(void *data)
mark_tsc_unstable("TSC halts in idle");
tsc_marked_unstable = 1;
}
+ if (lapic_detected_unstable && !lapic_marked_unstable) {
+ int i;
+ /* LAPIC could halt in idle, so notify users */
+ for_each_online_cpu(i)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_ON,
+ &i);
+ lapic_marked_unstable = 1;
+ }
local_irq_disable();
cpu = smp_processor_id();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
- &cpu);
+ if (lapic_marked_unstable)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
stop_critical_timings();
__monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -192,8 +203,9 @@ static int power_saving_thread(void *data)
__mwait(power_saving_mwait_eax, 1);
start_critical_timings();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
- &cpu);
+ if (lapic_marked_unstable)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
local_irq_enable();
if (jiffies > expire_time) {
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h
index 33181ad350d5..b17d8de9f6ff 100644
--- a/drivers/acpi/acpica/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -119,6 +119,10 @@
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
+/* Maximum sleep allowed via Sleep() operator */
+
+#define ACPI_MAX_SLEEP 20000 /* Two seconds */
+
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 64d1e5c2d4ae..c3f43daa8be3 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -80,10 +80,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 9070f1fe8f17..899d68afc3c5 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -125,6 +125,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
*/
u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
+/*
+ * Optionally truncate I/O addresses to 16 bits. Provides compatibility
+ * with other ACPI implementations. NOTE: During ACPICA initialization,
+ * this value is set to TRUE if any Windows OSI strings have been
+ * requested by the BIOS.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE);
+
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 5900f135dc6d..32391588e163 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -90,7 +90,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
/*
* hwgpe - GPE support
*/
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+ struct acpi_gpe_register_info *gpe_register_info);
+
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index a221ad404167..7c2c336006a1 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -69,7 +69,7 @@ acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
- u8 register_bit;
+ u32 register_bit;
ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
@@ -78,9 +78,8 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_NOT_EXIST);
}
- register_bit = (u8)
- (1 <<
- (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/* Clear the wake/run bits up front */
@@ -100,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_OK);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_ev_enable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to enable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
- * of type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE(ev_enable_gpe);
-
-
- /*
- * We will only allow a GPE to be enabled if it has either an
- * associated method (_Lxx/_Exx) or a handler. Otherwise, the
- * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
- * first time it fires.
- */
- if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
- return_ACPI_STATUS(AE_NO_HANDLER);
- }
-
- /* Ensure the HW enable masks are current */
-
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Clear the GPE (of stale events) */
-
- status = acpi_hw_clear_gpe(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Enable the requested GPE */
-
- status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ev_disable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to disable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
- * regardless of the type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(ev_disable_gpe);
-
-
- /*
- * Note: Always disable the GPE, even if we think that that it is already
- * disabled. It is possible that the AML or some other code has enabled
- * the GPE behind our back.
- */
-
- /* Ensure the HW enable masks are current */
-
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /*
- * Always H/W disable this GPE, even if we don't know the GPE type.
- * Simply clear the enable bit for this particular GPE, but do not
- * write out the current GPE enable mask since this may inadvertently
- * enable GPEs too early. An example is a rogue GPE that has arrived
- * during ACPICA initialization - possibly because AML or other code
- * has enabled the GPE.
- */
- status = acpi_hw_low_disable_gpe(gpe_event_info);
- return_ACPI_STATUS(status);
-}
-
/*******************************************************************************
*
@@ -451,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
return_VOID;
}
- /* Update the GPE register masks for return to enabled state */
-
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
-
/*
* Take a snapshot of the GPE info for this level - we copy the info to
* prevent a race condition with remove_handler/remove_block.
@@ -607,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Disable the GPE, so it doesn't keep firing before the method has a
* chance to run (it runs asynchronously with interrupts enabled).
*/
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
@@ -644,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Disable the GPE. The GPE will remain disabled a handler
* is installed or ACPICA is restarted.
*/
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 7c28f2d9fd35..341a38ce8aa6 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -500,6 +500,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index];
+ gpe_number = gpe_index + gpe_block->block_base_number;
+
+ /*
+ * If the GPE has already been enabled for runtime
+ * signaling, make sure it remains enabled, but do not
+ * increment its reference counter.
+ */
+ if (gpe_event_info->runtime_count) {
+ acpi_set_gpe(gpe_device, gpe_number,
+ ACPI_GPE_ENABLE);
+ gpe_enabled_count++;
+ continue;
+ }
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
wake_gpe_count++;
@@ -516,7 +529,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
/* Enable this GPE */
- gpe_number = gpe_index + gpe_block->block_base_number;
status = acpi_enable_gpe(gpe_device, gpe_number,
ACPI_GPE_TYPE_RUNTIME);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index cc825023012a..4a531cdf7942 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -719,13 +719,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
- /* Disable the GPE before installing the handler */
-
- status = acpi_ev_disable_gpe(gpe_event_info);
- if (ACPI_FAILURE (status)) {
- goto unlock_and_exit;
- }
-
/* Install the handler */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d5a5efc043bf..18b3f1468b7d 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -70,6 +70,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
acpi_status acpi_enable(void)
{
acpi_status status;
+ int retry;
ACPI_FUNCTION_TRACE(acpi_enable);
@@ -98,16 +99,18 @@ acpi_status acpi_enable(void)
/* Sanity check that transition succeeded */
- if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) {
- ACPI_ERROR((AE_INFO,
- "Hardware did not enter ACPI mode"));
- return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
+ for (retry = 0; retry < 30000; ++retry) {
+ if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
+ if (retry != 0)
+ ACPI_WARNING((AE_INFO,
+ "Platform took > %d00 usec to enter ACPI mode", retry));
+ return_ACPI_STATUS(AE_OK);
+ }
+ acpi_os_stall(100); /* 100 usec */
}
- ACPI_DEBUG_PRINT((ACPI_DB_INIT,
- "Transition to ACPI mode successful\n"));
-
- return_ACPI_STATUS(AE_OK);
+ ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
ACPI_EXPORT_SYMBOL(acpi_enable)
@@ -210,6 +213,44 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
/*******************************************************************************
*
+ * FUNCTION: acpi_clear_and_enable_gpe
+ *
+ * PARAMETERS: gpe_event_info - GPE to enable
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clear the given GPE from stale events and enable it.
+ *
+ ******************************************************************************/
+static acpi_status
+acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+{
+ acpi_status status;
+
+ /*
+ * We will only allow a GPE to be enabled if it has either an
+ * associated method (_Lxx/_Exx) or a handler. Otherwise, the
+ * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
+ * first time it fires.
+ */
+ if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
+ return_ACPI_STATUS(AE_NO_HANDLER);
+ }
+
+ /* Clear the GPE (of stale events) */
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Enable the requested GPE */
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_set_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
@@ -249,11 +290,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
switch (action) {
case ACPI_GPE_ENABLE:
- status = acpi_ev_enable_gpe(gpe_event_info);
+ status = acpi_clear_and_enable_gpe(gpe_event_info);
break;
case ACPI_GPE_DISABLE:
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
break;
default:
@@ -316,7 +357,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
gpe_event_info->runtime_count++;
if (gpe_event_info->runtime_count == 1) {
- status = acpi_ev_enable_gpe(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_clear_and_enable_gpe(gpe_event_info);
+ }
+
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count--;
goto unlock_and_exit;
@@ -343,7 +388,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
*/
gpe_event_info->wakeup_count++;
if (gpe_event_info->wakeup_count == 1) {
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
@@ -403,7 +448,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
gpe_event_info->runtime_count--;
if (!gpe_event_info->runtime_count) {
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_hw_low_set_gpe(gpe_event_info,
+ ACPI_GPE_DISABLE);
+ }
+
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count++;
goto unlock_and_exit;
@@ -424,7 +474,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
gpe_event_info->wakeup_count--;
if (!gpe_event_info->wakeup_count) {
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index 6d32e09327f1..675aaa91a770 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -201,6 +201,14 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)
acpi_ex_relinquish_interpreter();
+ /*
+ * For compatibility with other ACPI implementations and to prevent
+ * accidental deep sleeps, limit the sleep time to something reasonable.
+ */
+ if (how_long > ACPI_MAX_SLEEP) {
+ how_long = ACPI_MAX_SLEEP;
+ }
+
acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index bd72319a38f0..3450309c2786 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -57,21 +57,47 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/******************************************************************************
*
- * FUNCTION: acpi_hw_low_disable_gpe
+ * FUNCTION: acpi_hw_gpe_register_bit
+ *
+ * PARAMETERS: gpe_event_info - Info block for the GPE
+ * gpe_register_info - Info block for the GPE register
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given
+ * GPE set.
+ *
+ ******************************************************************************/
+
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+ struct acpi_gpe_register_info *gpe_register_info)
+{
+ return (u32)1 << (gpe_event_info->gpe_number -
+ gpe_register_info->base_gpe_number);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_hw_low_set_gpe
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
+ * action - Enable or disable
*
* RETURN: Status
*
- * DESCRIPTION: Disable a single GPE in the enable register.
+ * DESCRIPTION: Enable or disable a single GPE in its enable register.
*
******************************************************************************/
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u32 enable_mask;
+ u32 register_bit;
+
+ ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
@@ -87,11 +113,27 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
return (status);
}
- /* Clear just the bit that corresponds to this GPE */
+ /* Set ot clear just the bit that corresponds to this GPE */
- ACPI_CLEAR_BIT(enable_mask, ((u32)1 <<
- (gpe_event_info->gpe_number -
- gpe_register_info->base_gpe_number)));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
+ switch (action) {
+ case ACPI_GPE_COND_ENABLE:
+ if (!(register_bit & gpe_register_info->enable_for_run))
+ return (AE_BAD_PARAMETER);
+
+ case ACPI_GPE_ENABLE:
+ ACPI_SET_BIT(enable_mask, register_bit);
+ break;
+
+ case ACPI_GPE_DISABLE:
+ ACPI_CLEAR_BIT(enable_mask, register_bit);
+ break;
+
+ default:
+ ACPI_ERROR((AE_INFO, "Invalid action\n"));
+ return (AE_BAD_PARAMETER);
+ }
/* Write the updated enable mask */
@@ -116,23 +158,11 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
{
- struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
ACPI_FUNCTION_ENTRY();
- /* Get the info block for the entire GPE register */
-
- gpe_register_info = gpe_event_info->register_info;
- if (!gpe_register_info) {
- return (AE_NOT_EXIST);
- }
-
- /* Write the entire GPE (runtime) enable register */
-
- status = acpi_hw_write(gpe_register_info->enable_for_run,
- &gpe_register_info->enable_address);
-
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
return (status);
}
@@ -150,21 +180,28 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
+ struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
- u8 register_bit;
+ u32 register_bit;
ACPI_FUNCTION_ENTRY();
- register_bit = (u8)(1 <<
- (gpe_event_info->gpe_number -
- gpe_event_info->register_info->base_gpe_number));
+ /* Get the info block for the entire GPE register */
+
+ gpe_register_info = gpe_event_info->register_info;
+ if (!gpe_register_info) {
+ return (AE_NOT_EXIST);
+ }
+
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_hw_write(register_bit,
- &gpe_event_info->register_info->status_address);
+ &gpe_register_info->status_address);
return (status);
}
@@ -187,7 +224,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
acpi_event_status * event_status)
{
u32 in_byte;
- u8 register_bit;
+ u32 register_bit;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
acpi_event_status local_event_status = 0;
@@ -204,9 +241,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* Get the register bitmask for this GPE */
- register_bit = (u8)(1 <<
- (gpe_event_info->gpe_number -
- gpe_event_info->register_info->base_gpe_number));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/* GPE currently enabled? (enabled for runtime?) */
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index c10d587c1641..e1d9c777b213 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -222,6 +222,12 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
u32 one_byte;
u32 i;
+ /* Truncate address to 16 bits if requested */
+
+ if (acpi_gbl_truncate_io_addresses) {
+ address &= ACPI_UINT16_MAX;
+ }
+
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
@@ -279,6 +285,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
acpi_status status;
u32 i;
+ /* Truncate address to 16 bits if requested */
+
+ if (acpi_gbl_truncate_io_addresses) {
+ address &= ACPI_UINT16_MAX;
+ }
+
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 9bd6f050f299..4e5272c313e0 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -193,6 +193,15 @@ acpi_status acpi_ns_initialize_devices(void)
acpi_ns_init_one_device, NULL, &info,
NULL);
+ /*
+ * Any _OSI requests should be completed by now. If the BIOS has
+ * requested any Windows OSI strings, we will always truncate
+ * I/O addresses to 16 bits -- for Windows compatibility.
+ */
+ if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
+ acpi_gbl_truncate_io_addresses = TRUE;
+ }
+
ACPI_FREE(info.evaluate_info);
if (ACPI_FAILURE(status)) {
goto error_exit;
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index db3946e9c66b..216e1e948ff6 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kref.h>
#include <linux/rculist.h>
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 2ebc39115507..864dd46c346f 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -781,7 +781,7 @@ static int __init erst_init(void)
status = acpi_get_table(ACPI_SIG_ERST, 0,
(struct acpi_table_header **)&erst_tab);
if (status == AE_NOT_FOUND) {
- pr_err(ERST_PFX "Table is not found!\n");
+ pr_info(ERST_PFX "Table is not found!\n");
goto err;
} else if (ACPI_FAILURE(status)) {
const char *msg = acpi_format_exception(status);
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
index 814b19249616..8f8bd736d4ff 100644
--- a/drivers/acpi/atomicio.c
+++ b/drivers/acpi/atomicio.c
@@ -31,6 +31,7 @@
#include <linux/kref.h>
#include <linux/rculist.h>
#include <linux/interrupt.h>
+#include <linux/slab.h>
#include <acpi/atomicio.h>
#define ACPI_PFX "ACPI: "
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 3026e3fa83ef..dc58402b0a17 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -868,9 +868,15 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
static void acpi_battery_notify(struct acpi_device *device, u32 event)
{
struct acpi_battery *battery = acpi_driver_data(device);
+#ifdef CONFIG_ACPI_SYSFS_POWER
+ struct device *old;
+#endif
if (!battery)
return;
+#ifdef CONFIG_ACPI_SYSFS_POWER
+ old = battery->bat.dev;
+#endif
acpi_battery_update(battery);
acpi_bus_generate_proc_event(device, event,
acpi_battery_present(battery));
@@ -879,7 +885,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
acpi_battery_present(battery));
#ifdef CONFIG_ACPI_SYSFS_POWER
/* acpi_battery_update could remove power_supply object */
- if (battery->bat.dev)
+ if (old && battery->bat.dev)
power_supply_changed(&battery->bat);
#endif
}
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 2815df66f6f7..2bb28b9d91c4 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -214,7 +214,15 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
.ident = "Sony VGN-SR290J",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_vista,
+ .ident = "VGN-NS50B_L",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
},
},
{
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index fd51c4ab4829..7d857dabdde4 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device)
/* Button's GPE is run-wake GPE */
acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
+ ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count++;
device->wakeup.state.enabled = 1;
}
@@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
if (device->wakeup.flags.valid) {
acpi_disable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
+ ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count--;
device->wakeup.state.enabled = 0;
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index acf2ab249842..8a3b840c0bb2 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -347,7 +347,6 @@ static int __init acpi_fan_init(void)
{
int result = 0;
-
#ifdef CONFIG_ACPI_PROCFS
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
@@ -356,7 +355,9 @@ static int __init acpi_fan_init(void)
result = acpi_bus_register_driver(&acpi_fan_driver);
if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
return -ENODEV;
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 51284351418f..e9699aaed109 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -223,7 +223,7 @@ static bool processor_physically_present(acpi_handle handle)
type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
cpuid = acpi_get_cpuid(handle, type, acpi_id);
- if (cpuid == -1)
+ if ((cpuid == -1) && (num_possible_cpus() > 1))
return false;
return true;
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index b1034a9ada4e..38ea0cc6dc49 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return 0;
}
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index b1b385692f46..e9a8026d39f0 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -76,14 +76,19 @@ static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
module_param(max_cstate, uint, 0000);
static unsigned int nocst __read_mostly;
module_param(nocst, uint, 0000);
+static int bm_check_disable __read_mostly;
+module_param(bm_check_disable, uint, 0000);
static unsigned int latency_factor __read_mostly = 2;
module_param(latency_factor, uint, 0644);
+#ifdef CONFIG_ACPI_PROCFS
static u64 us_to_pm_timer_ticks(s64 t)
{
return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);
}
+#endif
+
/*
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
* For now disable this. Probably a bug somewhere else.
@@ -763,6 +768,9 @@ static int acpi_idle_bm_check(void)
{
u32 bm_status = 0;
+ if (bm_check_disable)
+ return 0;
+
acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
if (bm_status)
acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
@@ -947,7 +955,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (acpi_idle_suspend)
return(acpi_idle_enter_c1(dev, state));
- if (acpi_idle_bm_check()) {
+ if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
if (dev->safe_state) {
dev->last_state = dev->safe_state;
return dev->safe_state->enter(dev, dev->safe_state);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 3fb4bdea7e06..2862c781b372 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -82,6 +82,20 @@ static int acpi_sleep_prepare(u32 acpi_state)
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
/*
+ * The ACPI specification wants us to save NVS memory regions during hibernation
+ * and to restore them during the subsequent resume. Windows does that also for
+ * suspend to RAM. However, it is known that this mechanism does not work on
+ * all machines, so we allow the user to disable it with the help of the
+ * 'acpi_sleep=nonvs' kernel command line option.
+ */
+static bool nvs_nosave;
+
+void __init acpi_nvs_nosave(void)
+{
+ nvs_nosave = true;
+}
+
+/*
* ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
* user to request that behavior by using the 'acpi_old_suspend_ordering'
* kernel command line option that causes the following variable to be set.
@@ -114,6 +128,8 @@ static int __acpi_pm_prepare(void)
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ suspend_nvs_save();
+
if (error)
acpi_target_sleep_state = ACPI_STATE_S0;
return error;
@@ -143,6 +159,9 @@ static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
+ suspend_nvs_free();
+ acpi_ec_unblock_transactions();
+
if (acpi_state == ACPI_STATE_S0)
return;
@@ -192,6 +211,10 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
+ error = nvs_nosave ? 0 : suspend_nvs_alloc();
+ if (error)
+ return error;
+
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -269,12 +292,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
if (acpi_state == ACPI_STATE_S3)
acpi_restore_state_mem();
+ suspend_nvs_restore();
+
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
static void acpi_suspend_finish(void)
{
- acpi_ec_unblock_transactions();
acpi_pm_finish();
}
@@ -377,20 +401,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
-/*
- * The ACPI specification wants us to save NVS memory regions during hibernation
- * and to restore them during the subsequent resume. However, it is not certain
- * if this mechanism is going to work on all machines, so we allow the user to
- * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
- * option.
- */
-static bool s4_no_nvs;
-
-void __init acpi_s4_no_nvs(void)
-{
- s4_no_nvs = true;
-}
-
static unsigned long s4_hardware_signature;
static struct acpi_table_facs *facs;
static bool nosigcheck;
@@ -404,7 +414,7 @@ static int acpi_hibernation_begin(void)
{
int error;
- error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
+ error = nvs_nosave ? 0 : suspend_nvs_alloc();
if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -418,7 +428,7 @@ static int acpi_hibernation_pre_snapshot(void)
int error = acpi_pm_prepare();
if (!error)
- hibernate_nvs_save();
+ suspend_nvs_save();
return error;
}
@@ -441,13 +451,6 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
-static void acpi_hibernation_finish(void)
-{
- hibernate_nvs_free();
- acpi_ec_unblock_transactions();
- acpi_pm_finish();
-}
-
static void acpi_hibernation_leave(void)
{
/*
@@ -464,7 +467,7 @@ static void acpi_hibernation_leave(void)
panic("ACPI S4 hardware signature mismatch");
}
/* Restore the NVS memory area */
- hibernate_nvs_restore();
+ suspend_nvs_restore();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions_early();
}
@@ -479,7 +482,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot,
- .finish = acpi_hibernation_finish,
+ .finish = acpi_pm_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
@@ -506,8 +509,8 @@ static int acpi_hibernation_begin_old(void)
error = acpi_sleep_prepare(ACPI_STATE_S4);
if (!error) {
- if (!s4_no_nvs)
- error = hibernate_nvs_alloc();
+ if (!nvs_nosave)
+ error = suspend_nvs_alloc();
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
}
@@ -517,7 +520,7 @@ static int acpi_hibernation_begin_old(void)
static int acpi_hibernation_pre_snapshot_old(void)
{
acpi_pm_freeze();
- hibernate_nvs_save();
+ suspend_nvs_save();
return 0;
}
@@ -529,8 +532,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
- .finish = acpi_hibernation_finish,
.prepare = acpi_pm_freeze,
+ .finish = acpi_pm_finish,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
.pre_restore = acpi_pm_freeze,
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index c79e789ed03a..f8db50a0941c 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -388,10 +388,12 @@ static ssize_t counter_set(struct kobject *kobj,
if (index < num_gpes) {
if (!strcmp(buf, "disable\n") &&
(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
+ result = acpi_disable_gpe(handle, index,
+ ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "enable\n") &&
!(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
+ result = acpi_enable_gpe(handle, index,
+ ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index);
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c
index 4b9d339a6e28..388747a7ef4f 100644
--- a/drivers/acpi/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -64,16 +64,13 @@ void acpi_enable_wakeup_device(u8 sleep_state)
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
- if (!dev->wakeup.flags.valid)
- continue;
-
- if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
+ if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
|| sleep_state > (u32) dev->wakeup.sleep_state)
continue;
/* The wake-up power should have been enabled already. */
- acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
- ACPI_GPE_ENABLE);
+ acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE);
}
}
@@ -96,6 +93,8 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|| (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
+ acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE);
acpi_disable_wakeup_device_power(dev);
}
}
@@ -109,13 +108,8 @@ int __init acpi_wakeup_device_init(void)
struct acpi_device *dev = container_of(node,
struct acpi_device,
wakeup_list);
- /* In case user doesn't load button driver */
- if (!dev->wakeup.flags.always_enabled ||
- dev->wakeup.state.enabled)
- continue;
- acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE);
- dev->wakeup.state.enabled = 1;
+ if (dev->wakeup.flags.always_enabled)
+ dev->wakeup.state.enabled = 1;
}
mutex_unlock(&acpi_device_lock);
return 0;
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index f60b2b6a0931..d31590e7011b 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -122,6 +122,31 @@ static int __init amba_init(void)
postcore_initcall(amba_init);
+static int amba_get_enable_pclk(struct amba_device *pcdev)
+{
+ struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk");
+ int ret;
+
+ pcdev->pclk = pclk;
+
+ if (IS_ERR(pclk))
+ return PTR_ERR(pclk);
+
+ ret = clk_enable(pclk);
+ if (ret)
+ clk_put(pclk);
+
+ return ret;
+}
+
+static void amba_put_disable_pclk(struct amba_device *pcdev)
+{
+ struct clk *pclk = pcdev->pclk;
+
+ clk_disable(pclk);
+ clk_put(pclk);
+}
+
/*
* These are the device model conversion veneers; they convert the
* device model structures to our more specific structures.
@@ -130,17 +155,33 @@ static int amba_probe(struct device *dev)
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *pcdrv = to_amba_driver(dev->driver);
- struct amba_id *id;
+ struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
+ int ret;
- id = amba_lookup(pcdrv->id_table, pcdev);
+ do {
+ ret = amba_get_enable_pclk(pcdev);
+ if (ret)
+ break;
+
+ ret = pcdrv->probe(pcdev, id);
+ if (ret == 0)
+ break;
- return pcdrv->probe(pcdev, id);
+ amba_put_disable_pclk(pcdev);
+ } while (0);
+
+ return ret;
}
static int amba_remove(struct device *dev)
{
+ struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *drv = to_amba_driver(dev->driver);
- return drv->remove(to_amba_device(dev));
+ int ret = drv->remove(pcdev);
+
+ amba_put_disable_pclk(pcdev);
+
+ return ret;
}
static void amba_shutdown(struct device *dev)
@@ -203,7 +244,6 @@ static void amba_device_release(struct device *dev)
*/
int amba_device_register(struct amba_device *dev, struct resource *parent)
{
- u32 pid, cid;
u32 size;
void __iomem *tmp;
int i, ret;
@@ -241,25 +281,35 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
goto err_release;
}
- /*
- * Read pid and cid based on size of resource
- * they are located at end of region
- */
- for (pid = 0, i = 0; i < 4; i++)
- pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << (i * 8);
- for (cid = 0, i = 0; i < 4; i++)
- cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << (i * 8);
+ ret = amba_get_enable_pclk(dev);
+ if (ret == 0) {
+ u32 pid, cid;
- iounmap(tmp);
+ /*
+ * Read pid and cid based on size of resource
+ * they are located at end of region
+ */
+ for (pid = 0, i = 0; i < 4; i++)
+ pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) <<
+ (i * 8);
+ for (cid = 0, i = 0; i < 4; i++)
+ cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
+ (i * 8);
- if (cid == 0xb105f00d)
- dev->periphid = pid;
+ amba_put_disable_pclk(dev);
- if (!dev->periphid) {
- ret = -ENODEV;
- goto err_release;
+ if (cid == 0xb105f00d)
+ dev->periphid = pid;
+
+ if (!dev->periphid)
+ ret = -ENODEV;
}
+ iounmap(tmp);
+
+ if (ret)
+ goto err_release;
+
ret = device_add(&dev->dev);
if (ret)
goto err_release;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 8ca16f54e1ed..f2522534ae63 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1053,6 +1053,16 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
return -ENODEV;
+ /*
+ * For some reason, MCP89 on MacBook 7,1 doesn't work with
+ * ahci, use ata_generic instead.
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+ pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+ pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+ pdev->subsystem_device == 0xcb89)
+ return -ENODEV;
+
/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
* At the moment, we can only use the AHCI mode. Let the users know
* that for SAS drives they're out of luck.
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 573158a9668d..7107a6929deb 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -32,6 +32,11 @@
* A generic parallel ATA driver using libata
*/
+enum {
+ ATA_GEN_CLASS_MATCH = (1 << 0),
+ ATA_GEN_FORCE_DMA = (1 << 1),
+};
+
/**
* generic_set_mode - mode setting
* @link: link to set up
@@ -46,13 +51,17 @@
static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
{
struct ata_port *ap = link->ap;
+ const struct pci_device_id *id = ap->host->private_data;
int dma_enabled = 0;
struct ata_device *dev;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- /* Bits 5 and 6 indicate if DMA is active on master/slave */
- if (ap->ioaddr.bmdma_addr)
+ if (id->driver_data & ATA_GEN_FORCE_DMA) {
+ dma_enabled = 0xff;
+ } else if (ap->ioaddr.bmdma_addr) {
+ /* Bits 5 and 6 indicate if DMA is active on master/slave */
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
dma_enabled = 0xFF;
@@ -126,7 +135,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
const struct ata_port_info *ppi[] = { &info, NULL };
/* Don't use the generic entry unless instructed to do so */
- if (id->driver_data == 1 && all_generic_ide == 0)
+ if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
return -ENODEV;
/* Devices that need care */
@@ -155,7 +164,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
return rc;
pcim_pin_device(dev);
}
- return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0);
+ return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);
}
static struct pci_device_id ata_generic[] = {
@@ -167,7 +176,15 @@ static struct pci_device_id ata_generic[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
- { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
+ .driver_data = ATA_GEN_FORCE_DMA },
+ /*
+ * For some reason, MCP89 on MacBook 7,1 doesn't work with
+ * ahci, use ata_generic instead.
+ */
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
+ PCI_VENDOR_ID_APPLE, 0xcb89,
+ .driver_data = ATA_GEN_FORCE_DMA },
#if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
@@ -175,7 +192,8 @@ static struct pci_device_id ata_generic[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), },
#endif
/* Must come last. If you add entries adjust this table appropriately */
- { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
+ .driver_data = ATA_GEN_CLASS_MATCH },
{ 0, },
};
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 261f86d102e8..81e772a94d59 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -324,6 +324,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
struct ahci_host_priv *hpriv = ap->host->private_data;
void __iomem *mmio = hpriv->mmio;
void __iomem *em_mmio = mmio + hpriv->em_loc;
+ const unsigned char *msg_buf = buf;
u32 em_ctl, msg;
unsigned long flags;
int i;
@@ -343,8 +344,8 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
}
for (i = 0; i < size; i += 4) {
- msg = buf[i] | buf[i + 1] << 8 |
- buf[i + 2] << 16 | buf[i + 3] << 24;
+ msg = msg_buf[i] | msg_buf[i + 1] << 8 |
+ msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24;
writel(msg, em_mmio + i);
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 9630fbdf4e6c..9b9d3bd54e3a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -673,7 +673,7 @@ static struct kobject *get_device_parent(struct device *dev,
*/
if (parent == NULL)
parent_kobj = virtual_device_parent(dev);
- else if (parent->class)
+ else if (parent->class && !dev->class->ns_type)
return &parent->kobj;
else
parent_kobj = &parent->kobj;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 3381505c8a6c..72dae92f3cab 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -861,6 +861,7 @@ cciss_scsi_detect(int ctlr)
sh->n_io_port = 0; // I don't think we use these two...
sh->this_id = SELF_SCSI_ID;
sh->sg_tablesize = hba[ctlr]->maxsgentries;
+ sh->max_cmd_len = MAX_COMMAND_SIZE;
((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->scsi_host = sh;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 91d11631cec9..abb4ec6690fc 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -386,7 +386,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)
}
/* pdev is NULL for eisa */
-static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)
{
struct request_queue *q;
int j;
@@ -503,7 +503,7 @@ Enomem4:
return -1;
}
-static int __init cpqarray_init_one( struct pci_dev *pdev,
+static int __devinit cpqarray_init_one( struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int i;
@@ -740,7 +740,7 @@ __setup("smart2=", cpqarray_setup);
/*
* Find an EISA controller's signature. Set up an hba if we find it.
*/
-static int __init cpqarray_eisa_detect(void)
+static int __devinit cpqarray_eisa_detect(void)
{
int i=0, j;
__u32 board_id;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 6b077f93acc6..7258c95e895e 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
/* Last part of the attaching process ... */
if (ns.conn >= C_CONNECTED &&
os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
- kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
- mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
drbd_send_sizes(mdev, 0, 0); /* to start sync... */
drbd_send_uuids(mdev);
drbd_send_state(mdev);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 632e3245d1bb..2151f18b21de 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
mdev->new_state_tmp.i = ns.i;
ns.i = os.i;
ns.disk = D_NEGOTIATING;
+
+ /* We expect to receive up-to-date UUIDs soon.
+ To avoid a race in receive_state, free p_uuid while
+ holding req_lock. I.e. atomic with the state change */
+ kfree(mdev->p_uuid);
+ mdev->p_uuid = NULL;
}
rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 6f907ebed2d5..6d34f405a2f3 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -37,7 +37,7 @@
#include <linux/wait.h>
#include <linux/skbuff.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 40aec0fb8596..42d69d4de05c 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -244,7 +244,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
if (rel) {
hdr[0] |= 0x80 + bcsp->msgq_txseq;
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
- bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
+ bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07;
}
if (bcsp->use_crc)
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 4b51982fd23a..d2abf5143983 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -97,20 +97,18 @@ EXPORT_SYMBOL(agp_flush_chipset);
void agp_alloc_page_array(size_t size, struct agp_memory *mem)
{
mem->pages = NULL;
- mem->vmalloc_flag = false;
if (size <= 2*PAGE_SIZE)
- mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+ mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
if (mem->pages == NULL) {
mem->pages = vmalloc(size);
- mem->vmalloc_flag = true;
}
}
EXPORT_SYMBOL(agp_alloc_page_array);
void agp_free_page_array(struct agp_memory *mem)
{
- if (mem->vmalloc_flag) {
+ if (is_vmalloc_addr(mem->pages)) {
vfree(mem->pages);
} else {
kfree(mem->pages);
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 9344216183a4..a7547150a705 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1216,17 +1216,20 @@ static int intel_i915_get_gtt_size(void)
/* G33's GTT size defined in gmch_ctrl */
pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
- switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
- case G33_PGETBL_SIZE_1M:
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I830_GMCH_GMS_STOLEN_512:
+ size = 512;
+ break;
+ case I830_GMCH_GMS_STOLEN_1024:
size = 1024;
break;
- case G33_PGETBL_SIZE_2M:
- size = 2048;
+ case I830_GMCH_GMS_STOLEN_8192:
+ size = 8*1024;
break;
default:
dev_info(&agp_bridge->dev->dev,
"unknown page table size 0x%x, assuming 512KB\n",
- (gmch_ctrl & G33_PGETBL_SIZE_MASK));
+ (gmch_ctrl & I830_GMCH_GMS_MASK));
size = 512;
}
} else {
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 35603dd4e6c5..094bdc355b1f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -302,6 +302,12 @@ struct smi_info {
static int force_kipmid[SI_MAX_PARMS];
static int num_force_kipmid;
+#ifdef CONFIG_PCI
+static int pci_registered;
+#endif
+#ifdef CONFIG_PPC_OF
+static int of_registered;
+#endif
static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
static int num_max_busy_us;
@@ -1018,7 +1024,7 @@ static int ipmi_thread(void *data)
else if (smi_result == SI_SM_IDLE)
schedule_timeout_interruptible(100);
else
- schedule_timeout_interruptible(0);
+ schedule_timeout_interruptible(1);
}
return 0;
}
@@ -3314,6 +3320,8 @@ static __devinit int init_ipmi_si(void)
rv = pci_register_driver(&ipmi_pci_driver);
if (rv)
printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv);
+ else
+ pci_registered = 1;
#endif
#ifdef CONFIG_ACPI
@@ -3330,6 +3338,7 @@ static __devinit int init_ipmi_si(void)
#ifdef CONFIG_PPC_OF
of_register_platform_driver(&ipmi_of_platform_driver);
+ of_registered = 1;
#endif
/* We prefer devices with interrupts, but in the case of a machine
@@ -3383,11 +3392,13 @@ static __devinit int init_ipmi_si(void)
if (unload_when_empty && list_empty(&smi_infos)) {
mutex_unlock(&smi_infos_lock);
#ifdef CONFIG_PCI
- pci_unregister_driver(&ipmi_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_PPC_OF
- of_unregister_platform_driver(&ipmi_of_platform_driver);
+ if (of_registered)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
driver_unregister(&ipmi_driver.driver);
printk(KERN_WARNING PFX
@@ -3478,14 +3489,16 @@ static __exit void cleanup_ipmi_si(void)
return;
#ifdef CONFIG_PCI
- pci_unregister_driver(&ipmi_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_ACPI
pnp_unregister_driver(&ipmi_pnp_driver);
#endif
#ifdef CONFIG_PPC_OF
- of_unregister_platform_driver(&ipmi_of_platform_driver);
+ if (of_registered)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
mutex_lock(&smi_infos_lock);
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5d15630a5830..878ac0c2cc68 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -493,7 +493,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
sysrq_key_table[i] = op_p;
}
-static void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
+void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
{
struct sysrq_key_op *op_p;
int orig_log_level;
@@ -580,8 +580,12 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
case KEY_RIGHTALT:
if (value)
sysrq_alt = code;
- else if (sysrq_down && code == sysrq_alt_use)
- sysrq_down = false;
+ else {
+ if (sysrq_down && code == sysrq_alt_use)
+ sysrq_down = false;
+
+ sysrq_alt = 0;
+ }
break;
case KEY_SYSRQ:
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 8e00b4ddd083..792868d24f2a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -224,6 +224,7 @@ struct tpm_readpubek_params_out {
u8 algorithm[4];
u8 encscheme[2];
u8 sigscheme[2];
+ __be32 paramsize;
u8 parameters[12]; /*assuming RSA*/
__be32 keysize;
u8 modulus[256];
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 24314a9cffe8..1030f8420137 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -623,7 +623,14 @@ static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
static int tpm_tis_pnp_resume(struct pnp_dev *dev)
{
- return tpm_pm_resume(&dev->dev);
+ struct tpm_chip *chip = pnp_get_drvdata(dev);
+ int ret;
+
+ ret = tpm_pm_resume(&dev->dev);
+ if (!ret)
+ tpm_continue_selftest(chip);
+
+ return ret;
}
static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c
index d7be69f13154..b7dab32ce63c 100644
--- a/drivers/clocksource/cs5535-clockevt.c
+++ b/drivers/clocksource/cs5535-clockevt.c
@@ -194,6 +194,6 @@ err_timer:
module_init(cs5535_mfgpt_init);
-MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>");
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("CS5535/CS5536 MFGPT clock event driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index f3d3898898ed..717305d30444 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -449,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
clk_disable(p->clk);
/* TODO: calculate good shift from rate and counter bit width */
- cs->shift = 10;
+ cs->shift = 0;
cs->mult = clocksource_hz2mult(p->rate, cs->shift);
dev_info(&p->pdev->dev, "used as clock source\n");
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 063b2184caf5..938b74ea9ffb 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1077,6 +1077,7 @@ err_out_unregister:
err_unlock_policy:
unlock_policy_rwsem_write(cpu);
+ free_cpumask_var(policy->related_cpus);
err_free_cpumask:
free_cpumask_var(policy->cpus);
err_free_policy:
@@ -1762,17 +1763,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
dprintk("governor switch\n");
/* end old governor */
- if (data->governor) {
- /*
- * Need to release the rwsem around governor
- * stop due to lock dependency between
- * cancel_delayed_work_sync and the read lock
- * taken in the delayed work handler.
- */
- unlock_policy_rwsem_write(data->cpu);
+ if (data->governor)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
- lock_policy_rwsem_write(data->cpu);
- }
/* start new governor */
data->governor = policy->governor;
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 52ff8aa63f84..1b128702d300 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -143,7 +143,7 @@ static inline int which_bucket(unsigned int duration)
* This allows us to calculate
* E(duration)|iowait
*/
- if (nr_iowait_cpu())
+ if (nr_iowait_cpu(smp_processor_id()))
bucket = BUCKETS/2;
if (duration < 10)
@@ -175,7 +175,7 @@ static inline int performance_multiplier(void)
mult += 2 * get_loadavg();
/* for IO wait tasks (per cpu!) we add 5x each */
- mult += 10 * nr_iowait_cpu();
+ mult += 10 * nr_iowait_cpu(smp_processor_id());
return mult;
}
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 637c105f53d2..bd78acf3c365 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1183,10 +1183,14 @@ static size_t sg_copy_end_to_buffer(struct scatterlist *sgl, unsigned int nents,
/* Copy part of this segment */
ignore = skip - offset;
len = miter.length - ignore;
+ if (boffset + len > buflen)
+ len = buflen - boffset;
memcpy(buf + boffset, miter.addr + ignore, len);
} else {
- /* Copy all of this segment */
+ /* Copy all of this segment (up to buflen) */
len = miter.length;
+ if (boffset + len > buflen)
+ len = buflen - boffset;
memcpy(buf + boffset, miter.addr, len);
}
boffset += len;
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 5a22ca6927e5..7c3747902a37 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4257,10 +4257,12 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev,
struct ppc440spe_adma_chan *chan,
int *initcode)
{
+ struct of_device *ofdev;
struct device_node *np;
int ret;
- np = container_of(adev->dev, struct of_device, dev)->node;
+ ofdev = container_of(adev->dev, struct of_device, dev);
+ np = ofdev->dev.of_node;
if (adev->id != PPC440SPE_XOR_ID) {
adev->err_irq = irq_of_parse_and_map(np, 1);
if (adev->err_irq == NO_IRQ) {
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index aedef7941b22..0d2f9dbb47e4 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -209,7 +209,7 @@ config EDAC_I5100
config EDAC_MPC85XX
tristate "Freescale MPC83xx / MPC85xx"
- depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || MPC85xx)
+ depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
help
Support for error detection and correction on the Freescale
MPC8349, MPC8560, MPC8540, MPC8548
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index cf17dbb8014f..ac9f7985096d 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1958,20 +1958,20 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
u32 value = 0;
int err_sym = 0;
- amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value);
+ if (boot_cpu_data.x86 == 0x10) {
- /* F3x180[EccSymbolSize]=1, x8 symbols */
- if (boot_cpu_data.x86 == 0x10 &&
- boot_cpu_data.x86_model > 7 &&
- value & BIT(25)) {
- err_sym = decode_syndrome(syndrome, x8_vectors,
- ARRAY_SIZE(x8_vectors), 8);
- return map_err_sym_to_channel(err_sym, 8);
- } else {
- err_sym = decode_syndrome(syndrome, x4_vectors,
- ARRAY_SIZE(x4_vectors), 4);
- return map_err_sym_to_channel(err_sym, 4);
+ amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value);
+
+ /* F3x180[EccSymbolSize]=1 => x8 symbols */
+ if (boot_cpu_data.x86_model > 7 &&
+ value & BIT(25)) {
+ err_sym = decode_syndrome(syndrome, x8_vectors,
+ ARRAY_SIZE(x8_vectors), 8);
+ return map_err_sym_to_channel(err_sym, 8);
+ }
}
+ err_sym = decode_syndrome(syndrome, x4_vectors, ARRAY_SIZE(x4_vectors), 4);
+ return map_err_sym_to_channel(err_sym, 4);
}
/*
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 6b8b7b41ec5f..e0187d16dd7c 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1233,10 +1233,28 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
for (i = 0; i < MAX_SOCKET_BUSES; i++)
pcibios_scan_specific_bus(255-i);
}
+ pci_dev_put(pdev);
table++;
}
}
+static unsigned i7core_pci_lastbus(void)
+{
+ int last_bus = 0, bus;
+ struct pci_bus *b = NULL;
+
+ while ((b = pci_find_next_bus(b)) != NULL) {
+ bus = b->number;
+ debugf0("Found bus %d\n", bus);
+ if (bus > last_bus)
+ last_bus = bus;
+ }
+
+ debugf0("Last bus %d\n", last_bus);
+
+ return last_bus;
+}
+
/*
* i7core_get_devices Find and perform 'get' operation on the MCH's
* device/functions we want to reference for this driver
@@ -1244,7 +1262,8 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
* Need to 'get' device 16 func 1 and func 2
*/
int i7core_get_onedevice(struct pci_dev **prev, int devno,
- struct pci_id_descr *dev_descr, unsigned n_devs)
+ struct pci_id_descr *dev_descr, unsigned n_devs,
+ unsigned last_bus)
{
struct i7core_dev *i7core_dev;
@@ -1281,7 +1300,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
if (devno == 0)
return -ENODEV;
- i7core_printk(KERN_ERR,
+ i7core_printk(KERN_INFO,
"Device not found: dev %02x.%d PCI ID %04x:%04x\n",
dev_descr->dev, dev_descr->func,
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
@@ -1291,10 +1310,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
}
bus = pdev->bus->number;
- if (bus == 0x3f)
- socket = 0;
- else
- socket = 255 - bus;
+ socket = last_bus - bus;
i7core_dev = get_i7core_dev(socket);
if (!i7core_dev) {
@@ -1358,17 +1374,21 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
static int i7core_get_devices(struct pci_id_table *table)
{
- int i, rc;
+ int i, rc, last_bus;
struct pci_dev *pdev = NULL;
struct pci_id_descr *dev_descr;
+ last_bus = i7core_pci_lastbus();
+
while (table && table->descr) {
dev_descr = table->descr;
for (i = 0; i < table->n_devs; i++) {
pdev = NULL;
do {
- rc = i7core_get_onedevice(&pdev, i, &dev_descr[i],
- table->n_devs);
+ rc = i7core_get_onedevice(&pdev, i,
+ &dev_descr[i],
+ table->n_devs,
+ last_bus);
if (rc < 0) {
if (i == 0) {
i = table->n_devs;
@@ -1927,21 +1947,26 @@ fail:
* 0 for FOUND a device
* < 0 for error code
*/
+
+static int probed = 0;
+
static int __devinit i7core_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- int dev_idx = id->driver_data;
int rc;
struct i7core_dev *i7core_dev;
+ /* get the pci devices we want to reserve for our use */
+ mutex_lock(&i7core_edac_lock);
+
/*
* All memory controllers are allocated at the first pass.
*/
- if (unlikely(dev_idx >= 1))
+ if (unlikely(probed >= 1)) {
+ mutex_unlock(&i7core_edac_lock);
return -EINVAL;
-
- /* get the pci devices we want to reserve for our use */
- mutex_lock(&i7core_edac_lock);
+ }
+ probed++;
rc = i7core_get_devices(pci_dev_table);
if (unlikely(rc < 0))
@@ -2013,6 +2038,8 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
i7core_dev->socket);
}
}
+ probed--;
+
mutex_unlock(&i7core_edac_lock);
}
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 52ca09bf4726..1052340e6802 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -336,6 +336,7 @@ static struct of_device_id mpc85xx_pci_err_of_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
static struct of_platform_driver mpc85xx_pci_err_driver = {
.probe = mpc85xx_pci_err_probe,
@@ -650,6 +651,7 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {
{ .compatible = "fsl,p2020-l2-cache-controller", },
{},
};
+MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
static struct of_platform_driver mpc85xx_l2_err_driver = {
.probe = mpc85xx_l2_err_probe,
@@ -1120,11 +1122,13 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
{ .compatible = "fsl,mpc8555-memory-controller", },
{ .compatible = "fsl,mpc8560-memory-controller", },
{ .compatible = "fsl,mpc8568-memory-controller", },
+ { .compatible = "fsl,mpc8569-memory-controller", },
{ .compatible = "fsl,mpc8572-memory-controller", },
{ .compatible = "fsl,mpc8349-memory-controller", },
{ .compatible = "fsl,p2020-memory-controller", },
{},
};
+MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
static struct of_platform_driver mpc85xx_mc_err_driver = {
.probe = mpc85xx_mc_err_probe,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 724038dab4ca..7face915b963 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1,5 +1,5 @@
#
-# GPIO infrastructure and expanders
+# platform-neutral GPIO infrastructure and expanders
#
config ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 51c3cdd41b5a..e53dcff49b4f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,4 +1,8 @@
-# gpio support: dedicated expander chips, etc
+# generic gpio support: dedicated expander chips, etc
+#
+# NOTE: platform-specific GPIO drivers don't belong in the
+# drivers/gpio directory; put them with other platform setup
+# code, IRQ controllers, board init, etc.
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index f73a1555e49d..e23c06893d19 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -352,6 +352,6 @@ static void __exit cs5535_gpio_exit(void)
module_init(cs5535_gpio_init);
module_exit(cs5535_gpio_exit);
-MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>");
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 3ca36542e338..4e51fe3c1fc4 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -893,10 +893,12 @@ EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);
void gpio_unexport(unsigned gpio)
{
struct gpio_desc *desc;
- int status = -EINVAL;
+ int status = 0;
- if (!gpio_is_valid(gpio))
+ if (!gpio_is_valid(gpio)) {
+ status = -EINVAL;
goto done;
+ }
mutex_lock(&sysfs_lock);
@@ -911,7 +913,6 @@ void gpio_unexport(unsigned gpio)
clear_bit(FLAG_EXPORT, &desc->flags);
put_device(dev);
device_unregister(dev);
- status = 0;
} else
status = -ENODEV;
}
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
index ee568c8fcbd0..5005990f751f 100644
--- a/drivers/gpio/pl061.c
+++ b/drivers/gpio/pl061.c
@@ -232,7 +232,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
desc->chip->unmask(irq);
}
-static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
+static int pl061_probe(struct amba_device *dev, struct amba_id *id)
{
struct pl061_platform_data *pdata;
struct pl061_gpio *chip;
@@ -333,7 +333,7 @@ free_mem:
return ret;
}
-static struct amba_id pl061_ids[] __initdata = {
+static struct amba_id pl061_ids[] = {
{
.id = 0x00041061,
.mask = 0x000fffff,
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index da06476f2df4..9585e531ac6b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -864,8 +864,8 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0,
false);
mode->hdisplay = 1366;
- mode->vsync_start = mode->vsync_start - 1;
- mode->vsync_end = mode->vsync_end - 1;
+ mode->hsync_start = mode->hsync_start - 1;
+ mode->hsync_end = mode->hsync_end - 1;
return mode;
}
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 08c4c926e65f..719662034bbf 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -146,7 +146,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn
cvt = 1;
break;
case 'R':
- if (!cvt)
+ if (cvt)
rb = 1;
break;
case 'm':
@@ -315,8 +315,9 @@ static void drm_fb_helper_on(struct fb_info *info)
struct drm_device *dev = fb_helper->dev;
struct drm_crtc *crtc;
struct drm_crtc_helper_funcs *crtc_funcs;
+ struct drm_connector *connector;
struct drm_encoder *encoder;
- int i;
+ int i, j;
/*
* For each CRTC in this fb, turn the crtc on then,
@@ -332,7 +333,14 @@ static void drm_fb_helper_on(struct fb_info *info)
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-
+ /* Walk the connectors & encoders on this fb turning them on */
+ for (j = 0; j < fb_helper->connector_count; j++) {
+ connector = fb_helper->connector_info[j]->connector;
+ connector->dpms = DRM_MODE_DPMS_ON;
+ drm_connector_property_set_value(connector,
+ dev->mode_config.dpms_property,
+ DRM_MODE_DPMS_ON);
+ }
/* Found a CRTC on this fb, now find encoders */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
@@ -352,8 +360,9 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
struct drm_device *dev = fb_helper->dev;
struct drm_crtc *crtc;
struct drm_crtc_helper_funcs *crtc_funcs;
+ struct drm_connector *connector;
struct drm_encoder *encoder;
- int i;
+ int i, j;
/*
* For each CRTC in this fb, find all associated encoders
@@ -367,6 +376,14 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
if (!crtc->enabled)
continue;
+ /* Walk the connectors on this fb and mark them off */
+ for (j = 0; j < fb_helper->connector_count; j++) {
+ connector = fb_helper->connector_info[j]->connector;
+ connector->dpms = dpms_mode;
+ drm_connector_property_set_value(connector,
+ dev->mode_config.dpms_property,
+ dpms_mode);
+ }
/* Found a CRTC on this fb, now find encoders */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
@@ -1024,11 +1041,18 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
}
create_mode:
- mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres,
- cmdline_mode->yres,
- cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
- cmdline_mode->rb, cmdline_mode->interlace,
- cmdline_mode->margins);
+ if (cmdline_mode->cvt)
+ mode = drm_cvt_mode(fb_helper_conn->connector->dev,
+ cmdline_mode->xres, cmdline_mode->yres,
+ cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+ cmdline_mode->rb, cmdline_mode->interlace,
+ cmdline_mode->margins);
+ else
+ mode = drm_gtf_mode(fb_helper_conn->connector->dev,
+ cmdline_mode->xres, cmdline_mode->yres,
+ cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+ cmdline_mode->interlace,
+ cmdline_mode->margins);
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
list_add(&mode->head, &fb_helper_conn->connector->modes);
return mode;
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 66c697bc9b22..56f66426207f 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -208,7 +208,7 @@ static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)
uint8_t ctl2;
if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
- if (ctl2 & TFP410_CTL_2_HTPLG)
+ if (ctl2 & TFP410_CTL_2_RSEN)
ret = connector_status_connected;
else
ret = connector_status_disconnected;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 52510ad8b25d..9214119c0154 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -605,6 +605,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
case FBC_NOT_TILED:
seq_printf(m, "scanout buffer not tiled");
break;
+ case FBC_MULTIPLE_PIPES:
+ seq_printf(m, "multiple pipes are enabled");
+ break;
default:
seq_printf(m, "unknown reason");
}
@@ -620,7 +623,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
drm_i915_private_t *dev_priv = dev->dev_private;
bool sr_enabled = false;
- if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev))
+ if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev))
sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
else if (IS_I915GM(dev))
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 59a2bf8592ec..2305a1234f1e 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -128,9 +128,11 @@ static int i915_dma_cleanup(struct drm_device * dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
+ mutex_lock(&dev->struct_mutex);
intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
if (HAS_BSD(dev))
intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+ mutex_unlock(&dev->struct_mutex);
/* Clear the HWS virtual address at teardown */
if (I915_NEED_GFX_HWS(dev))
@@ -1229,7 +1231,7 @@ static void i915_warn_stolen(struct drm_device *dev)
static void i915_setup_compression(struct drm_device *dev, int size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_mm_node *compressed_fb, *compressed_llb;
+ struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
unsigned long cfb_base;
unsigned long ll_base = 0;
@@ -1298,7 +1300,7 @@ static void i915_cleanup_compression(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
drm_mm_put_block(dev_priv->compressed_fb);
- if (!IS_GM45(dev))
+ if (dev_priv->compressed_llb)
drm_mm_put_block(dev_priv->compressed_llb);
}
@@ -1410,6 +1412,10 @@ static int i915_load_modeset_init(struct drm_device *dev,
if (ret)
goto cleanup_vga_client;
+ /* IIR "flip pending" bit means done if this bit is set */
+ if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
+ dev_priv->flip_pending_is_done = true;
+
intel_modeset_init(dev);
ret = drm_irq_install(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 276583159847..2e1744d37ad5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -215,6 +215,7 @@ enum no_fbc_reason {
FBC_MODE_TOO_LARGE, /* mode too large for compression */
FBC_BAD_PLANE, /* fbc not supported on plane */
FBC_NOT_TILED, /* buffer not tiled */
+ FBC_MULTIPLE_PIPES, /* more than one pipe active */
};
enum intel_pch {
@@ -222,6 +223,8 @@ enum intel_pch {
PCH_CPT, /* Cougarpoint PCH */
};
+#define QUIRK_PIPEA_FORCE (1<<0)
+
struct intel_fbdev;
typedef struct drm_i915_private {
@@ -337,6 +340,8 @@ typedef struct drm_i915_private {
/* PCH chipset type */
enum intel_pch pch_type;
+ unsigned long quirks;
+
/* Register state */
bool modeset_on_lid;
u8 saveLBB;
@@ -596,6 +601,7 @@ typedef struct drm_i915_private {
struct drm_crtc *plane_to_crtc_mapping[2];
struct drm_crtc *pipe_to_crtc_mapping[2];
wait_queue_head_t pending_flip_queue;
+ bool flip_pending_is_done;
/* Reclocking support */
bool render_reclock_avail;
@@ -1076,7 +1082,7 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
drm_i915_private_t *dev_priv = dev->dev_private; \
if (I915_VERBOSE) \
DRM_DEBUG(" BEGIN_LP_RING %x\n", (int)(n)); \
- intel_ring_begin(dev, &dev_priv->render_ring, 4*(n)); \
+ intel_ring_begin(dev, &dev_priv->render_ring, (n)); \
} while (0)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9ded3dae6c87..5aa747fc25a9 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2239,8 +2239,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
mapping = inode->i_mapping;
for (i = 0; i < page_count; i++) {
page = read_cache_page_gfp(mapping, i,
- mapping_gfp_mask (mapping) |
+ GFP_HIGHUSER |
__GFP_COLD |
+ __GFP_RECLAIMABLE |
gfpmask);
if (IS_ERR(page))
goto err_pages;
@@ -3646,6 +3647,7 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev,
return ret;
}
+
int
i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv,
@@ -3793,7 +3795,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
unsigned long long total_size = 0;
int num_fences = 0;
for (i = 0; i < args->buffer_count; i++) {
- obj_priv = object_list[i]->driver_private;
+ obj_priv = to_intel_bo(object_list[i]);
total_size += object_list[i]->size;
num_fences +=
@@ -4741,6 +4743,16 @@ i915_gem_load(struct drm_device *dev)
list_add(&dev_priv->mm.shrink_list, &shrink_list);
spin_unlock(&shrink_list_lock);
+ /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
+ if (IS_GEN3(dev)) {
+ u32 tmp = I915_READ(MI_ARB_STATE);
+ if (!(tmp & MI_ARB_C3_LP_WRITE_ENABLE)) {
+ /* arb state is a masked write, so set bit + bit in mask */
+ tmp = MI_ARB_C3_LP_WRITE_ENABLE | (MI_ARB_C3_LP_WRITE_ENABLE << MI_ARB_MASK_SHIFT);
+ I915_WRITE(MI_ARB_STATE, tmp);
+ }
+ }
+
/* Old X drivers will take 0-2 for front, back, depth buffers */
if (!drm_core_check_feature(dev, DRIVER_MODESET))
dev_priv->fence_reg_start = 3;
@@ -4977,7 +4989,7 @@ i915_gpu_is_active(struct drm_device *dev)
}
static int
-i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
+i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
{
drm_i915_private_t *dev_priv, *next_dev;
struct drm_i915_gem_object *obj_priv, *next_obj;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2479be001e40..dba53d4b9fb3 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -940,22 +940,30 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
- if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
+ if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
intel_prepare_page_flip(dev, 0);
+ if (dev_priv->flip_pending_is_done)
+ intel_finish_page_flip_plane(dev, 0);
+ }
- if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
+ if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
intel_prepare_page_flip(dev, 1);
+ if (dev_priv->flip_pending_is_done)
+ intel_finish_page_flip_plane(dev, 1);
+ }
if (pipea_stats & vblank_status) {
vblank++;
drm_handle_vblank(dev, 0);
- intel_finish_page_flip(dev, 0);
+ if (!dev_priv->flip_pending_is_done)
+ intel_finish_page_flip(dev, 0);
}
if (pipeb_stats & vblank_status) {
vblank++;
drm_handle_vblank(dev, 1);
- intel_finish_page_flip(dev, 1);
+ if (!dev_priv->flip_pending_is_done)
+ intel_finish_page_flip(dev, 1);
}
if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
@@ -1387,29 +1395,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
dev_priv->pipestat[1] = 0;
if (I915_HAS_HOTPLUG(dev)) {
- u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-
- /* Note HDMI and DP share bits */
- if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
- hotplug_en |= HDMIB_HOTPLUG_INT_EN;
- if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
- hotplug_en |= HDMIC_HOTPLUG_INT_EN;
- if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
- hotplug_en |= HDMID_HOTPLUG_INT_EN;
- if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
- hotplug_en |= SDVOC_HOTPLUG_INT_EN;
- if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
- hotplug_en |= SDVOB_HOTPLUG_INT_EN;
- if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
- hotplug_en |= CRT_HOTPLUG_INT_EN;
- /* Ignore TV since it's buggy */
-
- I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-
/* Enable in IER... */
enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
/* and unmask in IMR */
- i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
+ dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;
}
/*
@@ -1427,16 +1416,41 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
}
I915_WRITE(EMR, error_mask);
- /* Disable pipe interrupt enables, clear pending pipe status */
- I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
- I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
- /* Clear pending interrupt status */
- I915_WRITE(IIR, I915_READ(IIR));
-
- I915_WRITE(IER, enable_mask);
I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ I915_WRITE(IER, enable_mask);
(void) I915_READ(IER);
+ if (I915_HAS_HOTPLUG(dev)) {
+ u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+ /* Note HDMI and DP share bits */
+ if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+ hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+ if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+ hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+ if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+ hotplug_en |= HDMID_HOTPLUG_INT_EN;
+ if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+ hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+ if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+ hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+ if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+ hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+ /* Programming the CRT detection parameters tends
+ to generate a spurious hotplug event about three
+ seconds later. So just do it once.
+ */
+ if (IS_G4X(dev))
+ hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+ hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+ }
+
+ /* Ignore TV since it's buggy */
+
+ I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+ }
+
opregion_enable_asle(dev);
return 0;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 64b0a3afd92b..cf41c672defe 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -178,6 +178,7 @@
#define MI_OVERLAY_OFF (0x2<<21)
#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2)
+#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1)
#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
@@ -358,6 +359,70 @@
#define LM_BURST_LENGTH 0x00000700
#define LM_FIFO_WATERMARK 0x0000001F
#define MI_ARB_STATE 0x020e4 /* 915+ only */
+#define MI_ARB_MASK_SHIFT 16 /* shift for enable bits */
+
+/* Make render/texture TLB fetches lower priorty than associated data
+ * fetches. This is not turned on by default
+ */
+#define MI_ARB_RENDER_TLB_LOW_PRIORITY (1 << 15)
+
+/* Isoch request wait on GTT enable (Display A/B/C streams).
+ * Make isoch requests stall on the TLB update. May cause
+ * display underruns (test mode only)
+ */
+#define MI_ARB_ISOCH_WAIT_GTT (1 << 14)
+
+/* Block grant count for isoch requests when block count is
+ * set to a finite value.
+ */
+#define MI_ARB_BLOCK_GRANT_MASK (3 << 12)
+#define MI_ARB_BLOCK_GRANT_8 (0 << 12) /* for 3 display planes */
+#define MI_ARB_BLOCK_GRANT_4 (1 << 12) /* for 2 display planes */
+#define MI_ARB_BLOCK_GRANT_2 (2 << 12) /* for 1 display plane */
+#define MI_ARB_BLOCK_GRANT_0 (3 << 12) /* don't use */
+
+/* Enable render writes to complete in C2/C3/C4 power states.
+ * If this isn't enabled, render writes are prevented in low
+ * power states. That seems bad to me.
+ */
+#define MI_ARB_C3_LP_WRITE_ENABLE (1 << 11)
+
+/* This acknowledges an async flip immediately instead
+ * of waiting for 2TLB fetches.
+ */
+#define MI_ARB_ASYNC_FLIP_ACK_IMMEDIATE (1 << 10)
+
+/* Enables non-sequential data reads through arbiter
+ */
+#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9)
+
+/* Disable FSB snooping of cacheable write cycles from binner/render
+ * command stream
+ */
+#define MI_ARB_CACHE_SNOOP_DISABLE (1 << 8)
+
+/* Arbiter time slice for non-isoch streams */
+#define MI_ARB_TIME_SLICE_MASK (7 << 5)
+#define MI_ARB_TIME_SLICE_1 (0 << 5)
+#define MI_ARB_TIME_SLICE_2 (1 << 5)
+#define MI_ARB_TIME_SLICE_4 (2 << 5)
+#define MI_ARB_TIME_SLICE_6 (3 << 5)
+#define MI_ARB_TIME_SLICE_8 (4 << 5)
+#define MI_ARB_TIME_SLICE_10 (5 << 5)
+#define MI_ARB_TIME_SLICE_14 (6 << 5)
+#define MI_ARB_TIME_SLICE_16 (7 << 5)
+
+/* Low priority grace period page size */
+#define MI_ARB_LOW_PRIORITY_GRACE_4KB (0 << 4) /* default */
+#define MI_ARB_LOW_PRIORITY_GRACE_8KB (1 << 4)
+
+/* Disable display A/B trickle feed */
+#define MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE (1 << 2)
+
+/* Set display plane priority */
+#define MI_ARB_DISPLAY_PRIORITY_A_B (0 << 0) /* display A > display B */
+#define MI_ARB_DISPLAY_PRIORITY_B_A (1 << 0) /* display B > display A */
+
#define CACHE_MODE_0 0x02120 /* 915+ only */
#define CM0_MASK_SHIFT 16
#define CM0_IZ_OPT_DISABLE (1<<6)
@@ -368,6 +433,9 @@
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
#define BB_ADDR 0x02140 /* 8 bytes */
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
+#define ECOSKPD 0x021d0
+#define ECO_GATING_CX_ONLY (1<<3)
+#define ECO_FLIP_DONE (1<<0)
/* GEN6 interrupt control */
#define GEN6_RENDER_HWSTAM 0x2098
@@ -1130,7 +1198,6 @@
#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
-#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
#define PORT_HOTPLUG_STAT 0x61114
#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
@@ -2802,6 +2869,7 @@
#define PCH_PP_STATUS 0xc7200
#define PCH_PP_CONTROL 0xc7204
+#define PANEL_UNLOCK_REGS (0xabcd << 16)
#define EDP_FORCE_VDD (1 << 3)
#define EDP_BLC_ENABLE (1 << 2)
#define PANEL_POWER_RESET (1 << 1)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 22ff38455731..ee0732b222a1 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -234,14 +234,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
else
tries = 1;
hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
- hotplug_en &= CRT_HOTPLUG_MASK;
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
- if (IS_G4X(dev))
- hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-
- hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
for (i = 0; i < tries ; i++) {
unsigned long timeout;
/* turn on the FORCE_DETECT */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cc8131ff319f..5e21b3119824 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -862,8 +862,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
intel_clock_t clock;
int max_n;
bool found;
- /* approximately equals target * 0.00488 */
- int err_most = (target >> 8) + (target >> 10);
+ /* approximately equals target * 0.00585 */
+ int err_most = (target >> 8) + (target >> 9);
found = false;
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
@@ -1180,8 +1180,12 @@ static void intel_update_fbc(struct drm_crtc *crtc,
struct drm_framebuffer *fb = crtc->fb;
struct intel_framebuffer *intel_fb;
struct drm_i915_gem_object *obj_priv;
+ struct drm_crtc *tmp_crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int plane = intel_crtc->plane;
+ int crtcs_enabled = 0;
+
+ DRM_DEBUG_KMS("\n");
if (!i915_powersave)
return;
@@ -1199,10 +1203,21 @@ static void intel_update_fbc(struct drm_crtc *crtc,
* If FBC is already on, we just have to verify that we can
* keep it that way...
* Need to disable if:
+ * - more than one pipe is active
* - changing FBC params (stride, fence, mode)
* - new fb is too large to fit in compressed buffer
* - going to an unsupported config (interlace, pixel multiply, etc.)
*/
+ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+ if (tmp_crtc->enabled)
+ crtcs_enabled++;
+ }
+ DRM_DEBUG_KMS("%d pipes active\n", crtcs_enabled);
+ if (crtcs_enabled > 1) {
+ DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
+ dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
+ goto out_disable;
+ }
if (intel_fb->obj->size > dev_priv->cfb_size) {
DRM_DEBUG_KMS("framebuffer too large, disabling "
"compression\n");
@@ -1255,7 +1270,7 @@ out_disable:
}
}
-static int
+int
intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
{
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
@@ -2255,6 +2270,11 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
intel_wait_for_vblank(dev);
}
+ /* Don't disable pipe A or pipe A PLLs if needed */
+ if (pipeconf_reg == PIPEACONF &&
+ (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+ goto skip_pipe_off;
+
/* Next, disable display pipes */
temp = I915_READ(pipeconf_reg);
if ((temp & PIPEACONF_ENABLE) != 0) {
@@ -2270,7 +2290,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
I915_READ(dpll_reg);
}
-
+ skip_pipe_off:
/* Wait for the clocks to turn off. */
udelay(150);
break;
@@ -2356,8 +2376,6 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
if (mode->clock * 3 > 27000 * 4)
return MODE_CLOCK_HIGH;
}
-
- drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
@@ -2970,11 +2988,13 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
if (srwm < 0)
srwm = 1;
srwm &= 0x3f;
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+ if (IS_I965GM(dev))
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
} else {
/* Turn off self refresh if both pipes are enabled */
- I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
- & ~FW_BLC_SELF_EN);
+ if (IS_I965GM(dev))
+ I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+ & ~FW_BLC_SELF_EN);
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@@ -3734,6 +3754,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
if (dev_priv->lvds_dither) {
if (HAS_PCH_SPLIT(dev)) {
pipeconf |= PIPE_ENABLE_DITHER;
+ pipeconf &= ~PIPE_DITHER_TYPE_MASK;
pipeconf |= PIPE_DITHER_TYPE_ST01;
} else
lvds |= LVDS_ENABLE_DITHER;
@@ -4410,7 +4431,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)
DRM_DEBUG_DRIVER("upclocking LVDS\n");
/* Unlock panel regs */
- I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
+ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+ PANEL_UNLOCK_REGS);
dpll &= ~DISPLAY_RATE_SELECT_FPA1;
I915_WRITE(dpll_reg, dpll);
@@ -4453,7 +4475,8 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
DRM_DEBUG_DRIVER("downclocking LVDS\n");
/* Unlock panel regs */
- I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
+ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+ PANEL_UNLOCK_REGS);
dpll |= DISPLAY_RATE_SELECT_FPA1;
I915_WRITE(dpll_reg, dpll);
@@ -4483,6 +4506,7 @@ static void intel_idle_update(struct work_struct *work)
struct drm_device *dev = dev_priv->dev;
struct drm_crtc *crtc;
struct intel_crtc *intel_crtc;
+ int enabled = 0;
if (!i915_powersave)
return;
@@ -4491,21 +4515,22 @@ static void intel_idle_update(struct work_struct *work)
i915_update_gfx_val(dev_priv);
- if (IS_I945G(dev) || IS_I945GM(dev)) {
- DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
- }
-
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
/* Skip inactive CRTCs */
if (!crtc->fb)
continue;
+ enabled++;
intel_crtc = to_intel_crtc(crtc);
if (!intel_crtc->busy)
intel_decrease_pllclock(crtc);
}
+ if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
+ DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
+ }
+
mutex_unlock(&dev->struct_mutex);
}
@@ -4601,10 +4626,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
kfree(work);
}
-void intel_finish_page_flip(struct drm_device *dev, int pipe)
+static void do_intel_finish_page_flip(struct drm_device *dev,
+ struct drm_crtc *crtc)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_unpin_work *work;
struct drm_i915_gem_object *obj_priv;
@@ -4648,6 +4673,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
schedule_work(&work->work);
}
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+
+ do_intel_finish_page_flip(dev, crtc);
+}
+
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
+
+ do_intel_finish_page_flip(dev, crtc);
+}
+
void intel_prepare_page_flip(struct drm_device *dev, int plane)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -4675,9 +4716,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
struct drm_gem_object *obj;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_unpin_work *work;
- unsigned long flags;
+ unsigned long flags, offset;
int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
int ret, pipesrc;
+ u32 flip_mask;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
@@ -4731,16 +4773,33 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
atomic_inc(&obj_priv->pending_flip);
work->pending_flip_obj = obj;
+ if (intel_crtc->plane)
+ flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+ else
+ flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+
+ /* Wait for any previous flip to finish */
+ if (IS_GEN3(dev))
+ while (I915_READ(ISR) & flip_mask)
+ ;
+
+ /* Offset into the new buffer for cases of shared fbs between CRTCs */
+ offset = obj_priv->gtt_offset;
+ offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8);
+
BEGIN_LP_RING(4);
- OUT_RING(MI_DISPLAY_FLIP |
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
- OUT_RING(fb->pitch);
if (IS_I965G(dev)) {
- OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
+ OUT_RING(MI_DISPLAY_FLIP |
+ MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+ OUT_RING(fb->pitch);
+ OUT_RING(offset | obj_priv->tiling_mode);
pipesrc = I915_READ(pipesrc_reg);
OUT_RING(pipesrc & 0x0fff0fff);
} else {
- OUT_RING(obj_priv->gtt_offset);
+ OUT_RING(MI_DISPLAY_FLIP_I915 |
+ MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+ OUT_RING(fb->pitch);
+ OUT_RING(offset);
OUT_RING(MI_NOOP);
}
ADVANCE_LP_RING();
@@ -5472,6 +5531,66 @@ static void intel_init_display(struct drm_device *dev)
}
}
+/*
+ * Some BIOSes insist on assuming the GPU's pipe A is enabled at suspend,
+ * resume, or other times. This quirk makes sure that's the case for
+ * affected systems.
+ */
+static void quirk_pipea_force (struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ dev_priv->quirks |= QUIRK_PIPEA_FORCE;
+ DRM_DEBUG_DRIVER("applying pipe a force quirk\n");
+}
+
+struct intel_quirk {
+ int device;
+ int subsystem_vendor;
+ int subsystem_device;
+ void (*hook)(struct drm_device *dev);
+};
+
+struct intel_quirk intel_quirks[] = {
+ /* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
+ { 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
+ /* HP Mini needs pipe A force quirk (LP: #322104) */
+ { 0x27ae,0x103c, 0x361a, quirk_pipea_force },
+
+ /* Thinkpad R31 needs pipe A force quirk */
+ { 0x3577, 0x1014, 0x0505, quirk_pipea_force },
+ /* Toshiba Protege R-205, S-209 needs pipe A force quirk */
+ { 0x2592, 0x1179, 0x0001, quirk_pipea_force },
+
+ /* ThinkPad X30 needs pipe A force quirk (LP: #304614) */
+ { 0x3577, 0x1014, 0x0513, quirk_pipea_force },
+ /* ThinkPad X40 needs pipe A force quirk */
+
+ /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
+ { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
+
+ /* 855 & before need to leave pipe A & dpll A up */
+ { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+ { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+};
+
+static void intel_init_quirks(struct drm_device *dev)
+{
+ struct pci_dev *d = dev->pdev;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) {
+ struct intel_quirk *q = &intel_quirks[i];
+
+ if (d->device == q->device &&
+ (d->subsystem_vendor == q->subsystem_vendor ||
+ q->subsystem_vendor == PCI_ANY_ID) &&
+ (d->subsystem_device == q->subsystem_device ||
+ q->subsystem_device == PCI_ANY_ID))
+ q->hook(dev);
+ }
+}
+
void intel_modeset_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5484,6 +5603,8 @@ void intel_modeset_init(struct drm_device *dev)
dev->mode_config.funcs = (void *)&intel_mode_funcs;
+ intel_init_quirks(dev);
+
intel_init_display(dev);
if (IS_I965G(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 49b54f05d3cf..5dde80f9e652 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -136,6 +136,12 @@ intel_dp_link_required(struct drm_device *dev,
}
static int
+intel_dp_max_data_rate(int max_link_clock, int max_lanes)
+{
+ return (max_link_clock * max_lanes * 8) / 10;
+}
+
+static int
intel_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
@@ -144,8 +150,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
int max_lanes = intel_dp_max_lane_count(intel_encoder);
- if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
- > max_link_clock * max_lanes)
+ /* only refuse the mode on non eDP since we have seen some wierd eDP panels
+ which are outside spec tolerances but somehow work by magic */
+ if (!IS_eDP(intel_encoder) &&
+ (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
+ > intel_dp_max_data_rate(max_link_clock, max_lanes)))
return MODE_CLOCK_HIGH;
if (mode->clock < 10000)
@@ -506,7 +515,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
for (clock = 0; clock <= max_clock; clock++) {
- int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+ int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
<= link_avail) {
@@ -521,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
}
}
}
+
+ if (IS_eDP(intel_encoder)) {
+ /* okay we failed just pick the highest */
+ dp_priv->lane_count = max_lane_count;
+ dp_priv->link_bw = bws[max_clock];
+ adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+ DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+ "count %d clock %d\n",
+ dp_priv->link_bw, dp_priv->lane_count,
+ adjusted_mode->clock);
+ return true;
+ }
return false;
}
@@ -696,6 +717,51 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
}
}
+static void ironlake_edp_panel_on (struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long timeout = jiffies + msecs_to_jiffies(5000);
+ u32 pp, pp_status;
+
+ pp_status = I915_READ(PCH_PP_STATUS);
+ if (pp_status & PP_ON)
+ return;
+
+ pp = I915_READ(PCH_PP_CONTROL);
+ pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ do {
+ pp_status = I915_READ(PCH_PP_STATUS);
+ } while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout));
+
+ if (time_after(jiffies, timeout))
+ DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status);
+
+ pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
+ I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void ironlake_edp_panel_off (struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long timeout = jiffies + msecs_to_jiffies(5000);
+ u32 pp, pp_status;
+
+ pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~POWER_TARGET_ON;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ do {
+ pp_status = I915_READ(PCH_PP_STATUS);
+ } while ((pp_status & PP_ON) && !time_after(jiffies, timeout));
+
+ if (time_after(jiffies, timeout))
+ DRM_DEBUG_KMS("panel off wait timed out\n");
+
+ /* Make sure VDD is enabled so DP AUX will work */
+ pp |= EDP_FORCE_VDD;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
static void ironlake_edp_backlight_on (struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -730,14 +796,18 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
if (mode != DRM_MODE_DPMS_ON) {
if (dp_reg & DP_PORT_EN) {
intel_dp_link_down(intel_encoder, dp_priv->DP);
- if (IS_eDP(intel_encoder))
+ if (IS_eDP(intel_encoder)) {
ironlake_edp_backlight_off(dev);
+ ironlake_edp_panel_off(dev);
+ }
}
} else {
if (!(dp_reg & DP_PORT_EN)) {
intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
- if (IS_eDP(intel_encoder))
+ if (IS_eDP(intel_encoder)) {
+ ironlake_edp_panel_on(dev);
ironlake_edp_backlight_on(dev);
+ }
}
}
dp_priv->dpms_mode = mode;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index df931f787665..2f7970be9051 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -215,6 +215,9 @@ extern void intel_init_clock_gating(struct drm_device *dev);
extern void ironlake_enable_drps(struct drm_device *dev);
extern void ironlake_disable_drps(struct drm_device *dev);
+extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
+ struct drm_gem_object *obj);
+
extern int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb,
struct drm_mode_fb_cmd *mode_cmd,
@@ -224,6 +227,7 @@ extern void intel_fbdev_fini(struct drm_device *dev);
extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
+extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
extern void intel_setup_overlay(struct drm_device *dev);
extern void intel_cleanup_overlay(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index c3c505244e07..3e18c9e7729b 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -98,7 +98,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
mutex_lock(&dev->struct_mutex);
- ret = i915_gem_object_pin(fbo, 64*1024);
+ ret = intel_pin_and_fence_fb_obj(dev, fbo);
if (ret) {
DRM_ERROR("failed to pin fb: %d\n", ret);
goto out_unref;
@@ -236,7 +236,7 @@ int intel_fbdev_destroy(struct drm_device *dev,
drm_framebuffer_cleanup(&ifb->base);
if (ifb->obj)
- drm_gem_object_unreference_unlocked(ifb->obj);
+ drm_gem_object_unreference(ifb->obj);
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 6a1accd83aec..0eab8df5bf7e 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -599,6 +599,26 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
return 0;
}
+static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
+{
+ DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident);
+ return 1;
+}
+
+/* The GPU hangs up on these systems if modeset is performed on LID open */
+static const struct dmi_system_id intel_no_modeset_on_lid[] = {
+ {
+ .callback = intel_no_modeset_on_lid_dmi_callback,
+ .ident = "Toshiba Tecra A11",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
+ },
+ },
+
+ { } /* terminating entry */
+};
+
/*
* Lid events. Note the use of 'modeset_on_lid':
* - we set it on lid close, and reset it on open
@@ -622,6 +642,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
*/
if (connector)
connector->status = connector->funcs->detect(connector);
+ /* Don't force modeset on machines where it causes a GPU lockup */
+ if (dmi_check_system(intel_no_modeset_on_lid))
+ return NOTIFY_OK;
if (!acpi_lid_open()) {
dev_priv->modeset_on_lid = 1;
return NOTIFY_OK;
@@ -983,8 +1006,8 @@ void intel_lvds_init(struct drm_device *dev)
drm_connector_attach_property(&intel_connector->base,
dev->mode_config.scaling_mode_property,
- DRM_MODE_SCALE_FULLSCREEN);
- lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
+ DRM_MODE_SCALE_ASPECT);
+ lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT;
/*
* LVDS discovery:
* 1) check for EDID on DDC
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index cea4f1a8709e..26362f8495a8 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -94,7 +94,7 @@ render_ring_flush(struct drm_device *dev,
#if WATCH_EXEC
DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
#endif
- intel_ring_begin(dev, ring, 8);
+ intel_ring_begin(dev, ring, 2);
intel_ring_emit(dev, ring, cmd);
intel_ring_emit(dev, ring, MI_NOOP);
intel_ring_advance(dev, ring);
@@ -358,7 +358,7 @@ bsd_ring_flush(struct drm_device *dev,
u32 invalidate_domains,
u32 flush_domains)
{
- intel_ring_begin(dev, ring, 8);
+ intel_ring_begin(dev, ring, 2);
intel_ring_emit(dev, ring, MI_FLUSH);
intel_ring_emit(dev, ring, MI_NOOP);
intel_ring_advance(dev, ring);
@@ -687,6 +687,7 @@ int intel_wrap_ring_buffer(struct drm_device *dev,
*virt++ = MI_NOOP;
ring->tail = 0;
+ ring->space = ring->head - 8;
return 0;
}
@@ -721,8 +722,9 @@ int intel_wait_ring_buffer(struct drm_device *dev,
}
void intel_ring_begin(struct drm_device *dev,
- struct intel_ring_buffer *ring, int n)
+ struct intel_ring_buffer *ring, int num_dwords)
{
+ int n = 4*num_dwords;
if (unlikely(ring->tail + n > ring->size))
intel_wrap_ring_buffer(dev, ring);
if (unlikely(ring->space < n))
@@ -752,7 +754,7 @@ void intel_fill_struct(struct drm_device *dev,
{
unsigned int *virt = ring->virtual_start + ring->tail;
BUG_ON((len&~(4-1)) != 0);
- intel_ring_begin(dev, ring, len);
+ intel_ring_begin(dev, ring, len/4);
memcpy(virt, data, len);
ring->tail += len;
ring->tail &= ring->size - 1;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index fc924b649195..e492919faf44 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -203,36 +203,26 @@ struct methods {
const bool rw;
};
-static struct methods nv04_methods[] = {
- { "PROM", load_vbios_prom, false },
- { "PRAMIN", load_vbios_pramin, true },
- { "PCIROM", load_vbios_pci, true },
-};
-
-static struct methods nv50_methods[] = {
- { "ACPI", load_vbios_acpi, true },
+static struct methods shadow_methods[] = {
{ "PRAMIN", load_vbios_pramin, true },
{ "PROM", load_vbios_prom, false },
{ "PCIROM", load_vbios_pci, true },
+ { "ACPI", load_vbios_acpi, true },
};
-#define METHODCNT 3
-
static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct methods *methods;
- int i;
+ const int nr_methods = ARRAY_SIZE(shadow_methods);
+ struct methods *methods = shadow_methods;
int testscore = 3;
- int scores[METHODCNT];
+ int scores[nr_methods], i;
if (nouveau_vbios) {
- methods = nv04_methods;
- for (i = 0; i < METHODCNT; i++)
+ for (i = 0; i < nr_methods; i++)
if (!strcasecmp(nouveau_vbios, methods[i].desc))
break;
- if (i < METHODCNT) {
+ if (i < nr_methods) {
NV_INFO(dev, "Attempting to use BIOS image from %s\n",
methods[i].desc);
@@ -244,12 +234,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios);
}
- if (dev_priv->card_type < NV_50)
- methods = nv04_methods;
- else
- methods = nv50_methods;
-
- for (i = 0; i < METHODCNT; i++) {
+ for (i = 0; i < nr_methods; i++) {
NV_TRACE(dev, "Attempting to load BIOS image from %s\n",
methods[i].desc);
data[0] = data[1] = 0; /* avoid reuse of previous image */
@@ -260,7 +245,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
}
while (--testscore > 0) {
- for (i = 0; i < METHODCNT; i++) {
+ for (i = 0; i < nr_methods; i++) {
if (scores[i] == testscore) {
NV_TRACE(dev, "Using BIOS image from %s\n",
methods[i].desc);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index c9a4a0d2a115..257ea130ae13 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -387,7 +387,8 @@ int nouveau_fbcon_init(struct drm_device *dev)
dev_priv->nfbdev = nfbdev;
nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
- ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
+ ret = drm_fb_helper_init(dev, &nfbdev->helper,
+ nv_two_heads(dev) ? 2 : 1, 4);
if (ret) {
kfree(nfbdev);
return ret;
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index f3f2827017ef..8c2d6478a221 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -498,7 +498,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if ((rdev->family == CHIP_RS600) ||
(rdev->family == CHIP_RS690) ||
(rdev->family == CHIP_RS740))
- pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+ pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
RADEON_PLL_PREFER_CLOSEST_LOWER);
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 4b6623df3b96..1caf625e472b 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -607,7 +607,7 @@ static void evergreen_mc_program(struct radeon_device *rdev)
WREG32(MC_VM_FB_LOCATION, tmp);
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
- WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
@@ -1222,11 +1222,11 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
ps_thread_count = 128;
sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count);
- sq_thread_resource_mgmt |= NUM_VS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt |= NUM_GS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt |= NUM_ES_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt_2 = NUM_HS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt_2 |= NUM_LS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
+ sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
@@ -1260,6 +1260,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
WREG32(VGT_GS_VERTEX_REUSE, 16);
WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
+ WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14);
+ WREG32(VGT_OUT_DEALLOC_CNTL, 16);
+
WREG32(CB_PERF_CTR0_SEL_0, 0);
WREG32(CB_PERF_CTR0_SEL_1, 0);
WREG32(CB_PERF_CTR1_SEL_0, 0);
@@ -1269,6 +1272,26 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
WREG32(CB_PERF_CTR3_SEL_0, 0);
WREG32(CB_PERF_CTR3_SEL_1, 0);
+ /* clear render buffer base addresses */
+ WREG32(CB_COLOR0_BASE, 0);
+ WREG32(CB_COLOR1_BASE, 0);
+ WREG32(CB_COLOR2_BASE, 0);
+ WREG32(CB_COLOR3_BASE, 0);
+ WREG32(CB_COLOR4_BASE, 0);
+ WREG32(CB_COLOR5_BASE, 0);
+ WREG32(CB_COLOR6_BASE, 0);
+ WREG32(CB_COLOR7_BASE, 0);
+ WREG32(CB_COLOR8_BASE, 0);
+ WREG32(CB_COLOR9_BASE, 0);
+ WREG32(CB_COLOR10_BASE, 0);
+ WREG32(CB_COLOR11_BASE, 0);
+
+ /* set the shader const cache sizes to 0 */
+ for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4)
+ WREG32(i, 0);
+ for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
+ WREG32(i, 0);
+
hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 64516b950891..345a75a03c96 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -333,7 +333,6 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
header = radeon_get_ib_value(p, h_idx);
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
reg = CP_PACKET0_GET_REG(header);
- mutex_lock(&p->rdev->ddev->mode_config.mutex);
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
@@ -368,7 +367,6 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
}
}
out:
- mutex_unlock(&p->rdev->ddev->mode_config.mutex);
return r;
}
@@ -1197,7 +1195,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad SET_RESOURCE (tex)\n");
return -EINVAL;
}
- ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
@@ -1209,7 +1207,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad SET_RESOURCE (tex)\n");
return -EINVAL;
}
- ib[idx+1+(i*8)+4] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
mipmap = reloc->robj;
r = evergreen_check_texture_resource(p, idx+1+(i*8),
texture, mipmap);
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 79683f6b4452..a1cd621780e2 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -713,6 +713,9 @@
#define SQ_GSVS_RING_OFFSET_2 0x28930
#define SQ_GSVS_RING_OFFSET_3 0x28934
+#define SQ_ALU_CONST_BUFFER_SIZE_PS_0 0x28140
+#define SQ_ALU_CONST_BUFFER_SIZE_HS_0 0x28f80
+
#define SQ_ALU_CONST_CACHE_PS_0 0x28940
#define SQ_ALU_CONST_CACHE_PS_1 0x28944
#define SQ_ALU_CONST_CACHE_PS_2 0x28948
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index cf89aa2eb28c..a89a15ab524d 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1230,7 +1230,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
header = radeon_get_ib_value(p, h_idx);
crtc_id = radeon_get_ib_value(p, h_idx + 5);
reg = CP_PACKET0_GET_REG(header);
- mutex_lock(&p->rdev->ddev->mode_config.mutex);
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
@@ -1264,7 +1263,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
}
out:
- mutex_unlock(&p->rdev->ddev->mode_config.mutex);
return r;
}
@@ -1628,6 +1626,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
case RADEON_TXFORMAT_RGB332:
case RADEON_TXFORMAT_Y8:
track->textures[i].cpp = 1;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case RADEON_TXFORMAT_AI88:
case RADEON_TXFORMAT_ARGB1555:
@@ -1639,12 +1638,14 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
case RADEON_TXFORMAT_LDUDV655:
case RADEON_TXFORMAT_DUDV88:
track->textures[i].cpp = 2;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case RADEON_TXFORMAT_ARGB8888:
case RADEON_TXFORMAT_RGBA8888:
case RADEON_TXFORMAT_SHADOW32:
case RADEON_TXFORMAT_LDUDUV8888:
track->textures[i].cpp = 4;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case RADEON_TXFORMAT_DXT1:
track->textures[i].cpp = 1;
@@ -2351,6 +2352,7 @@ void r100_mc_init(struct radeon_device *rdev)
if (rdev->flags & RADEON_IS_IGP)
base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
radeon_vram_location(rdev, &rdev->mc, base);
+ rdev->mc.gtt_base_align = 0;
if (!(rdev->flags & RADEON_IS_AGP))
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
@@ -2604,12 +2606,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
int surf_index = reg * 16;
int flags = 0;
- /* r100/r200 divide by 16 */
- if (rdev->family < CHIP_R300)
- flags = pitch / 16;
- else
- flags = pitch / 8;
-
if (rdev->family <= CHIP_RS200) {
if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
== (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
@@ -2633,6 +2629,20 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
if (tiling_flags & RADEON_TILING_SWAP_32BIT)
flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
+ /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */
+ if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) {
+ if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)))
+ if (ASIC_IS_RN50(rdev))
+ pitch /= 16;
+ }
+
+ /* r100/r200 divide by 16 */
+ if (rdev->family < CHIP_R300)
+ flags |= pitch / 16;
+ else
+ flags |= pitch / 8;
+
+
DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
@@ -3147,33 +3157,6 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
DRM_ERROR("compress format %d\n", t->compress_format);
}
-static int r100_cs_track_cube(struct radeon_device *rdev,
- struct r100_cs_track *track, unsigned idx)
-{
- unsigned face, w, h;
- struct radeon_bo *cube_robj;
- unsigned long size;
-
- for (face = 0; face < 5; face++) {
- cube_robj = track->textures[idx].cube_info[face].robj;
- w = track->textures[idx].cube_info[face].width;
- h = track->textures[idx].cube_info[face].height;
-
- size = w * h;
- size *= track->textures[idx].cpp;
-
- size += track->textures[idx].cube_info[face].offset;
-
- if (size > radeon_bo_size(cube_robj)) {
- DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
- size, radeon_bo_size(cube_robj));
- r100_cs_track_texture_print(&track->textures[idx]);
- return -1;
- }
- }
- return 0;
-}
-
static int r100_track_compress_size(int compress_format, int w, int h)
{
int block_width, block_height, block_bytes;
@@ -3204,6 +3187,37 @@ static int r100_track_compress_size(int compress_format, int w, int h)
return sz;
}
+static int r100_cs_track_cube(struct radeon_device *rdev,
+ struct r100_cs_track *track, unsigned idx)
+{
+ unsigned face, w, h;
+ struct radeon_bo *cube_robj;
+ unsigned long size;
+ unsigned compress_format = track->textures[idx].compress_format;
+
+ for (face = 0; face < 5; face++) {
+ cube_robj = track->textures[idx].cube_info[face].robj;
+ w = track->textures[idx].cube_info[face].width;
+ h = track->textures[idx].cube_info[face].height;
+
+ if (compress_format) {
+ size = r100_track_compress_size(compress_format, w, h);
+ } else
+ size = w * h;
+ size *= track->textures[idx].cpp;
+
+ size += track->textures[idx].cube_info[face].offset;
+
+ if (size > radeon_bo_size(cube_robj)) {
+ DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
+ size, radeon_bo_size(cube_robj));
+ r100_cs_track_texture_print(&track->textures[idx]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
static int r100_cs_track_texture_check(struct radeon_device *rdev,
struct r100_cs_track *track)
{
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
index 85617c311212..0266d72e0a4c 100644
--- a/drivers/gpu/drm/radeon/r200.c
+++ b/drivers/gpu/drm/radeon/r200.c
@@ -415,6 +415,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
/* 2D, 3D, CUBE */
switch (tmp) {
case 0:
+ case 3:
+ case 4:
case 5:
case 6:
case 7:
@@ -450,6 +452,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_TXFORMAT_RGB332:
case R200_TXFORMAT_Y8:
track->textures[i].cpp = 1;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R200_TXFORMAT_AI88:
case R200_TXFORMAT_ARGB1555:
@@ -461,6 +464,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_TXFORMAT_DVDU88:
case R200_TXFORMAT_AVYU4444:
track->textures[i].cpp = 2;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R200_TXFORMAT_ARGB8888:
case R200_TXFORMAT_RGBA8888:
@@ -468,6 +472,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_TXFORMAT_BGR111110:
case R200_TXFORMAT_LDVDU8888:
track->textures[i].cpp = 4;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R200_TXFORMAT_DXT1:
track->textures[i].cpp = 1;
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index b2f9efe2897c..19a7ef7ee344 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -481,6 +481,7 @@ void r300_mc_init(struct radeon_device *rdev)
if (rdev->flags & RADEON_IS_IGP)
base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
radeon_vram_location(rdev, &rdev->mc, base);
+ rdev->mc.gtt_base_align = 0;
if (!(rdev->flags & RADEON_IS_AGP))
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
@@ -881,6 +882,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case R300_TX_FORMAT_Y4X4:
case R300_TX_FORMAT_Z3Y3X2:
track->textures[i].cpp = 1;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_X16:
case R300_TX_FORMAT_Y8X8:
@@ -892,6 +894,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case R300_TX_FORMAT_B8G8_B8G8:
case R300_TX_FORMAT_G8R8_G8B8:
track->textures[i].cpp = 2;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_Y16X16:
case R300_TX_FORMAT_Z11Y11X10:
@@ -902,14 +905,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case R300_TX_FORMAT_FL_I32:
case 0x1e:
track->textures[i].cpp = 4;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_W16Z16Y16X16:
case R300_TX_FORMAT_FL_R16G16B16A16:
case R300_TX_FORMAT_FL_I32A32:
track->textures[i].cpp = 8;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_FL_R32G32B32A32:
track->textures[i].cpp = 16;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_DXT1:
track->textures[i].cpp = 1;
@@ -1171,6 +1177,8 @@ int r300_cs_parse(struct radeon_cs_parser *p)
int r;
track = kzalloc(sizeof(*track), GFP_KERNEL);
+ if (track == NULL)
+ return -ENOMEM;
r100_cs_track_clear(p->rdev, track);
p->track = track;
do {
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
index 34330df28483..694af7cc23ac 100644
--- a/drivers/gpu/drm/radeon/r520.c
+++ b/drivers/gpu/drm/radeon/r520.c
@@ -125,6 +125,7 @@ void r520_mc_init(struct radeon_device *rdev)
r520_vram_get_type(rdev);
r100_vram_init_sizes(rdev);
radeon_vram_location(rdev, &rdev->mc, 0);
+ rdev->mc.gtt_base_align = 0;
if (!(rdev->flags & RADEON_IS_AGP))
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 0e91871f45be..e100f69faeec 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -130,9 +130,14 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev)
break;
}
}
- } else
- rdev->pm.requested_power_state_index =
- rdev->pm.current_power_state_index - 1;
+ } else {
+ if (rdev->pm.current_power_state_index == 0)
+ rdev->pm.requested_power_state_index =
+ rdev->pm.num_power_states - 1;
+ else
+ rdev->pm.requested_power_state_index =
+ rdev->pm.current_power_state_index - 1;
+ }
}
rdev->pm.requested_clock_mode_index = 0;
/* don't use the power state if crtcs are active and no display flag is set */
@@ -1097,7 +1102,7 @@ static void r600_mc_program(struct radeon_device *rdev)
WREG32(MC_VM_FB_LOCATION, tmp);
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
- WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF);
+ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22);
@@ -1174,6 +1179,7 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
if (rdev->flags & RADEON_IS_IGP)
base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
radeon_vram_location(rdev, &rdev->mc, base);
+ rdev->mc.gtt_base_align = 0;
radeon_gtt_location(rdev, mc);
}
}
@@ -1219,8 +1225,10 @@ int r600_mc_init(struct radeon_device *rdev)
rdev->mc.visible_vram_size = rdev->mc.aper_size;
r600_vram_gtt_location(rdev, &rdev->mc);
- if (rdev->flags & RADEON_IS_IGP)
+ if (rdev->flags & RADEON_IS_IGP) {
+ rs690_pm_info(rdev);
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+ }
radeon_update_bandwidth_info(rdev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c
index f4fb88ece2bb..ca5c29f70779 100644
--- a/drivers/gpu/drm/radeon/r600_blit.c
+++ b/drivers/gpu/drm/radeon/r600_blit.c
@@ -538,9 +538,12 @@ int
r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
+ int ret;
DRM_DEBUG("\n");
- r600_nomm_get_vb(dev);
+ ret = r600_nomm_get_vb(dev);
+ if (ret)
+ return ret;
dev_priv->blit_vb->file_priv = file_priv;
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index c39c1bc13016..144c32d37136 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -585,7 +585,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
header = radeon_get_ib_value(p, h_idx);
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
reg = CP_PACKET0_GET_REG(header);
- mutex_lock(&p->rdev->ddev->mode_config.mutex);
+
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
@@ -620,7 +620,6 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
}
out:
- mutex_unlock(&p->rdev->ddev->mode_config.mutex);
return r;
}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8e1d44ca26ec..2f94dc66c183 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -177,6 +177,7 @@ void radeon_pm_resume(struct radeon_device *rdev);
void radeon_combios_get_power_modes(struct radeon_device *rdev);
void radeon_atombios_get_power_modes(struct radeon_device *rdev);
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
+void rs690_pm_info(struct radeon_device *rdev);
/*
* Fences.
@@ -350,6 +351,7 @@ struct radeon_mc {
int vram_mtrr;
bool vram_is_ddr;
bool igp_sideport_enabled;
+ u64 gtt_base_align;
};
bool radeon_combios_sideport_present(struct radeon_device *rdev);
@@ -619,7 +621,8 @@ enum radeon_dynpm_state {
DYNPM_STATE_DISABLED,
DYNPM_STATE_MINIMUM,
DYNPM_STATE_PAUSED,
- DYNPM_STATE_ACTIVE
+ DYNPM_STATE_ACTIVE,
+ DYNPM_STATE_SUSPENDED,
};
enum radeon_dynpm_action {
DYNPM_ACTION_NONE,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 87f7e2cc52d4..646f96f97c77 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -780,6 +780,13 @@ int radeon_asic_init(struct radeon_device *rdev)
case CHIP_R423:
case CHIP_RV410:
rdev->asic = &r420_asic;
+ /* handle macs */
+ if (rdev->bios == NULL) {
+ rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock;
+ rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock;
+ rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock;
+ rdev->asic->set_memory_clock = NULL;
+ }
break;
case CHIP_RS400:
case CHIP_RS480:
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 99bd8a9c56b3..10673ae59cfa 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -280,6 +280,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
}
}
+ /* ASUS HD 3600 board lists the DVI port as HDMI */
+ if ((dev->pdev->device == 0x9598) &&
+ (dev->pdev->subsystem_vendor == 0x1043) &&
+ (dev->pdev->subsystem_device == 0x01e4)) {
+ if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+ *connector_type = DRM_MODE_CONNECTOR_DVII;
+ }
+ }
+
/* ASUS HD 3450 board lists the DVI port as HDMI */
if ((dev->pdev->device == 0x95C5) &&
(dev->pdev->subsystem_vendor == 0x1043) &&
@@ -1029,8 +1038,15 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
data_offset);
switch (crev) {
case 1:
- if (igp_info->info.ucMemoryType & 0xf0)
- return true;
+ /* AMD IGPS */
+ if ((rdev->family == CHIP_RS690) ||
+ (rdev->family == CHIP_RS740)) {
+ if (igp_info->info.ulBootUpMemoryClock)
+ return true;
+ } else {
+ if (igp_info->info.ucMemoryType & 0xf0)
+ return true;
+ }
break;
case 2:
if (igp_info->info_2.ucMemoryType & 0x0f)
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index fbba938f8048..2c9213739999 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -48,6 +48,10 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
resource_size_t vram_base;
resource_size_t size = 256 * 1024; /* ??? */
+ if (!(rdev->flags & RADEON_IS_IGP))
+ if (!radeon_card_posted(rdev))
+ return false;
+
rdev->bios = NULL;
vram_base = drm_get_resource_start(rdev->ddev, 0);
bios = ioremap(vram_base, size);
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 1bee2f9e24a5..2417d7b06fdb 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -1411,6 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
} else
#endif /* CONFIG_PPC_PMAC */
+#ifdef CONFIG_PPC64
+ if (ASIC_IS_RN50(rdev))
+ rdev->mode_info.connector_table = CT_RN50_POWER;
+ else
+#endif
rdev->mode_info.connector_table = CT_GENERIC;
}
@@ -1853,6 +1858,33 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
CONNECTOR_OBJECT_ID_SVIDEO,
&hpd);
break;
+ case CT_RN50_POWER:
+ DRM_INFO("Connector Table: %d (rn50-power)\n",
+ rdev->mode_info.connector_table);
+ /* VGA - primary dac */
+ ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+ hpd.hpd = RADEON_HPD_NONE;
+ radeon_add_legacy_encoder(dev,
+ radeon_get_encoder_id(dev,
+ ATOM_DEVICE_CRT1_SUPPORT,
+ 1),
+ ATOM_DEVICE_CRT1_SUPPORT);
+ radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
+ DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+ CONNECTOR_OBJECT_ID_VGA,
+ &hpd);
+ ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+ hpd.hpd = RADEON_HPD_NONE;
+ radeon_add_legacy_encoder(dev,
+ radeon_get_encoder_id(dev,
+ ATOM_DEVICE_CRT2_SUPPORT,
+ 2),
+ ATOM_DEVICE_CRT2_SUPPORT);
+ radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+ DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+ CONNECTOR_OBJECT_ID_VGA,
+ &hpd);
+ break;
default:
DRM_INFO("Connector table: %d (invalid)\n",
rdev->mode_info.connector_table);
@@ -1906,15 +1938,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
return false;
}
- /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */
- if (dev->pdev->device == 0x5159 &&
- dev->pdev->subsystem_vendor == 0x1002 &&
- dev->pdev->subsystem_device == 0x013a) {
- if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
- *legacy_connector = CONNECTOR_CRT_LEGACY;
-
- }
-
/* X300 card with extra non-existent DVI port */
if (dev->pdev->device == 0x5B60 &&
dev->pdev->subsystem_vendor == 0x17af &&
@@ -3019,6 +3042,22 @@ void radeon_combios_asic_init(struct drm_device *dev)
combios_write_ram_size(dev);
}
+ /* quirk for rs4xx HP nx6125 laptop to make it resume
+ * - it hangs on resume inside the dynclk 1 table.
+ */
+ if (rdev->family == CHIP_RS480 &&
+ rdev->pdev->subsystem_vendor == 0x103c &&
+ rdev->pdev->subsystem_device == 0x308b)
+ return;
+
+ /* quirk for rs4xx HP dv5000 laptop to make it resume
+ * - it hangs on resume inside the dynclk 1 table.
+ */
+ if (rdev->family == CHIP_RS480 &&
+ rdev->pdev->subsystem_vendor == 0x103c &&
+ rdev->pdev->subsystem_device == 0x30a4)
+ return;
+
/* DYN CLK 1 */
table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
if (table)
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 0c7ccc6961a3..adccbc2c202c 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -771,30 +771,27 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
} else
ret = connector_status_connected;
- /* multiple connectors on the same encoder with the same ddc line
- * This tends to be HDMI and DVI on the same encoder with the
- * same ddc line. If the edid says HDMI, consider the HDMI port
- * connected and the DVI port disconnected. If the edid doesn't
- * say HDMI, vice versa.
+ /* This gets complicated. We have boards with VGA + HDMI with a
+ * shared DDC line and we have boards with DVI-D + HDMI with a shared
+ * DDC line. The latter is more complex because with DVI<->HDMI adapters
+ * you don't really know what's connected to which port as both are digital.
*/
if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
struct drm_device *dev = connector->dev;
+ struct radeon_device *rdev = dev->dev_private;
struct drm_connector *list_connector;
struct radeon_connector *list_radeon_connector;
list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
if (connector == list_connector)
continue;
list_radeon_connector = to_radeon_connector(list_connector);
- if (radeon_connector->devices == list_radeon_connector->devices) {
- if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
- if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
- ret = connector_status_disconnected;
- }
- } else {
- if ((connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) ||
- (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) {
+ if (list_radeon_connector->shared_ddc &&
+ (list_radeon_connector->ddc_bus->rec.i2c_id ==
+ radeon_connector->ddc_bus->rec.i2c_id)) {
+ /* cases where both connectors are digital */
+ if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
+ /* hpd is our only option in this case */
+ if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
ret = connector_status_disconnected;
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index b7023fff89eb..4eb67c0e0996 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -194,7 +194,7 @@ unpin:
fail:
drm_gem_object_unreference_unlocked(obj);
- return 0;
+ return ret;
}
int radeon_crtc_cursor_move(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index f10faed21567..dd279da90546 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -226,20 +226,20 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
{
u64 size_af, size_bf;
- size_af = 0xFFFFFFFF - mc->vram_end;
- size_bf = mc->vram_start;
+ size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align;
+ size_bf = mc->vram_start & ~mc->gtt_base_align;
if (size_bf > size_af) {
if (mc->gtt_size > size_bf) {
dev_warn(rdev->dev, "limiting GTT\n");
mc->gtt_size = size_bf;
}
- mc->gtt_start = mc->vram_start - mc->gtt_size;
+ mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size;
} else {
if (mc->gtt_size > size_af) {
dev_warn(rdev->dev, "limiting GTT\n");
mc->gtt_size = size_af;
}
- mc->gtt_start = mc->vram_end + 1;
+ mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align;
}
mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
@@ -779,6 +779,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
int radeon_resume_kms(struct drm_device *dev)
{
+ struct drm_connector *connector;
struct radeon_device *rdev = dev->dev_private;
if (rdev->powered_down)
@@ -797,6 +798,12 @@ int radeon_resume_kms(struct drm_device *dev)
radeon_resume(rdev);
radeon_pm_resume(rdev);
radeon_restore_bios_scratch_regs(rdev);
+
+ /* turn on display hw */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ }
+
radeon_fbdev_set_suspend(rdev, 0);
release_console_sem();
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 1ebb100015b7..e0b30b264c28 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -1072,6 +1072,8 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
if (is_dig) {
switch (mode) {
case DRM_MODE_DPMS_ON:
+ if (!ASIC_IS_DCE4(rdev))
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
@@ -1079,8 +1081,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
}
- if (!ASIC_IS_DCE4(rdev))
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 6a70c0dc7f92..ab389f89fa8d 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -128,7 +128,8 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
for (i = 0, found = 0; i < rdev->num_crtc; i++) {
crtc = (struct drm_crtc *)minfo->crtcs[i];
if (crtc && crtc->base.id == value) {
- value = i;
+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+ value = radeon_crtc->crtc_id;
found = 1;
break;
}
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 5b07b8848e09..5688a0cf6bbe 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -108,6 +108,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
udelay(panel_pwr_delay * 1000);
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
+ udelay(panel_pwr_delay * 1000);
break;
}
@@ -928,16 +929,14 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
if (ASIC_IS_R300(rdev)) {
gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
- }
-
- if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
- disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
- else
+ } else if (rdev->family != CHIP_R200)
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
-
- if (rdev->family == CHIP_R200)
+ else if (rdev->family == CHIP_R200)
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+ if (rdev->family >= CHIP_R200)
+ disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
+
if (is_tv) {
uint32_t dac_cntl;
@@ -1002,15 +1001,13 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
if (ASIC_IS_R300(rdev)) {
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
- }
+ } else if (rdev->family != CHIP_R200)
+ WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+ else if (rdev->family == CHIP_R200)
+ WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
if (rdev->family >= CHIP_R200)
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
- else
- WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-
- if (rdev->family == CHIP_R200)
- WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
if (is_tv)
radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c
index f2ed27c8055b..032040397743 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c
@@ -642,8 +642,8 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
}
flicker_removal = (tmp + 500) / 1000;
- if (flicker_removal < 2)
- flicker_removal = 2;
+ if (flicker_removal < 3)
+ flicker_removal = 3;
for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {
if (flicker_removal == SLOPE_limit[i])
break;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 67358baf28b2..95696aa57ac8 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -206,6 +206,7 @@ enum radeon_connector_table {
CT_MINI_INTERNAL,
CT_IMAC_G5_ISIGHT,
CT_EMAC,
+ CT_RN50_POWER,
};
enum radeon_dvo_chip {
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 63f679a04b25..3fa6984d9896 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -333,6 +333,7 @@ static ssize_t radeon_get_pm_profile(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n",
(cp == PM_PROFILE_AUTO) ? "auto" :
(cp == PM_PROFILE_LOW) ? "low" :
+ (cp == PM_PROFILE_MID) ? "mid" :
(cp == PM_PROFILE_HIGH) ? "high" : "default");
}
@@ -397,13 +398,20 @@ static ssize_t radeon_set_pm_method(struct device *dev,
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
mutex_unlock(&rdev->pm.mutex);
} else if (strncmp("profile", buf, strlen("profile")) == 0) {
+ bool flush_wq = false;
+
mutex_lock(&rdev->pm.mutex);
- rdev->pm.pm_method = PM_METHOD_PROFILE;
+ if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ flush_wq = true;
+ }
/* disable dynpm */
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
- cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ rdev->pm.pm_method = PM_METHOD_PROFILE;
mutex_unlock(&rdev->pm.mutex);
+ if (flush_wq)
+ flush_workqueue(rdev->wq);
} else {
DRM_ERROR("invalid power method!\n");
goto fail;
@@ -418,9 +426,18 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon
void radeon_pm_suspend(struct radeon_device *rdev)
{
+ bool flush_wq = false;
+
mutex_lock(&rdev->pm.mutex);
- cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+ rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+ flush_wq = true;
+ }
mutex_unlock(&rdev->pm.mutex);
+ if (flush_wq)
+ flush_workqueue(rdev->wq);
}
void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +449,12 @@ void radeon_pm_resume(struct radeon_device *rdev)
rdev->pm.current_sclk = rdev->clock.default_sclk;
rdev->pm.current_mclk = rdev->clock.default_mclk;
rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+ if (rdev->pm.pm_method == PM_METHOD_DYNPM
+ && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+ rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+ queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+ msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+ }
mutex_unlock(&rdev->pm.mutex);
radeon_pm_compute_clocks(rdev);
}
@@ -486,6 +509,8 @@ int radeon_pm_init(struct radeon_device *rdev)
void radeon_pm_fini(struct radeon_device *rdev)
{
if (rdev->pm.num_power_states > 1) {
+ bool flush_wq = false;
+
mutex_lock(&rdev->pm.mutex);
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +518,16 @@ void radeon_pm_fini(struct radeon_device *rdev)
radeon_pm_set_clocks(rdev);
} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
/* cancel work */
- cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ flush_wq = true;
/* reset default clocks */
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
radeon_pm_set_clocks(rdev);
}
mutex_unlock(&rdev->pm.mutex);
+ if (flush_wq)
+ flush_workqueue(rdev->wq);
device_remove_file(rdev->dev, &dev_attr_power_profile);
device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +748,12 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
radeon_pm_get_dynpm_state(rdev);
radeon_pm_set_clocks(rdev);
}
+
+ queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+ msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
}
mutex_unlock(&rdev->pm.mutex);
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
- queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
- msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
}
/*
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
index b5c757f68d3c..f78fd592544d 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen
+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen
@@ -80,8 +80,8 @@ evergreen 0x9400
0x00028010 DB_RENDER_OVERRIDE2
0x00028028 DB_STENCIL_CLEAR
0x0002802C DB_DEPTH_CLEAR
-0x00028034 PA_SC_SCREEN_SCISSOR_BR
0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
0x0002805C DB_DEPTH_SLICE
0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
@@ -460,8 +460,8 @@ evergreen 0x9400
0x00028844 SQ_PGM_RESOURCES_PS
0x00028848 SQ_PGM_RESOURCES_2_PS
0x0002884C SQ_PGM_EXPORTS_PS
-0x0002885C SQ_PGM_RESOURCES_VS
-0x00028860 SQ_PGM_RESOURCES_2_VS
+0x00028860 SQ_PGM_RESOURCES_VS
+0x00028864 SQ_PGM_RESOURCES_2_VS
0x00028878 SQ_PGM_RESOURCES_GS
0x0002887C SQ_PGM_RESOURCES_2_GS
0x00028890 SQ_PGM_RESOURCES_ES
@@ -469,8 +469,8 @@ evergreen 0x9400
0x000288A8 SQ_PGM_RESOURCES_FS
0x000288BC SQ_PGM_RESOURCES_HS
0x000288C0 SQ_PGM_RESOURCES_2_HS
-0x000288D0 SQ_PGM_RESOURCES_LS
-0x000288D4 SQ_PGM_RESOURCES_2_LS
+0x000288D4 SQ_PGM_RESOURCES_LS
+0x000288D8 SQ_PGM_RESOURCES_2_LS
0x000288E8 SQ_LDS_ALLOC
0x000288EC SQ_LDS_ALLOC_PS
0x000288F0 SQ_VTX_SEMANTIC_CLEAR
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index 9e4240b3bf0b..f454c9a5e7f2 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -57,7 +57,9 @@ void rs400_gart_adjust_size(struct radeon_device *rdev)
}
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) {
/* FIXME: RS400 & RS480 seems to have issue with GART size
- * if 4G of system memory (needs more testing) */
+ * if 4G of system memory (needs more testing)
+ */
+ /* XXX is this still an issue with proper alignment? */
rdev->mc.gtt_size = 32 * 1024 * 1024;
DRM_ERROR("Forcing to 32M GART size (because of ASIC bug ?)\n");
}
@@ -263,6 +265,7 @@ void rs400_mc_init(struct radeon_device *rdev)
r100_vram_init_sizes(rdev);
base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
radeon_vram_location(rdev, &rdev->mc, base);
+ rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1;
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
}
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 7bb4c3e52f3b..6dc15ea8ba33 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -698,6 +698,7 @@ void rs600_mc_init(struct radeon_device *rdev)
base = G_000004_MC_FB_START(base) << 16;
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
radeon_vram_location(rdev, &rdev->mc, base);
+ rdev->mc.gtt_base_align = 0;
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
}
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index bcc33195ebc2..ce4ecbe10816 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -79,7 +79,13 @@ void rs690_pm_info(struct radeon_device *rdev)
tmp.full = dfixed_const(100);
rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
- rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+ if (info->info.usK8MemoryClock)
+ rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+ else if (rdev->clock.default_mclk) {
+ rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+ rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
+ } else
+ rdev->pm.igp_system_mclk.full = dfixed_const(400);
rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock));
rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth);
break;
@@ -87,34 +93,31 @@ void rs690_pm_info(struct radeon_device *rdev)
tmp.full = dfixed_const(100);
rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
- rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+ if (info->info_v2.ulBootUpUMAClock)
+ rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+ else if (rdev->clock.default_mclk)
+ rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+ else
+ rdev->pm.igp_system_mclk.full = dfixed_const(66700);
rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);
rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
break;
default:
- tmp.full = dfixed_const(100);
/* We assume the slower possible clock ie worst case */
- /* DDR 333Mhz */
- rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
- /* FIXME: system clock ? */
- rdev->pm.igp_system_mclk.full = dfixed_const(100);
- rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
- rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+ rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+ rdev->pm.igp_system_mclk.full = dfixed_const(200);
+ rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
rdev->pm.igp_ht_link_width.full = dfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
}
} else {
- tmp.full = dfixed_const(100);
/* We assume the slower possible clock ie worst case */
- /* DDR 333Mhz */
- rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
- /* FIXME: system clock ? */
- rdev->pm.igp_system_mclk.full = dfixed_const(100);
- rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
- rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+ rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+ rdev->pm.igp_system_mclk.full = dfixed_const(200);
+ rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
rdev->pm.igp_ht_link_width.full = dfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
}
@@ -159,6 +162,7 @@ void rs690_mc_init(struct radeon_device *rdev)
rs690_pm_info(rdev);
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
radeon_vram_location(rdev, &rdev->mc, base);
+ rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1;
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
}
@@ -228,10 +232,6 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
- /* FIXME: detect IGP with sideport memory, i don't think there is any
- * such product available
- */
- bool sideport = false;
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
@@ -300,7 +300,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
/* Maximun bandwidth is the minimun bandwidth of all component */
rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
- if (sideport) {
+ if (rdev->mc.igp_sideport_enabled) {
if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
rdev->pm.sideport_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 7d9a7b0a180a..0c9c169a6852 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -195,6 +195,7 @@ void rv515_mc_init(struct radeon_device *rdev)
rv515_vram_get_type(rdev);
r100_vram_init_sizes(rdev);
radeon_vram_location(rdev, &rdev->mc, 0);
+ rdev->mc.gtt_base_align = 0;
if (!(rdev->flags & RADEON_IS_AGP))
radeon_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index cec536c222c5..b7fd82064922 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -224,7 +224,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
WREG32(MC_VM_FB_LOCATION, tmp);
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
- WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index ef910694bd63..ca904799f018 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -40,11 +40,13 @@
#include <linux/slab.h>
#include <asm/atomic.h>
-#include <asm/agp.h>
#include "ttm/ttm_bo_driver.h"
#include "ttm/ttm_page_alloc.h"
+#ifdef TTM_HAS_AGP
+#include <asm/agp.h>
+#endif
#define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *))
#define SMALL_ALLOCATION 16
@@ -104,7 +106,6 @@ struct ttm_pool_opts {
struct ttm_pool_manager {
struct kobject kobj;
struct shrinker mm_shrink;
- atomic_t page_alloc_inited;
struct ttm_pool_opts options;
union {
@@ -142,7 +143,7 @@ static void ttm_pool_kobj_release(struct kobject *kobj)
{
struct ttm_pool_manager *m =
container_of(kobj, struct ttm_pool_manager, kobj);
- (void)m;
+ kfree(m);
}
static ssize_t ttm_pool_store(struct kobject *kobj,
@@ -214,9 +215,7 @@ static struct kobj_type ttm_pool_kobj_type = {
.default_attrs = ttm_pool_attrs,
};
-static struct ttm_pool_manager _manager = {
- .page_alloc_inited = ATOMIC_INIT(0)
-};
+static struct ttm_pool_manager *_manager;
#ifndef CONFIG_X86
static int set_pages_array_wb(struct page **pages, int addrinarray)
@@ -271,7 +270,7 @@ static struct ttm_page_pool *ttm_get_pool(int flags,
if (flags & TTM_PAGE_FLAG_DMA32)
pool_index |= 0x2;
- return &_manager.pools[pool_index];
+ return &_manager->pools[pool_index];
}
/* set memory back to wb and free the pages. */
@@ -387,7 +386,7 @@ static int ttm_pool_get_num_unused_pages(void)
unsigned i;
int total = 0;
for (i = 0; i < NUM_POOLS; ++i)
- total += _manager.pools[i].npages;
+ total += _manager->pools[i].npages;
return total;
}
@@ -395,7 +394,7 @@ static int ttm_pool_get_num_unused_pages(void)
/**
* Callback for mm to request pool to reduce number of page held.
*/
-static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
+static int ttm_pool_mm_shrink(struct shrinker *shrink, int shrink_pages, gfp_t gfp_mask)
{
static atomic_t start_pool = ATOMIC_INIT(0);
unsigned i;
@@ -408,7 +407,7 @@ static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
unsigned nr_free = shrink_pages;
if (shrink_pages == 0)
break;
- pool = &_manager.pools[(i + pool_offset)%NUM_POOLS];
+ pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
shrink_pages = ttm_page_pool_free(pool, nr_free);
}
/* return estimated number of unused pages in pool */
@@ -576,10 +575,10 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
/* If allocation request is small and there is not enough
* pages in pool we fill the pool first */
- if (count < _manager.options.small
+ if (count < _manager->options.small
&& count > pool->npages) {
struct list_head new_pages;
- unsigned alloc_size = _manager.options.alloc_size;
+ unsigned alloc_size = _manager->options.alloc_size;
/**
* Can't change page caching if in irqsave context. We have to
@@ -667,7 +666,7 @@ int ttm_get_pages(struct list_head *pages, int flags,
{
struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
struct page *p = NULL;
- int gfp_flags = 0;
+ int gfp_flags = GFP_USER;
int r;
/* set zero flag for page allocation if required */
@@ -759,8 +758,8 @@ void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags,
pool->npages += page_count;
/* Check that we don't go over the pool limit */
page_count = 0;
- if (pool->npages > _manager.options.max_size) {
- page_count = pool->npages - _manager.options.max_size;
+ if (pool->npages > _manager->options.max_size) {
+ page_count = pool->npages - _manager->options.max_size;
/* free at least NUM_PAGES_TO_ALLOC number of pages
* to reduce calls to set_memory_wb */
if (page_count < NUM_PAGES_TO_ALLOC)
@@ -785,33 +784,36 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, int flags,
int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
{
int ret;
- if (atomic_add_return(1, &_manager.page_alloc_inited) > 1)
- return 0;
+
+ WARN_ON(_manager);
printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n");
- ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc");
+ _manager = kzalloc(sizeof(*_manager), GFP_KERNEL);
+
+ ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc");
- ttm_page_pool_init_locked(&_manager.uc_pool, GFP_HIGHUSER, "uc");
+ ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc");
- ttm_page_pool_init_locked(&_manager.wc_pool_dma32, GFP_USER | GFP_DMA32,
- "wc dma");
+ ttm_page_pool_init_locked(&_manager->wc_pool_dma32,
+ GFP_USER | GFP_DMA32, "wc dma");
- ttm_page_pool_init_locked(&_manager.uc_pool_dma32, GFP_USER | GFP_DMA32,
- "uc dma");
+ ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
+ GFP_USER | GFP_DMA32, "uc dma");
- _manager.options.max_size = max_pages;
- _manager.options.small = SMALL_ALLOCATION;
- _manager.options.alloc_size = NUM_PAGES_TO_ALLOC;
+ _manager->options.max_size = max_pages;
+ _manager->options.small = SMALL_ALLOCATION;
+ _manager->options.alloc_size = NUM_PAGES_TO_ALLOC;
- kobject_init(&_manager.kobj, &ttm_pool_kobj_type);
- ret = kobject_add(&_manager.kobj, &glob->kobj, "pool");
+ ret = kobject_init_and_add(&_manager->kobj, &ttm_pool_kobj_type,
+ &glob->kobj, "pool");
if (unlikely(ret != 0)) {
- kobject_put(&_manager.kobj);
+ kobject_put(&_manager->kobj);
+ _manager = NULL;
return ret;
}
- ttm_pool_mm_shrink_init(&_manager);
+ ttm_pool_mm_shrink_init(_manager);
return 0;
}
@@ -820,16 +822,14 @@ void ttm_page_alloc_fini()
{
int i;
- if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0)
- return;
-
printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n");
- ttm_pool_mm_shrink_fini(&_manager);
+ ttm_pool_mm_shrink_fini(_manager);
for (i = 0; i < NUM_POOLS; ++i)
- ttm_page_pool_free(&_manager.pools[i], FREE_ALL_PAGES);
+ ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
- kobject_put(&_manager.kobj);
+ kobject_put(&_manager->kobj);
+ _manager = NULL;
}
int ttm_page_alloc_debugfs(struct seq_file *m, void *data)
@@ -837,14 +837,14 @@ int ttm_page_alloc_debugfs(struct seq_file *m, void *data)
struct ttm_page_pool *p;
unsigned i;
char *h[] = {"pool", "refills", "pages freed", "size"};
- if (atomic_read(&_manager.page_alloc_inited) == 0) {
+ if (!_manager) {
seq_printf(m, "No pool allocator running.\n");
return 0;
}
seq_printf(m, "%6s %12s %13s %8s\n",
h[0], h[1], h[2], h[3]);
for (i = 0; i < NUM_POOLS; ++i) {
- p = &_manager.pools[i];
+ p = &_manager->pools[i];
seq_printf(m, "%6s %12ld %13ld %8d\n",
p->name, p->nrefills,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index f1d626112415..437ac786277a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -972,6 +972,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
ret = copy_from_user(rects, user_rects, rects_size);
if (unlikely(ret != 0)) {
DRM_ERROR("Failed to get rects.\n");
+ ret = -EFAULT;
goto out_free;
}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 132278fa6240..434099369058 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -358,6 +358,7 @@ config HID_ROCCAT
config HID_ROCCAT_KONE
tristate "Roccat Kone Mouse support"
depends on USB_HID
+ select HID_ROCCAT
---help---
Support for Roccat Kone mouse.
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index aa0f7dcabcd7..866e54ec5fb2 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1337,6 +1337,24 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
@@ -1760,7 +1778,8 @@ int hid_add_device(struct hid_device *hdev)
/* we need to kill them here, otherwise they will stay allocated to
* wait for coming driver */
- if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) && hid_ignore(hdev))
+ if (!(hdev->quirks & HID_QUIRK_NO_IGNORE)
+ && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
return -ENODEV;
/* XXX hack, any other cleaner solution after the driver core
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index c94026768570..850d02a7a925 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -949,8 +949,8 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
int ret = 0, len;
DECLARE_WAITQUEUE(wait, current);
+ mutex_lock(&list->read_mutex);
while (ret == 0) {
- mutex_lock(&list->read_mutex);
if (list->head == list->tail) {
add_wait_queue(&list->hdev->debug_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 6af77ed0b555..31601eef25dd 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -134,6 +134,7 @@
#define USB_VENDOR_ID_CH 0x068e
#define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2
#define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4
+#define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051
#define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff
#define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK 0x00d3
@@ -369,6 +370,8 @@
#define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701
#define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
+#define USB_VENDOR_ID_MOJO 0x8282
+#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
#define USB_VENDOR_ID_MONTEREY 0x0566
#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
@@ -391,6 +394,24 @@
#define USB_VENDOR_ID_NTRIG 0x1b96
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2 0x0004
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3 0x0005
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4 0x0006
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5 0x0007
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6 0x0008
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7 0x0009
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8 0x000A
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9 0x000B
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10 0x000C
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11 0x000D
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12 0x000E
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13 0x000F
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14 0x0010
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15 0x0011
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16 0x0012
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17 0x0013
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index b6b0caeeac58..fb69b8c4953f 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -868,6 +868,42 @@ static void ntrig_remove(struct hid_device *hdev)
static const struct hid_device_id ntrig_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
{ }
};
MODULE_DEVICE_TABLE(hid, ntrig_devices);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 1ebd3244eb85..b729c0286679 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -827,14 +827,21 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
ret++;
}
} else {
+ int skipped_report_id = 0;
+ if (buf[0] == 0x0) {
+ /* Don't send the Report ID */
+ buf++;
+ count--;
+ skipped_report_id = 1;
+ }
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
HID_REQ_SET_REPORT,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
((report_type + 1) << 8) | *buf,
- interface->desc.bInterfaceNumber, buf + 1, count - 1,
+ interface->desc.bInterfaceNumber, buf, count,
USB_CTRL_SET_TIMEOUT);
- /* count also the report id */
- if (ret > 0)
+ /* count also the report id, if this was a numbered report. */
+ if (ret > 0 && skipped_report_id)
ret++;
}
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 5ff8d327f33a..5f5aa39b3988 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -34,6 +34,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -56,6 +57,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET },
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 2988da150ed6..05344af50734 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -53,6 +53,7 @@ struct coretemp_data {
struct mutex update_lock;
const char *name;
u32 id;
+ u16 core_id;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
int temp;
@@ -75,7 +76,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute
if (attr->index == SHOW_NAME)
ret = sprintf(buf, "%s\n", data->name);
else /* show label */
- ret = sprintf(buf, "Core %d\n", data->id);
+ ret = sprintf(buf, "Core %d\n", data->core_id);
return ret;
}
@@ -304,6 +305,9 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
}
data->id = pdev->id;
+#ifdef CONFIG_SMP
+ data->core_id = c->cpu_core_id;
+#endif
data->name = "coretemp";
mutex_init(&data->update_lock);
@@ -405,6 +409,10 @@ struct pdev_entry {
struct list_head list;
struct platform_device *pdev;
unsigned int cpu;
+#ifdef CONFIG_SMP
+ u16 phys_proc_id;
+ u16 cpu_core_id;
+#endif
};
static LIST_HEAD(pdev_list);
@@ -415,6 +423,22 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
int err;
struct platform_device *pdev;
struct pdev_entry *pdev_entry;
+#ifdef CONFIG_SMP
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+#endif
+
+ mutex_lock(&pdev_list_mutex);
+
+#ifdef CONFIG_SMP
+ /* Skip second HT entry of each core */
+ list_for_each_entry(pdev_entry, &pdev_list, list) {
+ if (c->phys_proc_id == pdev_entry->phys_proc_id &&
+ c->cpu_core_id == pdev_entry->cpu_core_id) {
+ err = 0; /* Not an error */
+ goto exit;
+ }
+ }
+#endif
pdev = platform_device_alloc(DRVNAME, cpu);
if (!pdev) {
@@ -438,7 +462,10 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
pdev_entry->pdev = pdev;
pdev_entry->cpu = cpu;
- mutex_lock(&pdev_list_mutex);
+#ifdef CONFIG_SMP
+ pdev_entry->phys_proc_id = c->phys_proc_id;
+ pdev_entry->cpu_core_id = c->cpu_core_id;
+#endif
list_add_tail(&pdev_entry->list, &pdev_list);
mutex_unlock(&pdev_list_mutex);
@@ -449,6 +476,7 @@ exit_device_free:
exit_device_put:
platform_device_put(pdev);
exit:
+ mutex_unlock(&pdev_list_mutex);
return err;
}
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index e880e2c3871d..937983407e2a 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -289,6 +289,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_label;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -303,6 +304,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_amb_temp;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -318,6 +320,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.show = show_amb_min;
iattr->s_attr.dev_attr.store = store_amb_min;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -333,6 +336,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.show = show_amb_mid;
iattr->s_attr.dev_attr.store = store_amb_mid;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -348,6 +352,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.show = show_amb_max;
iattr->s_attr.dev_attr.store = store_amb_max;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -362,6 +367,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_amb_alarm;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 5be09c048c5f..25763d2223b6 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -80,6 +80,13 @@ superio_inb(int reg)
return inb(VAL);
}
+static inline void
+superio_outb(int reg, int val)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
static int superio_inw(int reg)
{
int val;
@@ -1517,6 +1524,21 @@ static int __init it87_find(unsigned short *address,
sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
reg = superio_inb(IT87_SIO_PINX2_REG);
+ /*
+ * The IT8720F has no VIN7 pin, so VCCH should always be
+ * routed internally to VIN7 with an internal divider.
+ * Curiously, there still is a configuration bit to control
+ * this, which means it can be set incorrectly. And even
+ * more curiously, many boards out there are improperly
+ * configured, even though the IT8720F datasheet claims
+ * that the internal routing of VCCH to VIN7 is the default
+ * setting. So we force the internal routing in this case.
+ */
+ if (sio_data->type == it8720 && !(reg & (1 << 1))) {
+ reg |= (1 << 1);
+ superio_outb(IT87_SIO_PINX2_REG, reg);
+ pr_notice("it87: Routing internal VCCH to in7\n");
+ }
if (reg & (1 << 0))
pr_info("it87: in3 is VCC (+5V)\n");
if (reg & (1 << 1))
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 099a2138cdf6..da5a2404cd3e 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -112,11 +112,21 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)
if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
return false;
- /* Differentiate between AM2+ (bad) and AM3 (good) */
+ /* DDR3 memory implies socket AM3, which is good */
pci_bus_read_config_dword(pdev->bus,
PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
- return !(reg_dram_cfg & DDR3_MODE);
+ if (reg_dram_cfg & DDR3_MODE)
+ return false;
+
+ /*
+ * Unfortunately it is possible to run a socket AM3 CPU with DDR2
+ * memory. We blacklist all the cores which do exist in socket AM2+
+ * format. It still isn't perfect, as RB-C2 cores exist in both AM2+
+ * and AM3 formats, but that's the best we can do.
+ */
+ return boot_cpu_data.x86_model < 4 ||
+ (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
}
static int __devinit k10temp_probe(struct pci_dev *pdev,
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 0ceb6d6200a3..8bdf80d91598 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -120,7 +120,7 @@ static ssize_t show_temp(struct device *dev,
int temp;
struct k8temp_data *data = k8temp_update_device(dev);
- if (data->swap_core_select)
+ if (data->swap_core_select && (data->sensorsp & SEL_CORE))
core = core ? 0 : 1;
temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
@@ -180,11 +180,13 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
}
if ((model >= 0x69) &&
- !(model == 0xc1 || model == 0x6c || model == 0x7c)) {
+ !(model == 0xc1 || model == 0x6c || model == 0x7c ||
+ model == 0x6b || model == 0x6f || model == 0x7f)) {
/*
- * RevG desktop CPUs (i.e. no socket S1G1 parts)
- * need additional offset, otherwise reported
- * temperature is below ambient temperature
+ * RevG desktop CPUs (i.e. no socket S1G1 or
+ * ASB1 parts) need additional offset,
+ * otherwise reported temperature is below
+ * ambient temperature
*/
data->temp_offset = 21000;
}
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index f4b21f2bb8ed..c60081169cc3 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -655,7 +655,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name,
/* & ~0x80, ignore enabled/disabled bit */
if ((type & ~0x80) != dmi_devices[i].type)
continue;
- if (strcmp(name, dmi_devices[i].name))
+ if (strcasecmp(name, dmi_devices[i].name))
continue;
memset(&info, 0, sizeof(struct i2c_board_info));
@@ -704,9 +704,6 @@ static int __devinit i801_probe(struct pci_dev *dev,
{
unsigned char temp;
int err, i;
-#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
- const char *vendor;
-#endif
I801_dev = dev;
i801_features = 0;
@@ -808,8 +805,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
}
#endif
#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
- vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
- if (vendor && !strcmp(vendor, "FUJITSU SIEMENS"))
+ if (dmi_name_in_vendors("FUJITSU"))
dmi_walk(dmi_check_onboard_devices, &i801_adapter);
#endif
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 3d76a188e42f..0fe505d7abe9 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -94,7 +94,7 @@ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
}
break;
default:
- return -1; /* XXXKW better error code? */
+ return -EOPNOTSUPP;
}
while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
@@ -104,7 +104,7 @@ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
if (error & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
- return -1; /* XXXKW better error code? */
+ return (error & M_SMB_ERROR_TYPE) ? -EIO : -ENXIO;
}
if (data_bytes == 1)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 1cca2631e5b3..0815e10da7c6 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1428,13 +1428,12 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
if (!(adapter->class & driver->class))
goto exit_free;
- /* Stop here if we can't use SMBUS_QUICK */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
+ /* Stop here if the bus doesn't support probing */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
if (address_list[0] == I2C_CLIENT_END)
goto exit_free;
- dev_warn(&adapter->dev, "SMBus Quick command not supported, "
- "can't probe for chips\n");
+ dev_warn(&adapter->dev, "Probing not supported\n");
err = -EOPNOTSUPP;
goto exit_free;
}
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 30ce0a8eca09..855ee44fdb52 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -969,7 +969,8 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
goto err;
goto out;
err:
- abort_connection(ep, skb, GFP_KERNEL);
+ state_set(&ep->com, ABORTING);
+ send_abort(ep, skb, GFP_KERNEL);
out:
connect_reply_upcall(ep, err);
return;
@@ -1372,7 +1373,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
pdev, 0);
mtu = pdev->mtu;
tx_chan = cxgb4_port_chan(pdev);
- smac_idx = tx_chan << 1;
+ smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
txq_idx = cxgb4_port_idx(pdev) * step;
step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
@@ -1383,7 +1384,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
dst->neighbour->dev, 0);
mtu = dst_mtu(dst);
tx_chan = cxgb4_port_chan(dst->neighbour->dev);
- smac_idx = tx_chan << 1;
+ smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
@@ -1950,7 +1951,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
pdev, 0);
ep->mtu = pdev->mtu;
ep->tx_chan = cxgb4_port_chan(pdev);
- ep->smac_idx = ep->tx_chan << 1;
+ ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
step = ep->com.dev->rdev.lldi.ntxq /
ep->com.dev->rdev.lldi.nchan;
ep->txq_idx = cxgb4_port_idx(pdev) * step;
@@ -1965,7 +1966,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->dst->neighbour->dev, 0);
ep->mtu = dst_mtu(ep->dst);
ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev);
- ep->smac_idx = ep->tx_chan << 1;
+ ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) &
+ 0x7F) << 1;
step = ep->com.dev->rdev.lldi.ntxq /
ep->com.dev->rdev.lldi.nchan;
ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step;
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 2447f5295482..fac5c6e68011 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -77,7 +77,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
kfree(cq->sw_queue);
dma_free_coherent(&(rdev->lldi.pdev->dev),
cq->memsize, cq->queue,
- pci_unmap_addr(cq, mapping));
+ dma_unmap_addr(cq, mapping));
c4iw_put_cqid(rdev, cq->cqid, uctx);
return ret;
}
@@ -112,7 +112,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
ret = -ENOMEM;
goto err3;
}
- pci_unmap_addr_set(cq, mapping, cq->dma_addr);
+ dma_unmap_addr_set(cq, mapping, cq->dma_addr);
memset(cq->queue, 0, cq->memsize);
/* build fw_ri_res_wr */
@@ -179,7 +179,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
return 0;
err4:
dma_free_coherent(&rdev->lldi.pdev->dev, cq->memsize, cq->queue,
- pci_unmap_addr(cq, mapping));
+ dma_unmap_addr(cq, mapping));
err3:
kfree(cq->sw_queue);
err2:
@@ -764,7 +764,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
struct c4iw_create_cq_resp uresp;
struct c4iw_ucontext *ucontext = NULL;
int ret;
- size_t memsize;
+ size_t memsize, hwentries;
struct c4iw_mm_entry *mm, *mm2;
PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
@@ -788,14 +788,29 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
* entries must be multiple of 16 for HW.
*/
entries = roundup(entries, 16);
- memsize = entries * sizeof *chp->cq.queue;
+
+ /*
+ * Make actual HW queue 2x to avoid cdix_inc overflows.
+ */
+ hwentries = entries * 2;
+
+ /*
+ * Make HW queue at least 64 entries so GTS updates aren't too
+ * frequent.
+ */
+ if (hwentries < 64)
+ hwentries = 64;
+
+ memsize = hwentries * sizeof *chp->cq.queue;
/*
* memsize must be a multiple of the page size if its a user cq.
*/
- if (ucontext)
+ if (ucontext) {
memsize = roundup(memsize, PAGE_SIZE);
- chp->cq.size = entries;
+ hwentries = memsize / sizeof *chp->cq.queue;
+ }
+ chp->cq.size = hwentries;
chp->cq.memsize = memsize;
ret = create_cq(&rhp->rdev, &chp->cq,
@@ -805,7 +820,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
chp->rhp = rhp;
chp->cq.size--; /* status page */
- chp->ibcq.cqe = chp->cq.size - 1;
+ chp->ibcq.cqe = entries - 2;
spin_lock_init(&chp->lock);
atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait);
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 277ab589b44d..d33e1a668811 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -261,7 +261,7 @@ static inline struct c4iw_mw *to_c4iw_mw(struct ib_mw *ibmw)
struct c4iw_fr_page_list {
struct ib_fast_reg_page_list ibpl;
- DECLARE_PCI_UNMAP_ADDR(mapping);
+ DEFINE_DMA_UNMAP_ADDR(mapping);
dma_addr_t dma_addr;
struct c4iw_dev *dev;
int size;
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 7f94da1a2437..82b5703b8947 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -764,7 +764,7 @@ struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,
if (!c4pl)
return ERR_PTR(-ENOMEM);
- pci_unmap_addr_set(c4pl, mapping, dma_addr);
+ dma_unmap_addr_set(c4pl, mapping, dma_addr);
c4pl->dma_addr = dma_addr;
c4pl->dev = dev;
c4pl->size = size;
@@ -779,7 +779,7 @@ void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)
struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);
dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev, c4pl->size,
- c4pl, pci_unmap_addr(c4pl, mapping));
+ c4pl, dma_unmap_addr(c4pl, mapping));
}
int c4iw_dereg_mr(struct ib_mr *ib_mr)
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 646a2a5711f2..86b93f2ecca3 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -40,10 +40,10 @@ static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
*/
dma_free_coherent(&(rdev->lldi.pdev->dev),
wq->rq.memsize, wq->rq.queue,
- pci_unmap_addr(&wq->rq, mapping));
+ dma_unmap_addr(&wq->rq, mapping));
dma_free_coherent(&(rdev->lldi.pdev->dev),
wq->sq.memsize, wq->sq.queue,
- pci_unmap_addr(&wq->sq, mapping));
+ dma_unmap_addr(&wq->sq, mapping));
c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
kfree(wq->rq.sw_rq);
kfree(wq->sq.sw_sq);
@@ -99,7 +99,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
if (!wq->sq.queue)
goto err5;
memset(wq->sq.queue, 0, wq->sq.memsize);
- pci_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
+ dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
wq->rq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev),
wq->rq.memsize, &(wq->rq.dma_addr),
@@ -112,7 +112,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
wq->rq.queue,
(unsigned long long)virt_to_phys(wq->rq.queue));
memset(wq->rq.queue, 0, wq->rq.memsize);
- pci_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr);
+ dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr);
wq->db = rdev->lldi.db_reg;
wq->gts = rdev->lldi.gts_reg;
@@ -217,11 +217,11 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
err7:
dma_free_coherent(&(rdev->lldi.pdev->dev),
wq->rq.memsize, wq->rq.queue,
- pci_unmap_addr(&wq->rq, mapping));
+ dma_unmap_addr(&wq->rq, mapping));
err6:
dma_free_coherent(&(rdev->lldi.pdev->dev),
wq->sq.memsize, wq->sq.queue,
- pci_unmap_addr(&wq->sq, mapping));
+ dma_unmap_addr(&wq->sq, mapping));
err5:
c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
err4:
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 1057cb96302e..9cf8d85bfcff 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -279,7 +279,7 @@ struct t4_swsqe {
struct t4_sq {
union t4_wr *queue;
dma_addr_t dma_addr;
- DECLARE_PCI_UNMAP_ADDR(mapping);
+ DEFINE_DMA_UNMAP_ADDR(mapping);
struct t4_swsqe *sw_sq;
struct t4_swsqe *oldest_read;
u64 udb;
@@ -298,7 +298,7 @@ struct t4_swrqe {
struct t4_rq {
union t4_recv_wr *queue;
dma_addr_t dma_addr;
- DECLARE_PCI_UNMAP_ADDR(mapping);
+ DEFINE_DMA_UNMAP_ADDR(mapping);
struct t4_swrqe *sw_rq;
u64 udb;
size_t memsize;
@@ -429,7 +429,7 @@ static inline int t4_wq_db_enabled(struct t4_wq *wq)
struct t4_cq {
struct t4_cqe *queue;
dma_addr_t dma_addr;
- DECLARE_PCI_UNMAP_ADDR(mapping);
+ DEFINE_DMA_UNMAP_ADDR(mapping);
struct t4_cqe *sw_queue;
void __iomem *gts;
struct c4iw_rdev *rdev;
diff --git a/drivers/infiniband/hw/qib/Makefile b/drivers/infiniband/hw/qib/Makefile
index c6515a1b9a6a..f12d7bb8b39f 100644
--- a/drivers/infiniband/hw/qib/Makefile
+++ b/drivers/infiniband/hw/qib/Makefile
@@ -6,7 +6,7 @@ ib_qib-y := qib_cq.o qib_diag.o qib_dma.o qib_driver.o qib_eeprom.o \
qib_qp.o qib_qsfp.o qib_rc.o qib_ruc.o qib_sdma.o qib_srq.o \
qib_sysfs.o qib_twsi.o qib_tx.o qib_uc.o qib_ud.o \
qib_user_pages.o qib_user_sdma.o qib_verbs_mcast.o qib_iba7220.o \
- qib_sd7220.o qib_sd7220_img.o qib_iba7322.o qib_verbs.o
+ qib_sd7220.o qib_iba7322.o qib_verbs.o
# 6120 has no fallback if no MSI interrupts, others can do INTx
ib_qib-$(CONFIG_PCI_MSI) += qib_iba6120.o
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 32d9208efcff..3593983df7ba 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -686,6 +686,7 @@ struct qib_devdata {
void __iomem *piobase;
/* mem-mapped pointer to base of user chip regs (if using WC PAT) */
u64 __iomem *userbase;
+ void __iomem *piovl15base; /* base of VL15 buffers, if not WC */
/*
* points to area where PIOavail registers will be DMA'ed.
* Has to be on a page of it's own, because the page will be
diff --git a/drivers/infiniband/hw/qib/qib_7220.h b/drivers/infiniband/hw/qib/qib_7220.h
index ea0bfd896f92..21f374aa0631 100644
--- a/drivers/infiniband/hw/qib/qib_7220.h
+++ b/drivers/infiniband/hw/qib/qib_7220.h
@@ -109,10 +109,6 @@ struct qib_chippport_specific {
*/
int qib_sd7220_presets(struct qib_devdata *dd);
int qib_sd7220_init(struct qib_devdata *dd);
-int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, u8 *img,
- int len, int offset);
-int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, const u8 *img,
- int len, int offset);
void qib_sd7220_clr_ibpar(struct qib_devdata *);
/*
* Below used for sdnum parameter, selecting one of the two sections
@@ -121,9 +117,6 @@ void qib_sd7220_clr_ibpar(struct qib_devdata *);
*/
#define IB_7220_SERDES 2
-int qib_sd7220_ib_load(struct qib_devdata *dd);
-int qib_sd7220_ib_vfy(struct qib_devdata *dd);
-
static inline u32 qib_read_kreg32(const struct qib_devdata *dd,
const u16 regno)
{
diff --git a/drivers/infiniband/hw/qib/qib_7322_regs.h b/drivers/infiniband/hw/qib/qib_7322_regs.h
index a97440ba924c..32dc81ff8d4a 100644
--- a/drivers/infiniband/hw/qib/qib_7322_regs.h
+++ b/drivers/infiniband/hw/qib/qib_7322_regs.h
@@ -742,15 +742,15 @@
#define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_1_LSB 0xF
#define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_1_MSB 0xF
#define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_1_RMASK 0x1
-#define QIB_7322_HwErrMask_statusValidNoEopMask_1_LSB 0xE
-#define QIB_7322_HwErrMask_statusValidNoEopMask_1_MSB 0xE
-#define QIB_7322_HwErrMask_statusValidNoEopMask_1_RMASK 0x1
+#define QIB_7322_HwErrMask_IBCBusToSPCParityErrMask_1_LSB 0xE
+#define QIB_7322_HwErrMask_IBCBusToSPCParityErrMask_1_MSB 0xE
+#define QIB_7322_HwErrMask_IBCBusToSPCParityErrMask_1_RMASK 0x1
#define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_0_LSB 0xD
#define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_0_MSB 0xD
#define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_0_RMASK 0x1
-#define QIB_7322_HwErrMask_statusValidNoEopMask_0_LSB 0xC
-#define QIB_7322_HwErrMask_statusValidNoEopMask_0_MSB 0xC
-#define QIB_7322_HwErrMask_statusValidNoEopMask_0_RMASK 0x1
+#define QIB_7322_HwErrMask_statusValidNoEopMask_LSB 0xC
+#define QIB_7322_HwErrMask_statusValidNoEopMask_MSB 0xC
+#define QIB_7322_HwErrMask_statusValidNoEopMask_RMASK 0x1
#define QIB_7322_HwErrMask_LATriggeredMask_LSB 0xB
#define QIB_7322_HwErrMask_LATriggeredMask_MSB 0xB
#define QIB_7322_HwErrMask_LATriggeredMask_RMASK 0x1
@@ -796,15 +796,15 @@
#define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_1_LSB 0xF
#define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_1_MSB 0xF
#define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_1_RMASK 0x1
-#define QIB_7322_HwErrStatus_statusValidNoEop_1_LSB 0xE
-#define QIB_7322_HwErrStatus_statusValidNoEop_1_MSB 0xE
-#define QIB_7322_HwErrStatus_statusValidNoEop_1_RMASK 0x1
+#define QIB_7322_HwErrStatus_IBCBusToSPCParityErr_1_LSB 0xE
+#define QIB_7322_HwErrStatus_IBCBusToSPCParityErr_1_MSB 0xE
+#define QIB_7322_HwErrStatus_IBCBusToSPCParityErr_1_RMASK 0x1
#define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_0_LSB 0xD
#define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_0_MSB 0xD
#define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_0_RMASK 0x1
-#define QIB_7322_HwErrStatus_statusValidNoEop_0_LSB 0xC
-#define QIB_7322_HwErrStatus_statusValidNoEop_0_MSB 0xC
-#define QIB_7322_HwErrStatus_statusValidNoEop_0_RMASK 0x1
+#define QIB_7322_HwErrStatus_statusValidNoEop_LSB 0xC
+#define QIB_7322_HwErrStatus_statusValidNoEop_MSB 0xC
+#define QIB_7322_HwErrStatus_statusValidNoEop_RMASK 0x1
#define QIB_7322_HwErrStatus_LATriggered_LSB 0xB
#define QIB_7322_HwErrStatus_LATriggered_MSB 0xB
#define QIB_7322_HwErrStatus_LATriggered_RMASK 0x1
@@ -850,15 +850,15 @@
#define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_1_LSB 0xF
#define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_1_MSB 0xF
#define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_1_RMASK 0x1
-#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_1_LSB 0xE
-#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_1_MSB 0xE
-#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_1_RMASK 0x1
+#define QIB_7322_HwErrClear_IBCBusToSPCParityErrClear_1_LSB 0xE
+#define QIB_7322_HwErrClear_IBCBusToSPCParityErrClear_1_MSB 0xE
+#define QIB_7322_HwErrClear_IBCBusToSPCParityErrClear_1_RMASK 0x1
#define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_0_LSB 0xD
#define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_0_MSB 0xD
#define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_0_RMASK 0x1
-#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_0_LSB 0xC
-#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_0_MSB 0xC
-#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_0_RMASK 0x1
+#define QIB_7322_HwErrClear_statusValidNoEopClear_LSB 0xC
+#define QIB_7322_HwErrClear_statusValidNoEopClear_MSB 0xC
+#define QIB_7322_HwErrClear_statusValidNoEopClear_RMASK 0x1
#define QIB_7322_HwErrClear_LATriggeredClear_LSB 0xB
#define QIB_7322_HwErrClear_LATriggeredClear_MSB 0xB
#define QIB_7322_HwErrClear_LATriggeredClear_RMASK 0x1
@@ -880,15 +880,15 @@
#define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_1_LSB 0xF
#define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_1_MSB 0xF
#define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_1_RMASK 0x1
-#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_1_LSB 0xE
-#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_1_MSB 0xE
-#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_1_RMASK 0x1
+#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_1_LSB 0xE
+#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_1_MSB 0xE
+#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_1_RMASK 0x1
#define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_0_LSB 0xD
#define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_0_MSB 0xD
#define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_0_RMASK 0x1
-#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_0_LSB 0xC
-#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_0_MSB 0xC
-#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_0_RMASK 0x1
+#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_0_LSB 0xC
+#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_0_MSB 0xC
+#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_0_RMASK 0x1
#define QIB_7322_EXTStatus_OFFS 0xC0
#define QIB_7322_EXTStatus_DEF 0x000000000000X000
diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c
index ca98dd523752..05dcf0d9a7d3 100644
--- a/drivers/infiniband/hw/qib/qib_diag.c
+++ b/drivers/infiniband/hw/qib/qib_diag.c
@@ -233,6 +233,7 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
u32 __iomem *krb32 = (u32 __iomem *)dd->kregbase;
u32 __iomem *map = NULL;
u32 cnt = 0;
+ u32 tot4k, offs4k;
/* First, simplest case, offset is within the first map. */
kreglen = (dd->kregend - dd->kregbase) * sizeof(u64);
@@ -250,7 +251,8 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
if (dd->userbase) {
/* If user regs mapped, they are after send, so set limit. */
u32 ulim = (dd->cfgctxts * dd->ureg_align) + dd->uregbase;
- snd_lim = dd->uregbase;
+ if (!dd->piovl15base)
+ snd_lim = dd->uregbase;
krb32 = (u32 __iomem *)dd->userbase;
if (offset >= dd->uregbase && offset < ulim) {
map = krb32 + (offset - dd->uregbase) / sizeof(u32);
@@ -277,14 +279,14 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
/* If 4k buffers exist, account for them by bumping
* appropriate limit.
*/
+ tot4k = dd->piobcnt4k * dd->align4k;
+ offs4k = dd->piobufbase >> 32;
if (dd->piobcnt4k) {
- u32 tot4k = dd->piobcnt4k * dd->align4k;
- u32 offs4k = dd->piobufbase >> 32;
if (snd_bottom > offs4k)
snd_bottom = offs4k;
else {
/* 4k above 2k. Bump snd_lim, if needed*/
- if (!dd->userbase)
+ if (!dd->userbase || dd->piovl15base)
snd_lim = offs4k + tot4k;
}
}
@@ -298,6 +300,15 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
cnt = snd_lim - offset;
}
+ if (!map && offs4k && dd->piovl15base) {
+ snd_lim = offs4k + tot4k + 2 * dd->align4k;
+ if (offset >= (offs4k + tot4k) && offset < snd_lim) {
+ map = (u32 __iomem *)dd->piovl15base +
+ ((offset - (offs4k + tot4k)) / sizeof(u32));
+ cnt = snd_lim - offset;
+ }
+ }
+
mapped:
if (cntp)
*cntp = cnt;
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 1eadadc13da8..a5e29dbb9537 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -1355,8 +1355,7 @@ static int qib_6120_bringup_serdes(struct qib_pportdata *ppd)
hwstat = qib_read_kreg64(dd, kr_hwerrstatus);
if (hwstat) {
/* should just have PLL, clear all set, in an case */
- if (hwstat & ~QLOGIC_IB_HWE_SERDESPLLFAILED)
- qib_write_kreg(dd, kr_hwerrclear, hwstat);
+ qib_write_kreg(dd, kr_hwerrclear, hwstat);
qib_write_kreg(dd, kr_errclear, ERR_MASK(HardwareErr));
}
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 503992d9c5ce..5eedf83e2c3b 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -543,7 +543,7 @@ struct vendor_txdds_ent {
static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *);
#define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */
-#define TXDDS_EXTRA_SZ 11 /* number of extra tx settings entries */
+#define TXDDS_EXTRA_SZ 13 /* number of extra tx settings entries */
#define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */
#define H1_FORCE_VAL 8
@@ -1100,9 +1100,9 @@ static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
HWE_AUTO_P(SDmaMemReadErr, 1),
HWE_AUTO_P(SDmaMemReadErr, 0),
HWE_AUTO_P(IBCBusFromSPCParityErr, 1),
+ HWE_AUTO_P(IBCBusToSPCParityErr, 1),
HWE_AUTO_P(IBCBusFromSPCParityErr, 0),
- HWE_AUTO_P(statusValidNoEop, 1),
- HWE_AUTO_P(statusValidNoEop, 0),
+ HWE_AUTO(statusValidNoEop),
HWE_AUTO(LATriggered),
{ .mask = 0 }
};
@@ -4763,6 +4763,8 @@ static void qib_7322_mini_pcs_reset(struct qib_pportdata *ppd)
SYM_MASK(IBPCSConfig_0, tx_rx_reset);
val = qib_read_kreg_port(ppd, krp_ib_pcsconfig);
+ qib_write_kreg(dd, kr_hwerrmask,
+ dd->cspec->hwerrmask & ~HWE_MASK(statusValidNoEop));
qib_write_kreg_port(ppd, krp_ibcctrl_a,
ppd->cpspec->ibcctrl_a &
~SYM_MASK(IBCCtrlA_0, IBLinkEn));
@@ -4772,6 +4774,9 @@ static void qib_7322_mini_pcs_reset(struct qib_pportdata *ppd)
qib_write_kreg_port(ppd, krp_ib_pcsconfig, val & ~reset_bits);
qib_write_kreg_port(ppd, krp_ibcctrl_a, ppd->cpspec->ibcctrl_a);
qib_write_kreg(dd, kr_scratch, 0ULL);
+ qib_write_kreg(dd, kr_hwerrclear,
+ SYM_MASK(HwErrClear, statusValidNoEopClear));
+ qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask);
}
/*
@@ -5624,6 +5629,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
if (ppd->port != port || !ppd->link_speed_supported)
continue;
ppd->cpspec->no_eep = val;
+ if (seth1)
+ ppd->cpspec->h1_val = h1;
/* now change the IBC and serdes, overriding generic */
init_txdds_table(ppd, 1);
any++;
@@ -6064,9 +6071,9 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
* the "cable info" setup here. Can be overridden
* in adapter-specific routines.
*/
- if (!(ppd->dd->flags & QIB_HAS_QSFP)) {
- if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd))
- qib_devinfo(ppd->dd->pcidev, "IB%u:%u: "
+ if (!(dd->flags & QIB_HAS_QSFP)) {
+ if (!IS_QMH(dd) && !IS_QME(dd))
+ qib_devinfo(dd->pcidev, "IB%u:%u: "
"Unknown mezzanine card type\n",
dd->unit, ppd->port);
cp->h1_val = IS_QMH(dd) ? H1_FORCE_QMH : H1_FORCE_QME;
@@ -6119,9 +6126,25 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
qib_set_ctxtcnt(dd);
if (qib_wc_pat) {
- ret = init_chip_wc_pat(dd, NUM_VL15_BUFS * dd->align4k);
+ resource_size_t vl15off;
+ /*
+ * We do not set WC on the VL15 buffers to avoid
+ * a rare problem with unaligned writes from
+ * interrupt-flushed store buffers, so we need
+ * to map those separately here. We can't solve
+ * this for the rarely used mtrr case.
+ */
+ ret = init_chip_wc_pat(dd, 0);
if (ret)
goto bail;
+
+ /* vl15 buffers start just after the 4k buffers */
+ vl15off = dd->physaddr + (dd->piobufbase >> 32) +
+ dd->piobcnt4k * dd->align4k;
+ dd->piovl15base = ioremap_nocache(vl15off,
+ NUM_VL15_BUFS * dd->align4k);
+ if (!dd->piovl15base)
+ goto bail;
}
qib_7322_set_baseaddrs(dd); /* set chip access pointers now */
@@ -6932,6 +6955,8 @@ static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = {
{ 0, 0, 0, 11 }, /* QME7342 backplane settings */
{ 0, 0, 0, 11 }, /* QME7342 backplane settings */
{ 0, 0, 0, 11 }, /* QME7342 backplane settings */
+ { 0, 0, 0, 3 }, /* QMH7342 backplane settings */
+ { 0, 0, 0, 4 }, /* QMH7342 backplane settings */
};
static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = {
@@ -6947,6 +6972,8 @@ static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = {
{ 0, 0, 0, 13 }, /* QME7342 backplane settings */
{ 0, 0, 0, 13 }, /* QME7342 backplane settings */
{ 0, 0, 0, 13 }, /* QME7342 backplane settings */
+ { 0, 0, 0, 9 }, /* QMH7342 backplane settings */
+ { 0, 0, 0, 10 }, /* QMH7342 backplane settings */
};
static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = {
@@ -6962,6 +6989,8 @@ static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = {
{ 0, 1, 12, 6 }, /* QME7342 backplane setting */
{ 0, 1, 12, 7 }, /* QME7342 backplane setting */
{ 0, 1, 12, 8 }, /* QME7342 backplane setting */
+ { 0, 1, 0, 10 }, /* QMH7342 backplane settings */
+ { 0, 1, 0, 12 }, /* QMH7342 backplane settings */
};
static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds,
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 9b40f345ac3f..a873dd596e81 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1059,7 +1059,7 @@ static int __init qlogic_ib_init(void)
goto bail_dev;
}
- qib_cq_wq = create_workqueue("qib_cq");
+ qib_cq_wq = create_singlethread_workqueue("qib_cq");
if (!qib_cq_wq) {
ret = -ENOMEM;
goto bail_wq;
@@ -1289,8 +1289,18 @@ static int __devinit qib_init_one(struct pci_dev *pdev,
if (qib_mini_init || initfail || ret) {
qib_stop_timers(dd);
+ flush_scheduled_work();
for (pidx = 0; pidx < dd->num_pports; ++pidx)
dd->f_quiet_serdes(dd->pport + pidx);
+ if (qib_mini_init)
+ goto bail;
+ if (!j) {
+ (void) qibfs_remove(dd);
+ qib_device_remove(dd);
+ }
+ if (!ret)
+ qib_unregister_ib_device(dd);
+ qib_postinit_cleanup(dd);
if (initfail)
ret = initfail;
goto bail;
@@ -1472,6 +1482,9 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd)
dma_addr_t pa = rcd->rcvegrbuf_phys[chunk];
unsigned i;
+ /* clear for security and sanity on each use */
+ memset(rcd->rcvegrbuf[chunk], 0, size);
+
for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) {
dd->f_put_tid(dd, e + egroff +
(u64 __iomem *)
@@ -1499,6 +1512,12 @@ bail:
return -ENOMEM;
}
+/*
+ * Note: Changes to this routine should be mirrored
+ * for the diagnostics routine qib_remap_ioaddr32().
+ * There is also related code for VL15 buffers in qib_init_7322_variables().
+ * The teardown code that unmaps is in qib_pcie_ddcleanup()
+ */
int init_chip_wc_pat(struct qib_devdata *dd, u32 vl15buflen)
{
u64 __iomem *qib_kregbase = NULL;
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index c926bf4541df..7fa6e5592630 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -179,6 +179,8 @@ void qib_pcie_ddcleanup(struct qib_devdata *dd)
iounmap(dd->piobase);
if (dd->userbase)
iounmap(dd->userbase);
+ if (dd->piovl15base)
+ iounmap(dd->piovl15base);
pci_disable_device(dd->pcidev);
pci_release_regions(dd->pcidev);
diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c
index 0aeed0e74cb6..e9f9f8bc3204 100644
--- a/drivers/infiniband/hw/qib/qib_sd7220.c
+++ b/drivers/infiniband/hw/qib/qib_sd7220.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
+ * All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -37,10 +38,14 @@
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/firmware.h>
#include "qib.h"
#include "qib_7220.h"
+#define SD7220_FW_NAME "qlogic/sd7220.fw"
+MODULE_FIRMWARE(SD7220_FW_NAME);
+
/*
* Same as in qib_iba7220.c, but just the registers needed here.
* Could move whole set to qib_7220.h, but decided better to keep
@@ -102,6 +107,10 @@ static int qib_internal_presets(struct qib_devdata *dd);
/* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */
static int qib_sd_trimself(struct qib_devdata *dd, int val);
static int epb_access(struct qib_devdata *dd, int sdnum, int claim);
+static int qib_sd7220_ib_load(struct qib_devdata *dd,
+ const struct firmware *fw);
+static int qib_sd7220_ib_vfy(struct qib_devdata *dd,
+ const struct firmware *fw);
/*
* Below keeps track of whether the "once per power-on" initialization has
@@ -110,10 +119,13 @@ static int epb_access(struct qib_devdata *dd, int sdnum, int claim);
* state of the reset "pin", is no longer valid. Instead, we check for the
* actual uC code having been loaded.
*/
-static int qib_ibsd_ucode_loaded(struct qib_pportdata *ppd)
+static int qib_ibsd_ucode_loaded(struct qib_pportdata *ppd,
+ const struct firmware *fw)
{
struct qib_devdata *dd = ppd->dd;
- if (!dd->cspec->serdes_first_init_done && (qib_sd7220_ib_vfy(dd) > 0))
+
+ if (!dd->cspec->serdes_first_init_done &&
+ qib_sd7220_ib_vfy(dd, fw) > 0)
dd->cspec->serdes_first_init_done = 1;
return dd->cspec->serdes_first_init_done;
}
@@ -377,6 +389,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd,
*/
int qib_sd7220_init(struct qib_devdata *dd)
{
+ const struct firmware *fw;
int ret = 1; /* default to failure */
int first_reset, was_reset;
@@ -387,8 +400,15 @@ int qib_sd7220_init(struct qib_devdata *dd)
qib_ibsd_reset(dd, 1);
qib_sd_trimdone_monitor(dd, "Driver-reload");
}
+
+ ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev);
+ if (ret) {
+ qib_dev_err(dd, "Failed to load IB SERDES image\n");
+ goto done;
+ }
+
/* Substitute our deduced value for was_reset */
- ret = qib_ibsd_ucode_loaded(dd->pport);
+ ret = qib_ibsd_ucode_loaded(dd->pport, fw);
if (ret < 0)
goto bail;
@@ -437,13 +457,13 @@ int qib_sd7220_init(struct qib_devdata *dd)
int vfy;
int trim_done;
- ret = qib_sd7220_ib_load(dd);
+ ret = qib_sd7220_ib_load(dd, fw);
if (ret < 0) {
qib_dev_err(dd, "Failed to load IB SERDES image\n");
goto bail;
} else {
/* Loaded image, try to verify */
- vfy = qib_sd7220_ib_vfy(dd);
+ vfy = qib_sd7220_ib_vfy(dd, fw);
if (vfy != ret) {
qib_dev_err(dd, "SERDES PRAM VFY failed\n");
goto bail;
@@ -506,6 +526,8 @@ bail:
done:
/* start relock timer regardless, but start at 1 second */
set_7220_relock_poll(dd, -1);
+
+ release_firmware(fw);
return ret;
}
@@ -829,8 +851,8 @@ static int qib_sd7220_ram_xfer(struct qib_devdata *dd, int sdnum, u32 loc,
#define PROG_CHUNK 64
-int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
- u8 *img, int len, int offset)
+static int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
+ const u8 *img, int len, int offset)
{
int cnt, sofar, req;
@@ -840,7 +862,7 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
if (req > PROG_CHUNK)
req = PROG_CHUNK;
cnt = qib_sd7220_ram_xfer(dd, sdnum, offset + sofar,
- img + sofar, req, 0);
+ (u8 *)img + sofar, req, 0);
if (cnt < req) {
sofar = -1;
break;
@@ -853,8 +875,8 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
#define VFY_CHUNK 64
#define SD_PRAM_ERROR_LIMIT 42
-int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum,
- const u8 *img, int len, int offset)
+static int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum,
+ const u8 *img, int len, int offset)
{
int cnt, sofar, req, idx, errors;
unsigned char readback[VFY_CHUNK];
@@ -881,6 +903,18 @@ int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum,
return errors ? -errors : sofar;
}
+static int
+qib_sd7220_ib_load(struct qib_devdata *dd, const struct firmware *fw)
+{
+ return qib_sd7220_prog_ld(dd, IB_7220_SERDES, fw->data, fw->size, 0);
+}
+
+static int
+qib_sd7220_ib_vfy(struct qib_devdata *dd, const struct firmware *fw)
+{
+ return qib_sd7220_prog_vfy(dd, IB_7220_SERDES, fw->data, fw->size, 0);
+}
+
/*
* IRQ not set up at this point in init, so we poll.
*/
diff --git a/drivers/infiniband/hw/qib/qib_sd7220_img.c b/drivers/infiniband/hw/qib/qib_sd7220_img.c
deleted file mode 100644
index a1118fbd2370..000000000000
--- a/drivers/infiniband/hw/qib/qib_sd7220_img.c
+++ /dev/null
@@ -1,1081 +0,0 @@
-/*
- * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
- * This file contains the memory image from the vendor, to be copied into
- * the IB SERDES of the IBA7220 during initialization.
- * The file also includes the two functions which use this image.
- */
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include "qib.h"
-#include "qib_7220.h"
-
-static unsigned char qib_sd7220_ib_img[] = {
-/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6,
- 0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
-/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01,
- 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08,
-/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08,
- 0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2,
-/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7,
- 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00,
-/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75,
- 0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5,
-/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38,
- 0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94,
-/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36,
- 0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74,
-/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90,
- 0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20,
-/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3,
- 0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12,
-/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04,
- 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09,
-/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00,
- 0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2,
-/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09,
- 0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24,
-/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83,
- 0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3,
-/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0,
- 0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03,
-/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4,
- 0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E,
-/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82,
- 0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44,
-/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40,
- 0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54,
-/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44,
- 0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08,
-/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF,
- 0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40,
-/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75,
- 0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E,
-/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD,
- 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81,
-/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED,
- 0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF,
-/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0,
- 0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12,
-/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32,
- 0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74,
-/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83,
- 0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0,
-/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19,
- 0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE,
-/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03,
- 0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0,
-/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83,
- 0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12,
-/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3,
- 0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A,
-/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF,
- 0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19,
-/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30,
- 0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
-/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C,
- 0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60,
-/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44,
- 0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02,
-/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7,
- 0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0,
-/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04,
- 0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01,
-/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40,
- 0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12,
-/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32,
- 0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44,
-/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0,
- 0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5,
-/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40,
- 0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07,
-/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F,
- 0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D,
-/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A,
- 0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74,
-/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12,
- 0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90,
-/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE,
- 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5,
-/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02,
- 0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82,
-/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A,
- 0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04,
-/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82,
- 0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A,
-/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04,
- 0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82,
-/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92,
- 0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A,
-/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2,
- 0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F,
-/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20,
- 0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12,
-/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30,
- 0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06,
-/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D,
- 0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0,
-/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43,
- 0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04,
-/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A,
- 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
-/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
- 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
-/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
- 0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17,
-/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44,
- 0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12,
-/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12,
- 0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74,
-/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0,
- 0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44,
-/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07,
- 0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE,
-/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12,
- 0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10,
-/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12,
- 0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF,
-/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30,
- 0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
-/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B,
- 0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5,
-/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09,
- 0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82,
-/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F,
- 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3,
-/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02,
- 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E,
-/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09,
- 0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1,
-/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B,
- 0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75,
-/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73,
- 0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0,
-/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47,
- 0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F,
-/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07,
- 0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80,
-/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74,
- 0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F,
-/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83,
- 0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08,
-/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12,
- 0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B,
-/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36,
- 0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83,
-/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12,
- 0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0,
-/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5,
- 0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33,
-/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4,
- 0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4,
-/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E,
- 0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12,
-/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF,
- 0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D,
-/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02,
- 0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01,
-/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06,
- 0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF,
-/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80,
- 0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04,
-/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E,
- 0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5,
-/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60,
- 0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46,
-/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76,
- 0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F,
-/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95,
- 0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5,
-/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01,
- 0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80,
-/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95,
- 0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
-/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
- 0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F,
-/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46,
- 0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75,
-/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E,
- 0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5,
-/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5,
- 0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F,
-/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5,
- 0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5,
-/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04,
- 0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80,
-/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F,
- 0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5,
-/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D,
- 0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70,
-/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5,
- 0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C,
-/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E,
- 0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79,
-/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85,
- 0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50,
-/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78,
- 0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30,
-/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E,
- 0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19,
-/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
- 0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
-/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F,
- 0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14,
-/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19,
- 0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
-/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75,
- 0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C,
-/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E,
- 0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80,
-/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5,
- 0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
-/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB,
- 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0,
-/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44,
- 0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0,
-/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA,
- 0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC,
-/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5,
- 0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0,
-/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83,
- 0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44,
-/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54,
- 0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
-/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3,
- 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42,
-/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74,
- 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5,
-/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5,
- 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5,
-/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C,
- 0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80,
-/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22,
- 0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5,
-/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07,
- 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C,
-/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44,
- 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85,
-/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A,
- 0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E,
-/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED,
- 0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22,
-/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02,
- 0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11,
-/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22,
- 0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
-/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11,
- 0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
-/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
- 0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11,
-/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
- 0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
-/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5,
- 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF,
-/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82,
- 0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5,
-/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25,
- 0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
-/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4,
- 0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25,
-/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83,
- 0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
-/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD,
- 0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41,
-/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22,
- 0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00,
-/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
- 0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5,
-/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42,
- 0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C,
-/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75,
- 0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3,
-/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E,
- 0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5,
-/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00,
- 0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5,
-/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07,
- 0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95,
-/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4,
- 0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0,
-/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
- 0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82,
-/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4,
- 0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41,
-/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60,
- 0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37,
-/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD,
- 0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28,
-/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8,
- 0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F,
-/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0,
- 0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54,
-/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF,
- 0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26,
-/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4,
- 0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89,
-/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12,
- 0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08,
-/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24,
- 0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12,
-/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E,
- 0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
-/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01,
- 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78,
-/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF,
- 0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0,
-/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07,
- 0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF,
-/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24,
- 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
-/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC,
- 0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12,
-/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08,
- 0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4,
-/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08,
- 0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41,
-/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0,
- 0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D,
-/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0,
- 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4,
-/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5,
- 0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5,
-/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6,
- 0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78,
-/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE,
- 0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8,
-/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5,
- 0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1,
-/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00,
- 0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3,
-/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43,
- 0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83,
-/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0,
- 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0,
-/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55,
- 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6,
-/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3,
- 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33,
-/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40,
- 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF,
-/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10,
- 0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E,
-/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F,
- 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93,
-/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25,
- 0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C,
-/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4,
- 0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D,
-/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66,
- 0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90,
-/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4,
- 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12,
-/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
- 0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83,
-/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8,
- 0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12,
-/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05,
- 0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55,
-/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70,
- 0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5,
-/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
- 0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12,
-/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
- 0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
-/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
- 0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12,
-/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12,
- 0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E,
-/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44,
- 0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3,
-/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68,
- 0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14,
-/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA,
- 0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74,
-/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80,
- 0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5,
-/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95,
- 0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70,
-/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12,
- 0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80,
-/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D,
- 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85,
-/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F,
- 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07,
-/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5,
- 0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F,
-/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12,
- 0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12,
-/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C,
- 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38,
-/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80,
- 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08,
-/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D,
- 0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39,
-/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38,
- 0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F,
-/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12,
- 0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A,
-/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12,
- 0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5,
-/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75,
- 0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12,
-/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0,
- 0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06,
-/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5,
- 0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13,
-/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09,
- 0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40,
-/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E,
- 0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
-/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
- 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
-/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
- 0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F,
-/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04,
- 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5,
-/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80,
- 0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0,
-/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74,
- 0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17,
-/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07,
- 0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90,
-/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44,
- 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54,
-/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F,
- 0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07,
-/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82,
- 0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED,
-/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF,
- 0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54,
-/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91,
- 0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30,
-/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92,
- 0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4,
-/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75,
- 0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A,
-/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0,
- 0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E,
-/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E,
- 0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0,
-/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75,
- 0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75,
-/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07,
- 0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10,
-/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF,
- 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82,
-/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5,
- 0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75,
-/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44,
- 0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
-/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0,
- 0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34,
-/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22,
- 0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1,
-/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25,
- 0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4,
-/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85,
- 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0,
-/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00,
- 0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00,
-/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22,
- 0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5,
-/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30,
- 0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC,
-/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B,
- 0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28,
-/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07,
- 0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24,
-/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70,
- 0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07,
-/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0,
- 0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12,
-/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41,
- 0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12,
-/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04,
- 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64,
-/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02,
- 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07,
-/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07,
- 0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF,
-/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0,
- 0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
-/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0,
- 0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07,
-/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12,
- 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
-/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E,
- 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70,
-/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43,
- 0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10,
-/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
- 0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52,
-/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08,
- 0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B,
-/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00,
- 0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
-/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12,
- 0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51,
-/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1,
- 0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1,
-/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80,
- 0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01,
-/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40,
- 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
-/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12,
- 0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22,
-/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10,
- 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12,
- 0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10,
-/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12,
- 0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0,
-/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07,
- 0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07,
-/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00,
- 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
-/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90,
- 0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56,
-/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12,
- 0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5,
-/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA,
- 0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12,
-/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F,
- 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22,
-/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74,
- 0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57,
-/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01,
- 0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04,
-/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4,
- 0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0,
-/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94,
- 0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12,
-/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5,
- 0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5,
-/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56,
- 0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80,
-/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40,
- 0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22,
-/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93,
- 0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5,
-/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22,
- 0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5,
-/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93,
- 0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6,
-/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED,
- 0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5,
-/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01,
- 0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00,
-/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D,
- 0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01,
-/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12,
- 0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4,
-/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85,
- 0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5,
-/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07,
- 0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12,
-/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E,
- 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45,
-/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08,
- 0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00,
-/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5,
- 0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05,
-/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC,
- 0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11,
-/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0,
- 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE,
-/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83,
- 0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58,
-/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75,
- 0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75,
-/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08,
- 0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF,
-/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90,
- 0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35,
-/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF,
- 0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45,
-/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
- 0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E,
-/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60,
- 0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5,
-/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE,
- 0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58,
-/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12,
- 0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00,
-/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07,
- 0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B,
-/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12,
- 0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12,
-/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64,
- 0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E,
-/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95,
- 0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40,
-/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05,
- 0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39,
-/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12,
- 0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B,
-/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07,
- 0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F,
-/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5,
- 0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C,
-/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39,
- 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12,
-/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5,
- 0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38,
-/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C,
- 0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C,
-/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09,
- 0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40,
-/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E,
- 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38,
-/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80,
- 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07,
-/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F,
- 0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63,
-/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12,
- 0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5,
-/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38,
- 0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60,
-/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39,
- 0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C,
-/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12,
- 0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5,
-/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08,
- 0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15,
-/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17,
- 0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80,
-/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94,
- 0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31,
-/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15,
- 0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01,
-/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04,
- 0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A,
-/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77,
- 0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15,
-/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04,
- 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15,
-/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E,
- 0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22,
-/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15,
- 0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A,
-/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29,
- 0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13,
-/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24,
- 0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63,
-/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6,
- 0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22,
-/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3,
- 0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5,
-/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74,
- 0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74,
-/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20,
- 0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8,
-/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44,
- 0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF,
-/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6,
- 0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3,
-/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E,
- 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A,
-/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5,
- 0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3,
-/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07,
- 0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70,
-/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5,
- 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5,
-/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5,
- 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5,
-/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
- 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80,
-/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF,
- 0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12,
-/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D,
- 0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02,
-/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B,
- 0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B,
-/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B,
- 0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5,
-/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60,
- 0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12,
-/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E,
- 0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6,
-/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8,
- 0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA,
-/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5,
- 0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80,
-/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5,
- 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4,
-/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29,
- 0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F,
-/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E,
- 0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B,
-/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11,
- 0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12,
-/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A,
- 0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5,
-/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13,
- 0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3,
-/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12,
- 0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE,
-/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19,
- 0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E,
-/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75,
- 0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D,
-/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12,
- 0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94,
-/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83,
- 0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0,
-/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
- 0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82,
-/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F,
- 0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75,
-/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21,
- 0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44,
-/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF,
- 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75,
-/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29,
- 0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07,
-/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12,
- 0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10,
-/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44,
- 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0,
-/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12,
- 0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58,
-/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC,
- 0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83,
-/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
- 0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
-/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
- 0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
-/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
- 0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
-/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2,
- 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4,
-/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12,
- 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07,
-/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58,
- 0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A,
-/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7,
- 0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09,
-/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0,
- 0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54,
-/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78,
- 0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,
-/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B,
- 0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33,
-/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83,
- 0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83,
-/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E,
- 0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3,
-/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00,
- 0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02,
-/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58,
- 0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12,
-/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54,
- 0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E,
-/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04,
- 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE,
-/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05,
- 0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33,
-/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C,
- 0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02,
-/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12,
- 0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12,
-/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2,
- 0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3,
-/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41,
- 0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5,
-/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07,
- 0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C,
-/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B,
- 0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60,
-/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41,
- 0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B,
-/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00,
- 0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02,
-/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41,
- 0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40,
-/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1,
- 0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F,
-/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70,
- 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
-/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2,
- 0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E,
-/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5,
- 0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5,
-/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0,
- 0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05,
-/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70,
- 0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA,
-/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F,
- 0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0,
-/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5,
- 0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01,
-/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D,
- 0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32,
-/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04,
- 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82,
-/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01,
- 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15,
-/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05,
- 0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43,
-/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E,
- 0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24,
-/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83,
- 0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0,
-/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34,
- 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12,
-/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0,
- 0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0,
-/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04,
- 0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80,
-/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0,
- 0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83,
-/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12,
- 0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33,
-/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E,
- 0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15,
-/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75,
- 0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12,
-/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80,
- 0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12,
-/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20,
- 0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C,
-/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80,
- 0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF,
-/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25,
- 0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07,
-/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08,
- 0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0,
-/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
- 0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E,
-/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82,
- 0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94,
-/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04,
- 0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83,
-/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5,
- 0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07,
-/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75,
- 0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29,
-/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12,
- 0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0,
-/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70,
- 0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90,
-/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0,
- 0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF,
-/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5,
- 0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07,
-/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22,
- 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90,
-/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94,
- 0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98,
-/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C,
- 0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0,
-/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4,
- 0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8,
-/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC,
- 0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0,
-/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6,
- 0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB,
-/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4,
- 0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5,
-/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08,
- 0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5,
-/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29,
- 0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80,
-/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5,
- 0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35,
-/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83,
- 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12,
-/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26,
- 0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75,
-/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17,
- 0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4,
-/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93,
- 0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5,
-/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10,
- 0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54,
-/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06,
- 0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00,
-/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00,
- 0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0,
-/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75,
- 0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0,
-/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14,
- 0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70,
-/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7,
- 0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74,
-/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44,
- 0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12,
-/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0,
- 0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12,
-/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE,
- 0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B,
-/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4,
- 0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF,
-/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F,
- 0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70,
-/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41,
- 0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5,
-/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A,
- 0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5,
-/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5,
- 0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5,
-/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0,
- 0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C,
-/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80,
- 0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04,
-/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F,
- 0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A,
-/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41,
- 0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01,
-/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54,
- 0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F,
-/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58,
- 0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59,
-/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85,
- 0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59,
-/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15,
- 0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A,
-/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5,
- 0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2,
-/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20,
- 0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12,
-/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94,
- 0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9,
-/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9,
- 0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00,
-/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83,
- 0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12,
-/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02,
- 0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83,
-/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75,
- 0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94,
-/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A,
- 0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74,
-/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE,
- 0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08,
-/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85,
- 0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0,
-/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01,
- 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC,
-/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E,
- 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00,
-/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
- 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56,
-/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE,
- 0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12,
-/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E,
- 0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44,
-/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4,
- 0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08,
-/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82,
- 0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3,
-/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E,
- 0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
-/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC,
- 0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD,
-/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02,
- 0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09,
-/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42,
- 0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3,
-/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C,
- 0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F,
-/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84,
- 0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82,
-/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0,
- 0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22,
-/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75,
- 0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12,
-/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20,
- 0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26,
-/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41,
- 0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40,
-/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12,
- 0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56,
-/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42,
- 0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39,
-/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5,
- 0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F,
-/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB,
- 0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00,
-/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81
-};
-
-int qib_sd7220_ib_load(struct qib_devdata *dd)
-{
- return qib_sd7220_prog_ld(dd, IB_7220_SERDES, qib_sd7220_ib_img,
- sizeof(qib_sd7220_ib_img), 0);
-}
-
-int qib_sd7220_ib_vfy(struct qib_devdata *dd)
-{
- return qib_sd7220_prog_vfy(dd, IB_7220_SERDES, qib_sd7220_ib_img,
- sizeof(qib_sd7220_ib_img), 0);
-}
diff --git a/drivers/infiniband/hw/qib/qib_tx.c b/drivers/infiniband/hw/qib/qib_tx.c
index f7eb1ddff5f3..af30232b6831 100644
--- a/drivers/infiniband/hw/qib/qib_tx.c
+++ b/drivers/infiniband/hw/qib/qib_tx.c
@@ -340,9 +340,13 @@ rescan:
if (i < dd->piobcnt2k)
buf = (u32 __iomem *)(dd->pio2kbase +
i * dd->palign);
- else
+ else if (i < dd->piobcnt2k + dd->piobcnt4k || !dd->piovl15base)
buf = (u32 __iomem *)(dd->pio4kbase +
(i - dd->piobcnt2k) * dd->align4k);
+ else
+ buf = (u32 __iomem *)(dd->piovl15base +
+ (i - (dd->piobcnt2k + dd->piobcnt4k)) *
+ dd->align4k);
if (pbufnum)
*pbufnum = i;
dd->upd_pio_shadow = 0;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index df3eb8c9fd96..b4b22576f12a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1163,7 +1163,7 @@ static ssize_t create_child(struct device *dev,
return ret ? ret : count;
}
-static DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child);
+static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child);
static ssize_t delete_child(struct device *dev,
struct device_attribute *attr,
@@ -1183,7 +1183,7 @@ static ssize_t delete_child(struct device *dev,
return ret ? ret : count;
}
-static DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child);
+static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child);
int ipoib_add_pkey_attr(struct net_device *dev)
{
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index fbd62abb66f9..0ffaf2c77a19 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -89,7 +89,6 @@ struct gc_pad {
struct gc {
struct pardevice *pd;
struct gc_pad pads[GC_MAX_DEVICES];
- struct input_dev *dev[GC_MAX_DEVICES];
struct timer_list timer;
int pad_count[GC_MAX];
int used;
@@ -387,7 +386,7 @@ static void gc_nes_process_packet(struct gc *gc)
for (i = 0; i < GC_MAX_DEVICES; i++) {
pad = &gc->pads[i];
- dev = gc->dev[i];
+ dev = pad->dev;
s = gc_status_bit[i];
switch (pad->type) {
@@ -579,7 +578,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char *data)
read = parport_read_status(port) ^ 0x80;
for (j = 0; j < GC_MAX_DEVICES; j++) {
- struct gc_pad *pad = &gc->pads[i];
+ struct gc_pad *pad = &gc->pads[j];
if (pad->type == GC_PSX || pad->type == GC_DDR)
data[j] |= (read & gc_status_bit[j]) ? (1 << i) : 0;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index d8fa5d724c57..1ba25145b333 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -73,7 +73,7 @@ config KEYBOARD_ATKBD
default y
select SERIO
select SERIO_LIBPS2
- select SERIO_I8042 if X86 && !X86_MRST
+ select SERIO_I8042 if X86
select SERIO_GSCPS2 if GSC
help
Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
@@ -124,7 +124,7 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
right-hand column will be interpreted as the key shown in the
left-hand column.
-config QT2160
+config KEYBOARD_QT2160
tristate "Atmel AT42QT2160 Touch Sensor Chip"
depends on I2C && EXPERIMENTAL
help
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
index 7aa59e07b689..fb16b5e5ea13 100644
--- a/drivers/input/keyboard/twl4030_keypad.c
+++ b/drivers/input/keyboard/twl4030_keypad.c
@@ -51,8 +51,12 @@
*/
#define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */
#define TWL4030_MAX_COLS 8
-#define TWL4030_ROW_SHIFT 3
-#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS)
+/*
+ * Note that we add space for an extra column so that we can handle
+ * row lines connected to the gnd (see twl4030_col_xlate()).
+ */
+#define TWL4030_ROW_SHIFT 4
+#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS << TWL4030_ROW_SHIFT)
struct twl4030_keypad {
unsigned short keymap[TWL4030_KEYMAP_SIZE];
@@ -182,7 +186,7 @@ static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state)
return ret;
}
-static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
+static bool twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
{
int i;
u16 check = 0;
@@ -191,12 +195,12 @@ static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
u16 col = key_state[i];
if ((col & check) && hweight16(col) > 1)
- return 1;
+ return true;
check |= col;
}
- return 0;
+ return false;
}
static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
@@ -225,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
if (!changed)
continue;
- for (col = 0; col < kp->n_cols; col++) {
+ /* Extra column handles "all gnd" rows */
+ for (col = 0; col < kp->n_cols + 1; col++) {
int code;
if (!(changed & (1 << col)))
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
index 4ef764cc493c..ee2bf6bcf291 100644
--- a/drivers/input/keyboard/w90p910_keypad.c
+++ b/drivers/input/keyboard/w90p910_keypad.c
@@ -258,7 +258,7 @@ static struct platform_driver w90p910_keypad_driver = {
.probe = w90p910_keypad_probe,
.remove = __devexit_p(w90p910_keypad_remove),
.driver = {
- .name = "nuc900-keypad",
+ .name = "nuc900-kpi",
.owner = THIS_MODULE,
},
};
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 0ac47d2898ec..4b42ffc0532a 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -69,7 +69,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)
unsigned char nextstate = read_state(lp);
if (lp->laststate != nextstate) {
- int key_down = nextstate <= ARRAY_SIZE(lp->btncode);
+ int key_down = nextstate < ARRAY_SIZE(lp->btncode);
unsigned short keycode = key_down ?
lp->btncode[nextstate] : lp->btncode[lp->laststate];
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index eeb58c1cac16..c714ca2407f8 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -17,7 +17,7 @@ config MOUSE_PS2
default y
select SERIO
select SERIO_LIBPS2
- select SERIO_I8042 if X86 && !X86_MRST
+ select SERIO_I8042 if X86
select SERIO_GSCPS2 if GSC
help
Say Y here if you have a PS/2 mouse connected to your system. This
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 40cea334ad13..705589dc9ac5 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -141,8 +141,13 @@ static int synaptics_capability(struct psmouse *psmouse)
priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
priv->ext_cap = priv->ext_cap_0c = 0;
- if (!SYN_CAP_VALID(priv->capabilities))
+ /*
+ * Older firmwares had submodel ID fixed to 0x47
+ */
+ if (SYN_ID_FULL(priv->identity) < 0x705 &&
+ SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) {
return -1;
+ }
/*
* Unless capExtended is set the rest of the flags should be ignored
@@ -206,6 +211,7 @@ static int synaptics_resolution(struct psmouse *psmouse)
unsigned char max[3];
if (SYN_ID_MAJOR(priv->identity) < 4)
+ return 0;
if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) {
if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) {
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 7d4d5e12c0df..b6aa7d20d8a3 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -47,7 +47,7 @@
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
-#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
+#define SYN_CAP_SUBMODEL_ID(c) (((c) & 0x00ff00) >> 8)
#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16)
@@ -66,6 +66,7 @@
#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f)
#define SYN_ID_MAJOR(i) ((i) & 0x0f)
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
+#define SYN_ID_FULL(i) ((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i))
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
/* synaptics special commands */
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 6168469ad1a6..ed7ad7416b24 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -7,6 +7,10 @@
* the Free Software Foundation.
*/
+#ifdef CONFIG_X86
+#include <asm/x86_init.h>
+#endif
+
/*
* Names.
*/
@@ -166,6 +170,13 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
},
},
{
+ /* Gigabyte Spring Peak - defines wrong chassis type */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
+ },
+ },
+ {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
@@ -840,6 +851,12 @@ static int __init i8042_platform_init(void)
{
int retval;
+#ifdef CONFIG_X86
+ /* Just return if pre-detection shows no i8042 controller exist */
+ if (!x86_platform.i8042_detect())
+ return -ENODEV;
+#endif
+
/*
* On ix86 platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on ix86 boxes.
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index d564af58175c..415f6306105d 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -284,12 +284,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
(data[4] << 20) + (data[5] << 12) +
(data[6] << 4) + (data[7] >> 4);
- wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+ wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
+ ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
- switch (wacom->id[idx]) {
+ switch (wacom->id[idx] & 0xfffff) {
case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */
- case 0x20802: /* Intuos4 Classic Pen */
+ case 0x20802: /* Intuos4 Inking Pen */
case 0x012:
wacom->tool[idx] = BTN_TOOL_PENCIL;
break;
@@ -513,7 +514,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
- if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
+ if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
data[2] | (data[3] & 0x1f) | data[4] | data[8] |
(data[7] & 0x01)) {
input_report_key(input, wacom->tool[1], 1);
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 0d2d7e54b465..5f0221cffef9 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -679,6 +679,13 @@ static int __devinit ad7877_probe(struct spi_device *spi)
return -EINVAL;
}
+ spi->bits_per_word = 16;
+ err = spi_setup(spi);
+ if (err) {
+ dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n");
+ return err;
+ }
+
ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
index cc18265be1a8..7a45d68c3516 100644
--- a/drivers/input/touchscreen/w90p910_ts.c
+++ b/drivers/input/touchscreen/w90p910_ts.c
@@ -233,7 +233,7 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev)
w90p910_ts->state = TS_IDLE;
spin_lock_init(&w90p910_ts->lock);
setup_timer(&w90p910_ts->timer, w90p910_check_pen_up,
- (unsigned long)&w90p910_ts);
+ (unsigned long)w90p910_ts);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index c5016bd2d94f..c3b1dc3a13a0 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
return numbytes;
}
-/* set up next receive skb for data mode
- */
-static void new_rcv_skb(struct bc_state *bcs)
-{
- struct cardstate *cs = bcs->cs;
- unsigned short hw_hdr_len = cs->hw_hdr_len;
-
- if (bcs->ignore) {
- bcs->skb = NULL;
- return;
- }
-
- bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
- if (bcs->skb == NULL) {
- dev_warn(cs->dev, "could not allocate new skb\n");
- return;
- }
- skb_reserve(bcs->skb, hw_hdr_len);
-}
-
/* process a block of received bytes in HDLC data mode
* (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
* Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
@@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
- __u16 fcs = bcs->fcs;
- struct sk_buff *skb = bcs->skb;
+ __u16 fcs = bcs->rx_fcs;
+ struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0;
unsigned char c;
@@ -245,8 +225,7 @@ byte_stuff:
/* prepare reception of next frame */
inputstate &= ~INS_have_data;
- new_rcv_skb(bcs);
- skb = bcs->skb;
+ skb = gigaset_new_rx_skb(bcs);
} else {
/* empty frame (7E 7E) */
#ifdef CONFIG_GIGASET_DEBUG
@@ -255,8 +234,7 @@ byte_stuff:
if (!skb) {
/* skipped (?) */
gigaset_isdn_rcv_err(bcs);
- new_rcv_skb(bcs);
- skb = bcs->skb;
+ skb = gigaset_new_rx_skb(bcs);
}
}
@@ -279,11 +257,11 @@ byte_stuff:
#endif
inputstate |= INS_have_data;
if (skb) {
- if (skb->len == SBUFSIZE) {
+ if (skb->len >= bcs->rx_bufsize) {
dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
/* skip remainder of packet */
- bcs->skb = skb = NULL;
+ bcs->rx_skb = skb = NULL;
} else {
*__skb_put(skb, 1) = c;
fcs = crc_ccitt_byte(fcs, c);
@@ -292,7 +270,7 @@ byte_stuff:
}
bcs->inputstate = inputstate;
- bcs->fcs = fcs;
+ bcs->rx_fcs = fcs;
return procbytes;
}
@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
- struct sk_buff *skb = bcs->skb;
+ struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0;
unsigned char c;
if (!skb) {
/* skip this block */
- new_rcv_skb(bcs);
+ gigaset_new_rx_skb(bcs);
return numbytes;
}
- while (procbytes < numbytes && skb->len < SBUFSIZE) {
+ while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {
c = *src++;
procbytes++;
@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
if (inputstate & INS_have_data) {
gigaset_skb_rcvd(bcs, skb);
inputstate &= ~INS_have_data;
- new_rcv_skb(bcs);
+ gigaset_new_rx_skb(bcs);
}
bcs->inputstate = inputstate;
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 8f78f15c8ef7..6fbe8999c419 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -70,7 +70,7 @@
#define MAX_NUMBER_DIGITS 20
#define MAX_FMT_IE_LEN 20
-/* values for gigaset_capi_appl.connected */
+/* values for bcs->apconnstate */
#define APCONN_NONE 0 /* inactive/listening */
#define APCONN_SETUP 1 /* connecting */
#define APCONN_ACTIVE 2 /* B channel up */
@@ -80,10 +80,10 @@ struct gigaset_capi_appl {
struct list_head ctrlist;
struct gigaset_capi_appl *bcnext;
u16 id;
+ struct capi_register_params rp;
u16 nextMessageNumber;
u32 listenInfoMask;
u32 listenCIPmask;
- int connected;
};
/* CAPI specific controller data structure */
@@ -319,6 +319,39 @@ static const char *format_ie(const char *ie)
return result;
}
+/*
+ * emit DATA_B3_CONF message
+ */
+static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr,
+ u16 appl, u16 msgid, int channel,
+ u16 handle, u16 info)
+{
+ struct sk_buff *cskb;
+ u8 *msg;
+
+ cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
+ if (!cskb) {
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
+ return;
+ }
+ /* frequent message, avoid _cmsg overhead */
+ msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN);
+ CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN);
+ CAPIMSG_SETAPPID(msg, appl);
+ CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3);
+ CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF);
+ CAPIMSG_SETMSGID(msg, msgid);
+ CAPIMSG_SETCONTROLLER(msg, ctr->cnr);
+ CAPIMSG_SETPLCI_PART(msg, channel);
+ CAPIMSG_SETNCCI_PART(msg, 1);
+ CAPIMSG_SETHANDLE_CONF(msg, handle);
+ CAPIMSG_SETINFO_CONF(msg, info);
+
+ /* emit message */
+ dump_rawmsg(DEBUG_MCMD, __func__, msg);
+ capi_ctr_handle_message(ctr, appl, cskb);
+}
+
/*
* driver interface functions
@@ -339,7 +372,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
struct gigaset_capi_ctr *iif = cs->iif;
struct gigaset_capi_appl *ap = bcs->ap;
unsigned char *req = skb_mac_header(dskb);
- struct sk_buff *cskb;
u16 flags;
/* update statistics */
@@ -351,39 +383,22 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
}
/* don't send further B3 messages if disconnected */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
return;
}
- /* ToDo: honor unset "delivery confirmation" bit */
+ /*
+ * send DATA_B3_CONF if "delivery confirmation" bit was set in request;
+ * otherwise it has already been sent by do_data_b3_req()
+ */
flags = CAPIMSG_FLAGS(req);
-
- /* build DATA_B3_CONF message */
- cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
- if (!cskb) {
- dev_err(cs->dev, "%s: out of memory\n", __func__);
- return;
- }
- /* frequent message, avoid _cmsg overhead */
- CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN);
- CAPIMSG_SETAPPID(cskb->data, ap->id);
- CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
- CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF);
- CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
- CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
- CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
- CAPIMSG_SETNCCI_PART(cskb->data, 1);
- CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
- if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
- CAPIMSG_SETINFO_CONF(cskb->data,
- CapiFlagsNotSupportedByProtocol);
- else
- CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR);
-
- /* emit message */
- dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data);
- capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
+ if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)
+ send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req),
+ bcs->channel + 1, CAPIMSG_HANDLE_REQ(req),
+ (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ?
+ CapiFlagsNotSupportedByProtocol :
+ CAPI_NOERROR);
}
EXPORT_SYMBOL_GPL(gigaset_skb_sent);
@@ -412,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
}
/* don't send further B3 messages if disconnected */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
dev_kfree_skb_any(skb);
return;
@@ -484,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
u32 actCIPmask;
struct sk_buff *skb;
unsigned int msgsize;
+ unsigned long flags;
int i;
/*
@@ -608,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
format_ie(iif->hcmsg.CalledPartyNumber));
/* scan application list for matching listeners */
- bcs->ap = NULL;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) {
+ dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+ __func__, bcs->ap, bcs->apconnstate);
+ bcs->ap = NULL;
+ bcs->apconnstate = APCONN_NONE;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);
list_for_each_entry(ap, &iif->appls, ctrlist)
if (actCIPmask & ap->listenCIPmask) {
@@ -626,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
/* add to listeners on this B channel, update state */
+ spin_lock_irqsave(&bcs->aplock, flags);
ap->bcnext = bcs->ap;
bcs->ap = ap;
bcs->chstate |= CHS_NOTIFY_LL;
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
/* emit message */
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -654,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs,
struct gigaset_capi_ctr *iif = cs->iif;
struct sk_buff *skb;
- if (ap->connected == APCONN_NONE)
+ if (bcs->apconnstate == APCONN_NONE)
return;
capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND,
@@ -668,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs,
}
capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
- ap->connected = APCONN_NONE;
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -685,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,
struct sk_buff *skb;
/* nothing to do if no logical connection active */
- if (ap->connected < APCONN_ACTIVE)
+ if (bcs->apconnstate < APCONN_ACTIVE)
return;
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
ap->nextMessageNumber++,
@@ -714,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
- struct gigaset_capi_appl *ap = bcs->ap;
+ struct gigaset_capi_appl *ap;
struct sk_buff *skb;
unsigned int msgsize;
+ unsigned long flags;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ ap = bcs->ap;
if (!ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
return;
}
+ if (bcs->apconnstate == APCONN_NONE) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ dev_warn(cs->dev, "%s: application %u not connected\n",
+ __func__, ap->id);
+ return;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
while (ap->bcnext) {
/* this should never happen */
dev_warn(cs->dev, "%s: dropping extra application %u\n",
@@ -730,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs)
CapiCallGivenToOtherApplication);
ap->bcnext = ap->bcnext->bcnext;
}
- if (ap->connected == APCONN_NONE) {
- dev_warn(cs->dev, "%s: application %u not connected\n",
- __func__, ap->id);
- return;
- }
/* prepare CONNECT_ACTIVE_IND message
* Note: LLC not supported by device
@@ -772,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs)
void gigaset_isdn_hupD(struct bc_state *bcs)
{
struct gigaset_capi_appl *ap;
+ unsigned long flags;
/*
* ToDo: pass on reason code reported by device
* (requires ev-layer state machine extension to collect
* ZCAU device reply)
*/
- for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) {
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ ap = bcs->ap;
+ bcs->ap = ap->bcnext;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_b3_ind(bcs, ap);
send_disconnect_ind(bcs, ap, 0);
+ spin_lock_irqsave(&bcs->aplock, flags);
}
- bcs->ap = NULL;
+ bcs->apconnstate = APCONN_NONE;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
}
/**
@@ -796,24 +833,21 @@ void gigaset_isdn_connB(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
- struct gigaset_capi_appl *ap = bcs->ap;
+ struct gigaset_capi_appl *ap;
struct sk_buff *skb;
+ unsigned long flags;
unsigned int msgsize;
u8 command;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ ap = bcs->ap;
if (!ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
return;
}
- while (ap->bcnext) {
- /* this should never happen */
- dev_warn(cs->dev, "%s: dropping extra application %u\n",
- __func__, ap->bcnext->id);
- send_disconnect_ind(bcs, ap->bcnext,
- CapiCallGivenToOtherApplication);
- ap->bcnext = ap->bcnext->bcnext;
- }
- if (!ap->connected) {
+ if (!bcs->apconnstate) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_warn(cs->dev, "%s: application %u not connected\n",
__func__, ap->id);
return;
@@ -825,13 +859,26 @@ void gigaset_isdn_connB(struct bc_state *bcs)
* CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP
* Parameters in both cases always: NCCI = 1, NCPI empty
*/
- if (ap->connected >= APCONN_ACTIVE) {
+ if (bcs->apconnstate >= APCONN_ACTIVE) {
command = CAPI_CONNECT_B3_ACTIVE;
msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;
} else {
command = CAPI_CONNECT_B3;
msgsize = CAPI_CONNECT_B3_IND_BASELEN;
}
+ bcs->apconnstate = APCONN_ACTIVE;
+
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ while (ap->bcnext) {
+ /* this should never happen */
+ dev_warn(cs->dev, "%s: dropping extra application %u\n",
+ __func__, ap->bcnext->id);
+ send_disconnect_ind(bcs, ap->bcnext,
+ CapiCallGivenToOtherApplication);
+ ap->bcnext = ap->bcnext->bcnext;
+ }
+
capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND,
ap->nextMessageNumber++,
iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16));
@@ -842,7 +889,6 @@ void gigaset_isdn_connB(struct bc_state *bcs)
}
capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
- ap->connected = APCONN_ACTIVE;
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -945,8 +991,64 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
return;
}
ap->id = appl;
+ ap->rp = *rp;
list_add(&ap->ctrlist, &iif->appls);
+ dev_info(cs->dev, "application %u registered\n", ap->id);
+}
+
+/*
+ * remove CAPI application from channel
+ * helper function to keep indentation levels down and stay in 80 columns
+ */
+
+static inline void remove_appl_from_channel(struct bc_state *bcs,
+ struct gigaset_capi_appl *ap)
+{
+ struct cardstate *cs = bcs->cs;
+ struct gigaset_capi_appl *bcap;
+ unsigned long flags;
+ int prevconnstate;
+
+ spin_lock_irqsave(&bcs->aplock, flags);
+ bcap = bcs->ap;
+ if (bcap == NULL) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ return;
+ }
+
+ /* check first application on channel */
+ if (bcap == ap) {
+ bcs->ap = ap->bcnext;
+ if (bcs->ap != NULL) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ return;
+ }
+
+ /* none left, clear channel state */
+ prevconnstate = bcs->apconnstate;
+ bcs->apconnstate = APCONN_NONE;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ if (prevconnstate == APCONN_ACTIVE) {
+ dev_notice(cs->dev, "%s: hanging up channel %u\n",
+ __func__, bcs->channel);
+ gigaset_add_event(cs, &bcs->at_state,
+ EV_HUP, NULL, 0, NULL);
+ gigaset_schedule_event(cs);
+ }
+ return;
+ }
+
+ /* check remaining list */
+ do {
+ if (bcap->bcnext == ap) {
+ bcap->bcnext = bcap->bcnext->bcnext;
+ return;
+ }
+ bcap = bcap->bcnext;
+ } while (bcap != NULL);
+ spin_unlock_irqrestore(&bcs->aplock, flags);
}
/*
@@ -958,19 +1060,19 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl)
= container_of(ctr, struct gigaset_capi_ctr, ctr);
struct cardstate *cs = iif->ctr.driverdata;
struct gigaset_capi_appl *ap, *tmp;
+ unsigned ch;
list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)
if (ap->id == appl) {
- if (ap->connected != APCONN_NONE) {
- dev_err(cs->dev,
- "%s: application %u still connected\n",
- __func__, ap->id);
- /* ToDo: clear active connection */
- }
+ /* remove from any channels */
+ for (ch = 0; ch < cs->channels; ch++)
+ remove_appl_from_channel(&cs->bcs[ch], ap);
+
+ /* remove from registration list */
list_del(&ap->ctrlist);
kfree(ap);
+ dev_info(cs->dev, "application %u released\n", appl);
}
-
}
/*
@@ -1149,7 +1251,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
char **commands;
char *s;
u8 *pp;
- int i, l;
+ unsigned long flags;
+ int i, l, lbc, lhlc;
u16 info;
/* decode message */
@@ -1164,8 +1267,18 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiNoPlciAvailable);
return;
}
+ spin_lock_irqsave(&bcs->aplock, flags);
+ if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE)
+ dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+ __func__, bcs->ap, bcs->apconnstate);
ap->bcnext = NULL;
bcs->ap = ap;
+ bcs->apconnstate = APCONN_SETUP;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ bcs->rx_bufsize = ap->rp.datablklen;
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
/* build command table */
@@ -1273,42 +1386,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
goto error;
}
- /* check/encode parameter: BC */
- if (cmsg->BC && cmsg->BC[0]) {
- /* explicit BC overrides CIP */
- l = 2*cmsg->BC[0] + 7;
+ /*
+ * check/encode parameters: BC & HLC
+ * must be encoded together as device doesn't accept HLC separately
+ * explicit parameters override values derived from CIP
+ */
+
+ /* determine lengths */
+ if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */
+ lbc = 2*cmsg->BC[0];
+ else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */
+ lbc = strlen(cip2bchlc[cmsg->CIPValue].bc);
+ else /* no BC */
+ lbc = 0;
+ if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */
+ lhlc = 2*cmsg->HLC[0];
+ else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */
+ lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc);
+ else /* no HLC */
+ lhlc = 0;
+
+ if (lbc) {
+ /* have BC: allocate and assemble command string */
+ l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */
+ if (lhlc)
+ l += lhlc + 7; /* ";^SHLC=" + value */
commands[AT_BC] = kmalloc(l, GFP_KERNEL);
if (!commands[AT_BC])
goto oom;
strcpy(commands[AT_BC], "^SBC=");
- decode_ie(cmsg->BC, commands[AT_BC]+5);
+ if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */
+ decode_ie(cmsg->BC, commands[AT_BC] + 5);
+ else /* BC derived from CIP */
+ strcpy(commands[AT_BC] + 5,
+ cip2bchlc[cmsg->CIPValue].bc);
+ if (lhlc) {
+ strcpy(commands[AT_BC] + lbc + 5, ";^SHLC=");
+ if (cmsg->HLC && cmsg->HLC[0])
+ /* HLC specified explicitly */
+ decode_ie(cmsg->HLC,
+ commands[AT_BC] + lbc + 12);
+ else /* HLC derived from CIP */
+ strcpy(commands[AT_BC] + lbc + 12,
+ cip2bchlc[cmsg->CIPValue].hlc);
+ }
strcpy(commands[AT_BC] + l - 2, "\r");
- } else if (cip2bchlc[cmsg->CIPValue].bc) {
- l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7;
- commands[AT_BC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_BC])
- goto oom;
- snprintf(commands[AT_BC], l, "^SBC=%s\r",
- cip2bchlc[cmsg->CIPValue].bc);
- }
-
- /* check/encode parameter: HLC */
- if (cmsg->HLC && cmsg->HLC[0]) {
- /* explicit HLC overrides CIP */
- l = 2*cmsg->HLC[0] + 7;
- commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_HLC])
- goto oom;
- strcpy(commands[AT_HLC], "^SHLC=");
- decode_ie(cmsg->HLC, commands[AT_HLC]+5);
- strcpy(commands[AT_HLC] + l - 2, "\r");
- } else if (cip2bchlc[cmsg->CIPValue].hlc) {
- l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7;
- commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_HLC])
- goto oom;
- snprintf(commands[AT_HLC], l, "^SHLC=%s\r",
- cip2bchlc[cmsg->CIPValue].hlc);
+ } else {
+ /* no BC */
+ if (lhlc) {
+ dev_notice(cs->dev, "%s: cannot set HLC without BC\n",
+ "CONNECT_REQ");
+ info = CapiIllMessageParmCoding; /* ? */
+ goto error;
+ }
}
/* check/encode parameter: B Protocol */
@@ -1322,13 +1452,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
bcs->proto2 = L2_HDLC;
break;
case 1:
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
break;
default:
dev_warn(cs->dev,
"B1 Protocol %u unsupported, using Transparent\n",
cmsg->B1protocol);
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
}
if (cmsg->B2protocol != 1)
dev_warn(cs->dev,
@@ -1382,7 +1512,6 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
goto error;
}
gigaset_schedule_event(cs);
- ap->connected = APCONN_SETUP;
send_conf(iif, ap, skb, CapiSuccess);
return;
@@ -1410,6 +1539,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
_cmsg *cmsg = &iif->acmsg;
struct bc_state *bcs;
struct gigaset_capi_appl *oap;
+ unsigned long flags;
int channel;
/* decode message */
@@ -1429,12 +1559,24 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
switch (cmsg->Reject) {
case 0: /* Accept */
/* drop all competing applications, keep only this one */
- for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
- if (oap != ap)
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ oap = bcs->ap;
+ bcs->ap = oap->bcnext;
+ if (oap != ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_ind(bcs, oap,
CapiCallGivenToOtherApplication);
+ spin_lock_irqsave(&bcs->aplock, flags);
+ }
+ }
ap->bcnext = NULL;
bcs->ap = ap;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ bcs->rx_bufsize = ap->rp.datablklen;
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
bcs->chstate |= CHS_NOTIFY_LL;
/* check/encode B channel protocol */
@@ -1448,13 +1590,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
bcs->proto2 = L2_HDLC;
break;
case 1:
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
break;
default:
dev_warn(cs->dev,
"B1 Protocol %u unsupported, using Transparent\n",
cmsg->B1protocol);
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
}
if (cmsg->B2protocol != 1)
dev_warn(cs->dev,
@@ -1502,31 +1644,45 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
send_disconnect_ind(bcs, ap, 0);
/* remove it from the list of listening apps */
+ spin_lock_irqsave(&bcs->aplock, flags);
if (bcs->ap == ap) {
bcs->ap = ap->bcnext;
- if (bcs->ap == NULL)
+ if (bcs->ap == NULL) {
/* last one: stop ev-layer hupD notifications */
+ bcs->apconnstate = APCONN_NONE;
bcs->chstate &= ~CHS_NOTIFY_LL;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
return;
}
for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) {
if (oap->bcnext == ap) {
oap->bcnext = oap->bcnext->bcnext;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
return;
}
}
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: application %u not found\n",
__func__, ap->id);
return;
default: /* Reject */
/* drop all competing applications, keep only this one */
- for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
- if (oap != ap)
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ oap = bcs->ap;
+ bcs->ap = oap->bcnext;
+ if (oap != ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_ind(bcs, oap,
CapiCallGivenToOtherApplication);
+ spin_lock_irqsave(&bcs->aplock, flags);
+ }
+ }
ap->bcnext = NULL;
bcs->ap = ap;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
/* reject call - will trigger DISCONNECT_IND for this app */
dev_info(cs->dev, "%s: Reject=%x\n",
@@ -1549,6 +1705,7 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
{
struct cardstate *cs = iif->ctr.driverdata;
_cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
/* decode message */
@@ -1563,9 +1720,10 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
/* mark logical connection active */
- ap->connected = APCONN_ACTIVE;
+ bcs->apconnstate = APCONN_ACTIVE;
/* build NCCI: always 1 (one B3 connection only) */
cmsg->adr.adrNCCI |= 1 << 16;
@@ -1611,7 +1769,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
if (cmsg->Reject) {
/* Reject: clear B3 connect received flag */
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
/* trigger hangup, causing eventual DISCONNECT_IND */
if (!gigaset_add_event(cs, &bcs->at_state,
@@ -1683,11 +1841,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
}
/* skip if DISCONNECT_IND already sent */
- if (!ap->connected)
+ if (!bcs->apconnstate)
return;
/* check for active logical connection */
- if (ap->connected >= APCONN_ACTIVE) {
+ if (bcs->apconnstate >= APCONN_ACTIVE) {
/*
* emit DISCONNECT_B3_IND with cause 0x3301
* use separate cmsg structure, as the content of iif->acmsg
@@ -1736,6 +1894,7 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
{
struct cardstate *cs = iif->ctr.driverdata;
_cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
/* decode message */
@@ -1751,17 +1910,17 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
/* reject if logical connection not active */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
send_conf(iif, ap, skb,
CapiMessageNotSupportedInCurrentState);
return;
}
/* trigger hangup, causing eventual DISCONNECT_B3_IND */
- if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
- EV_HUP, NULL, 0, NULL)) {
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
@@ -1782,11 +1941,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ struct bc_state *bcs;
int channel = CAPIMSG_PLCI_PART(skb->data);
u16 ncci = CAPIMSG_NCCI_PART(skb->data);
u16 msglen = CAPIMSG_LEN(skb->data);
u16 datalen = CAPIMSG_DATALEN(skb->data);
u16 flags = CAPIMSG_FLAGS(skb->data);
+ u16 msgid = CAPIMSG_MSGID(skb->data);
+ u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
/* frequent message, avoid _cmsg overhead */
dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
@@ -1802,6 +1964,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64)
dev_notice(cs->dev, "%s: unexpected length %d\n",
"DATA_B3_REQ", msglen);
@@ -1821,7 +1984,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
}
/* reject if logical connection not active */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
return;
}
@@ -1832,17 +1995,19 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
skb_pull(skb, msglen);
/* pass to device-specific module */
- if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
+ if (cs->ops->send_skb(bcs, skb) < 0) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
- /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */
-
/*
- * ToDo: honor unset "delivery confirmation" bit
- * (send DATA_B3_CONF immediately?)
+ * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery
+ * confirmation" bit is set; otherwise we have to send it now
*/
+ if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION))
+ send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle,
+ flags ? CapiFlagsNotSupportedByProtocol
+ : CAPI_NOERROR);
}
/*
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index f6f45f221920..5d4befb81057 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs)
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
+ dev_kfree_skb(bcs->rx_skb);
+ bcs->rx_skb = NULL;
for (i = 0; i < AT_NUM; ++i) {
kfree(bcs->commands[i]);
@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->emptycount = 0;
#endif
- gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_bufsize = 0;
+ bcs->rx_skb = NULL;
+ bcs->rx_fcs = PPP_INITFCS;
bcs->inputstate = 0;
- if (cs->ignoreframes) {
- bcs->skb = NULL;
- } else {
- bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (bcs->skb != NULL)
- skb_reserve(bcs->skb, cs->hw_hdr_len);
- else
- pr_err("out of memory\n");
- }
-
bcs->channel = channel;
bcs->cs = cs;
@@ -658,16 +649,15 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
for (i = 0; i < AT_NUM; ++i)
bcs->commands[i] = NULL;
+ spin_lock_init(&bcs->aplock);
+ bcs->ap = NULL;
+ bcs->apconnstate = 0;
+
gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
if (cs->ops->initbcshw(bcs))
return bcs;
gig_dbg(DEBUG_INIT, " failed");
-
- gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
-
return NULL;
}
@@ -839,14 +829,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
bcs->emptycount = 0;
#endif
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_fcs = PPP_INITFCS;
bcs->chstate = 0;
bcs->ignore = cs->ignoreframes;
- if (bcs->ignore) {
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
- }
+ dev_kfree_skb(bcs->rx_skb);
+ bcs->rx_skb = NULL;
cs->ops->reinitbcshw(bcs);
}
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 206c380c5235..ceaef9a04a42 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] =
/* dial */
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} },
-{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} },
-{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
-{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
+{RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD+AT_PROTO} },
{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} },
{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} },
{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} },
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 05947f9c1849..8738b0821fc9 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -45,10 +45,6 @@
#define MAX_EVENTS 64 /* size of event queue */
#define RBUFSIZE 8192
-#define SBUFSIZE 4096 /* sk_buff payload size */
-
-#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
-#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
/* compile time options */
#define GIG_MAJOR 0
@@ -190,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define AT_BC 3
#define AT_PROTO 4
#define AT_TYPE 5
-#define AT_HLC 6
-#define AT_CLIP 7
+#define AT_CLIP 6
/* total number */
-#define AT_NUM 8
+#define AT_NUM 7
/* variables in struct at_state_t */
#define VAR_ZSAU 0
@@ -380,8 +375,10 @@ struct bc_state {
struct at_state_t at_state;
- __u16 fcs;
- struct sk_buff *skb;
+ /* receive buffer */
+ unsigned rx_bufsize; /* max size accepted by application */
+ struct sk_buff *rx_skb;
+ __u16 rx_fcs;
int inputstate; /* see INS_XXXX */
int channel;
@@ -406,7 +403,9 @@ struct bc_state {
struct bas_bc_state *bas; /* usb hardware driver (base) */
} hw;
- void *ap; /* LL application structure */
+ void *ap; /* associated LL application */
+ int apconnstate; /* LL application connection state */
+ spinlock_t aplock;
};
struct cardstate {
@@ -801,8 +800,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
gigaset_schedule_event(bcs->cs);
}
-/* handling routines for sk_buff */
-/* ============================= */
+/* set up next receive skb for data mode */
+static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs)
+{
+ struct cardstate *cs = bcs->cs;
+ unsigned short hw_hdr_len = cs->hw_hdr_len;
+
+ if (bcs->ignore) {
+ bcs->rx_skb = NULL;
+ } else {
+ bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len);
+ if (bcs->rx_skb == NULL)
+ dev_warn(cs->dev, "could not allocate skb\n");
+ else
+ skb_reserve(bcs->rx_skb, hw_hdr_len);
+ }
+ return bcs->rx_skb;
+}
/* append received bytes to inbuf */
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index c22e5ace8276..f01c3c2e2e46 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -16,7 +16,10 @@
#include "gigaset.h"
#include <linux/isdnif.h>
+#define SBUFSIZE 4096 /* sk_buff payload size */
+#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
#define HW_HDR_LEN 2 /* Header size used to store ack info */
+#define MAX_BUF_SIZE (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */
/* == Handling of I4L IO =====================================================*/
@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY;
}
+ switch (bcs->proto2) {
+ case L2_HDLC:
+ bcs->rx_bufsize = SBUFSIZE;
+ break;
+ default: /* assume transparent */
+ bcs->rx_bufsize = TRANSBUFSIZE;
+ }
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
if (!commands) {
@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
return -EINVAL;
}
bcs = cs->bcs + ch;
+ switch (bcs->proto2) {
+ case L2_HDLC:
+ bcs->rx_bufsize = SBUFSIZE;
+ break;
+ default: /* assume transparent */
+ bcs->rx_bufsize = TRANSBUFSIZE;
+ }
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
if (!gigaset_add_event(cs, &bcs->at_state,
EV_ACCEPT, NULL, 0, NULL))
return -ENOMEM;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 16fd3bd48883..2dfd346fc889 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
*/
static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
{
- bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
- if (unlikely(bcs->skb == NULL)) {
+ bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
+ if (bcs->rx_skb == NULL)
/* skipping */
return;
- }
- if (unlikely(bcs->skb->len == SBUFSIZE)) {
+ if (bcs->rx_skb->len >= bcs->rx_bufsize) {
dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
bcs->hw.bas->giants++;
- dev_kfree_skb_any(bcs->skb);
- bcs->skb = NULL;
+ dev_kfree_skb_any(bcs->rx_skb);
+ bcs->rx_skb = NULL;
return;
}
- *__skb_put(bcs->skb, 1) = c;
+ *__skb_put(bcs->rx_skb, 1) = c;
}
/* hdlc_flush
@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
static inline void hdlc_flush(struct bc_state *bcs)
{
/* clear skb or allocate new if not skipping */
- if (likely(bcs->skb != NULL))
- skb_trim(bcs->skb, 0);
- else if (!bcs->ignore) {
- bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
- if (bcs->skb)
- skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
- else
- dev_err(bcs->cs->dev, "could not allocate skb\n");
- }
+ if (bcs->rx_skb != NULL)
+ skb_trim(bcs->rx_skb, 0);
+ else
+ gigaset_new_rx_skb(bcs);
/* reset packet state */
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_fcs = PPP_INITFCS;
}
/* hdlc_done
@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs)
hdlc_flush(bcs);
return;
}
- procskb = bcs->skb;
+ procskb = bcs->rx_skb;
if (procskb == NULL) {
/* previous error */
gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs)
bcs->hw.bas->runts++;
dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
- } else if (bcs->fcs != PPP_GOODFCS) {
- dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
+ } else if (bcs->rx_fcs != PPP_GOODFCS) {
+ dev_notice(cs->dev, "frame check error\n");
bcs->hw.bas->fcserrs++;
dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs)
bcs->hw.bas->goodbytes += len;
gigaset_skb_rcvd(bcs, procskb);
}
-
- bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (bcs->skb)
- skb_reserve(bcs->skb, cs->hw_hdr_len);
- else
- dev_err(cs->dev, "could not allocate skb\n");
- bcs->fcs = PPP_INITFCS;
+ gigaset_new_rx_skb(bcs);
+ bcs->rx_fcs = PPP_INITFCS;
}
/* hdlc_frag
@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
bcs->hw.bas->alignerrs++;
gigaset_isdn_rcv_err(bcs);
- __skb_trim(bcs->skb, 0);
- bcs->fcs = PPP_INITFCS;
+ __skb_trim(bcs->rx_skb, 0);
+ bcs->rx_fcs = PPP_INITFCS;
}
/* bit counts lookup table for HDLC bit unstuffing
@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
static inline void trans_receive(unsigned char *src, unsigned count,
struct bc_state *bcs)
{
- struct cardstate *cs = bcs->cs;
struct sk_buff *skb;
int dobytes;
unsigned char *dst;
@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count,
hdlc_flush(bcs);
return;
}
- skb = bcs->skb;
- if (unlikely(skb == NULL)) {
- bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (!skb) {
- dev_err(cs->dev, "could not allocate skb\n");
- return;
- }
- skb_reserve(skb, cs->hw_hdr_len);
- }
+ skb = bcs->rx_skb;
+ if (skb == NULL)
+ skb = gigaset_new_rx_skb(bcs);
bcs->hw.bas->goodbytes += skb->len;
- dobytes = TRANSBUFSIZE - skb->len;
+ dobytes = bcs->rx_bufsize - skb->len;
while (count > 0) {
dst = skb_put(skb, count < dobytes ? count : dobytes);
while (count > 0 && dobytes > 0) {
@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count,
dump_bytes(DEBUG_STREAM_DUMP,
"rcv data", skb->data, skb->len);
gigaset_skb_rcvd(bcs, skb);
- bcs->skb = skb =
- dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (!skb) {
- dev_err(cs->dev, "could not allocate skb\n");
+ skb = gigaset_new_rx_skb(bcs);
+ if (skb == NULL)
return;
- }
- skb_reserve(skb, cs->hw_hdr_len);
- dobytes = TRANSBUFSIZE;
+ dobytes = bcs->rx_bufsize;
}
}
}
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index 72eb92647c1b..feec8d89d719 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -187,12 +187,13 @@ void
hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
{
struct net_local *lp = card->netif;
- struct net_device *dev = lp->dev;
+ struct net_device *dev;
struct sk_buff *skb;
if (!lp)
return; /* non existing device */
+ dev = lp->dev;
dev->stats.rx_bytes += len;
skb = dev_alloc_skb(len);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 81bf25e67ce1..e4112622e5a2 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -302,6 +302,15 @@ config LEDS_MC13783
This option enable support for on-chip LED drivers found
on Freescale Semiconductor MC13783 PMIC.
+config LEDS_NS2
+ tristate "LED support for Network Space v2 GPIO LEDs"
+ depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2
+ default y
+ help
+ This option enable support for the dual-GPIO LED found on the
+ Network Space v2 board (and parents). This include Internet Space v2,
+ Network Space (Max) v2 and d2 Network v2 boards.
+
config LEDS_TRIGGERS
bool "LED Trigger support"
help
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 2493de499374..7d6b95831f8e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
+obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
new file mode 100644
index 000000000000..74dce4ba0262
--- /dev/null
+++ b/drivers/leds/leds-ns2.c
@@ -0,0 +1,338 @@
+/*
+ * leds-ns2.c - Driver for the Network Space v2 (and parents) dual-GPIO LED
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.com>
+ *
+ * Based on leds-gpio.c by Raphael Assenat <raph@8d.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <mach/leds-ns2.h>
+
+/*
+ * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
+ * relation with the SATA activity. This capability is exposed through the
+ * "sata" sysfs attribute.
+ *
+ * The following array detail the different LED registers and the combination
+ * of their possible values:
+ *
+ * cmd_led | slow_led | /SATA active | LED state
+ * | | |
+ * 1 | 0 | x | off
+ * - | 1 | x | on
+ * 0 | 0 | 1 | on
+ * 0 | 0 | 0 | blink (rate 300ms)
+ */
+
+enum ns2_led_modes {
+ NS_V2_LED_OFF,
+ NS_V2_LED_ON,
+ NS_V2_LED_SATA,
+};
+
+struct ns2_led_mode_value {
+ enum ns2_led_modes mode;
+ int cmd_level;
+ int slow_level;
+};
+
+static struct ns2_led_mode_value ns2_led_modval[] = {
+ { NS_V2_LED_OFF , 1, 0 },
+ { NS_V2_LED_ON , 0, 1 },
+ { NS_V2_LED_ON , 1, 1 },
+ { NS_V2_LED_SATA, 0, 0 },
+};
+
+struct ns2_led_data {
+ struct led_classdev cdev;
+ unsigned cmd;
+ unsigned slow;
+ unsigned char sata; /* True when SATA mode active. */
+ rwlock_t rw_lock; /* Lock GPIOs. */
+};
+
+static int ns2_led_get_mode(struct ns2_led_data *led_dat,
+ enum ns2_led_modes *mode)
+{
+ int i;
+ int ret = -EINVAL;
+ int cmd_level;
+ int slow_level;
+
+ read_lock(&led_dat->rw_lock);
+
+ cmd_level = gpio_get_value(led_dat->cmd);
+ slow_level = gpio_get_value(led_dat->slow);
+
+ for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) {
+ if (cmd_level == ns2_led_modval[i].cmd_level &&
+ slow_level == ns2_led_modval[i].slow_level) {
+ *mode = ns2_led_modval[i].mode;
+ ret = 0;
+ break;
+ }
+ }
+
+ read_unlock(&led_dat->rw_lock);
+
+ return ret;
+}
+
+static void ns2_led_set_mode(struct ns2_led_data *led_dat,
+ enum ns2_led_modes mode)
+{
+ int i;
+
+ write_lock(&led_dat->rw_lock);
+
+ for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) {
+ if (mode == ns2_led_modval[i].mode) {
+ gpio_set_value(led_dat->cmd,
+ ns2_led_modval[i].cmd_level);
+ gpio_set_value(led_dat->slow,
+ ns2_led_modval[i].slow_level);
+ }
+ }
+
+ write_unlock(&led_dat->rw_lock);
+}
+
+static void ns2_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct ns2_led_data *led_dat =
+ container_of(led_cdev, struct ns2_led_data, cdev);
+ enum ns2_led_modes mode;
+
+ if (value == LED_OFF)
+ mode = NS_V2_LED_OFF;
+ else if (led_dat->sata)
+ mode = NS_V2_LED_SATA;
+ else
+ mode = NS_V2_LED_ON;
+
+ ns2_led_set_mode(led_dat, mode);
+}
+
+static ssize_t ns2_led_sata_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buff, size_t count)
+{
+ int ret;
+ unsigned long enable;
+ enum ns2_led_modes mode;
+ struct ns2_led_data *led_dat = dev_get_drvdata(dev);
+
+ ret = strict_strtoul(buff, 10, &enable);
+ if (ret < 0)
+ return ret;
+
+ enable = !!enable;
+
+ if (led_dat->sata == enable)
+ return count;
+
+ ret = ns2_led_get_mode(led_dat, &mode);
+ if (ret < 0)
+ return ret;
+
+ if (enable && mode == NS_V2_LED_ON)
+ ns2_led_set_mode(led_dat, NS_V2_LED_SATA);
+ if (!enable && mode == NS_V2_LED_SATA)
+ ns2_led_set_mode(led_dat, NS_V2_LED_ON);
+
+ led_dat->sata = enable;
+
+ return count;
+}
+
+static ssize_t ns2_led_sata_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ns2_led_data *led_dat = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", led_dat->sata);
+}
+
+static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
+
+static int __devinit
+create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
+ const struct ns2_led *template)
+{
+ int ret;
+ enum ns2_led_modes mode;
+
+ ret = gpio_request(template->cmd, template->name);
+ if (ret == 0) {
+ ret = gpio_direction_output(template->cmd,
+ gpio_get_value(template->cmd));
+ if (ret)
+ gpio_free(template->cmd);
+ }
+ if (ret) {
+ dev_err(&pdev->dev, "%s: failed to setup command GPIO\n",
+ template->name);
+ }
+
+ ret = gpio_request(template->slow, template->name);
+ if (ret == 0) {
+ ret = gpio_direction_output(template->slow,
+ gpio_get_value(template->slow));
+ if (ret)
+ gpio_free(template->slow);
+ }
+ if (ret) {
+ dev_err(&pdev->dev, "%s: failed to setup slow GPIO\n",
+ template->name);
+ goto err_free_cmd;
+ }
+
+ rwlock_init(&led_dat->rw_lock);
+
+ led_dat->cdev.name = template->name;
+ led_dat->cdev.default_trigger = template->default_trigger;
+ led_dat->cdev.blink_set = NULL;
+ led_dat->cdev.brightness_set = ns2_led_set;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ led_dat->cmd = template->cmd;
+ led_dat->slow = template->slow;
+
+ ret = ns2_led_get_mode(led_dat, &mode);
+ if (ret < 0)
+ goto err_free_slow;
+
+ /* Set LED initial state. */
+ led_dat->sata = (mode == NS_V2_LED_SATA) ? 1 : 0;
+ led_dat->cdev.brightness =
+ (mode == NS_V2_LED_OFF) ? LED_OFF : LED_FULL;
+
+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+ if (ret < 0)
+ goto err_free_slow;
+
+ dev_set_drvdata(led_dat->cdev.dev, led_dat);
+ ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
+ if (ret < 0)
+ goto err_free_cdev;
+
+ return 0;
+
+err_free_cdev:
+ led_classdev_unregister(&led_dat->cdev);
+err_free_slow:
+ gpio_free(led_dat->slow);
+err_free_cmd:
+ gpio_free(led_dat->cmd);
+
+ return ret;
+}
+
+static void __devexit delete_ns2_led(struct ns2_led_data *led_dat)
+{
+ device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
+ led_classdev_unregister(&led_dat->cdev);
+ gpio_free(led_dat->cmd);
+ gpio_free(led_dat->slow);
+}
+
+static int __devinit ns2_led_probe(struct platform_device *pdev)
+{
+ struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
+ struct ns2_led_data *leds_data;
+ int i;
+ int ret;
+
+ if (!pdata)
+ return -EINVAL;
+
+ leds_data = kzalloc(sizeof(struct ns2_led_data) *
+ pdata->num_leds, GFP_KERNEL);
+ if (!leds_data)
+ return -ENOMEM;
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]);
+ if (ret < 0)
+ goto err;
+
+ }
+
+ platform_set_drvdata(pdev, leds_data);
+
+ return 0;
+
+err:
+ for (i = i - 1; i >= 0; i--)
+ delete_ns2_led(&leds_data[i]);
+
+ kfree(leds_data);
+
+ return ret;
+}
+
+static int __devexit ns2_led_remove(struct platform_device *pdev)
+{
+ int i;
+ struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
+ struct ns2_led_data *leds_data;
+
+ leds_data = platform_get_drvdata(pdev);
+
+ for (i = 0; i < pdata->num_leds; i++)
+ delete_ns2_led(&leds_data[i]);
+
+ kfree(leds_data);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver ns2_led_driver = {
+ .probe = ns2_led_probe,
+ .remove = __devexit_p(ns2_led_remove),
+ .driver = {
+ .name = "leds-ns2",
+ .owner = THIS_MODULE,
+ },
+};
+MODULE_ALIAS("platform:leds-ns2");
+
+static int __init ns2_led_init(void)
+{
+ return platform_driver_register(&ns2_led_driver);
+}
+
+static void __exit ns2_led_exit(void)
+{
+ platform_driver_unregister(&ns2_led_driver);
+}
+
+module_init(ns2_led_init);
+module_exit(ns2_led_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("Network Space v2 LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 46b3a044eadf..cb20d0b0555a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
/* First make sure individual recovery_offsets are correct */
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk >= 0 &&
+ mddev->delta_disks >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
mddev->curr_resync_completed > rdev->recovery_offset)
rdev->recovery_offset = mddev->curr_resync_completed;
@@ -3001,6 +3002,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
return -EINVAL;
}
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ rdev->new_raid_disk = rdev->raid_disk;
+
/* ->takeover must set new_* and/or delta_disks
* if it succeeds, and may set them when it fails.
*/
@@ -3051,13 +3055,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
mddev->safemode = 0;
}
- module_put(mddev->pers->owner);
- /* Invalidate devices that are now superfluous */
- list_for_each_entry(rdev, &mddev->disks, same_set)
- if (rdev->raid_disk >= mddev->raid_disks) {
- rdev->raid_disk = -1;
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ char nm[20];
+ if (rdev->raid_disk < 0)
+ continue;
+ if (rdev->new_raid_disk > mddev->raid_disks)
+ rdev->new_raid_disk = -1;
+ if (rdev->new_raid_disk == rdev->raid_disk)
+ continue;
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_remove_link(&mddev->kobj, nm);
+ }
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ if (rdev->raid_disk < 0)
+ continue;
+ if (rdev->new_raid_disk == rdev->raid_disk)
+ continue;
+ rdev->raid_disk = rdev->new_raid_disk;
+ if (rdev->raid_disk < 0)
clear_bit(In_sync, &rdev->flags);
+ else {
+ char nm[20];
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+ printk("md: cannot register %s for %s after level change\n",
+ nm, mdname(mddev));
}
+ }
+
+ module_put(mddev->pers->owner);
mddev->pers = pers;
mddev->private = priv;
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
@@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
atomic_inc(&mddev->openers);
mutex_unlock(&mddev->open_mutex);
+ check_disk_size_change(mddev->gendisk, bdev);
out:
return err;
}
@@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev)
rcu_read_lock();
list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
+ mddev->delta_disks >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < mddev->curr_resync)
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 7ab5ea155452..10597bfec000 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -78,6 +78,9 @@ struct mdk_rdev_s
int desc_nr; /* descriptor index in the superblock */
int raid_disk; /* role of device in array */
+ int new_raid_disk; /* role that the device will have in
+ * the array after a level-change completes.
+ */
int saved_raid_disk; /* role that device used to have in the
* array and could again if we did a partial
* resync from the bitmap
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index e70f004c99e8..563abed5a2cb 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -173,9 +173,11 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
list_for_each_entry(rdev1, &mddev->disks, same_set) {
int j = rdev1->raid_disk;
- if (mddev->level == 10)
+ if (mddev->level == 10) {
/* taking over a raid10-n2 array */
j /= 2;
+ rdev1->new_raid_disk = j;
+ }
if (j < 0 || j >= mddev->raid_disks) {
printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
@@ -361,12 +363,6 @@ static int raid0_run(mddev_t *mddev)
mddev->private = conf;
}
conf = mddev->private;
- if (conf->scale_raid_disks) {
- int i;
- for (i=0; i < conf->strip_zone[0].nb_dev; i++)
- conf->devlist[i]->raid_disk /= conf->scale_raid_disks;
- /* FIXME update sysfs rd links */
- }
/* calculate array device size */
md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
@@ -573,7 +569,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
return;
}
-static void *raid0_takeover_raid5(mddev_t *mddev)
+static void *raid0_takeover_raid45(mddev_t *mddev)
{
mdk_rdev_t *rdev;
raid0_conf_t *priv_conf;
@@ -596,6 +592,7 @@ static void *raid0_takeover_raid5(mddev_t *mddev)
/* Set new parameters */
mddev->new_level = 0;
+ mddev->new_layout = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->raid_disks--;
mddev->delta_disks = -1;
@@ -635,6 +632,7 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
/* Set new parameters */
mddev->new_level = 0;
+ mddev->new_layout = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = - mddev->raid_disks / 2;
mddev->raid_disks += mddev->delta_disks;
@@ -643,19 +641,22 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
mddev->recovery_cp = MaxSector;
create_strip_zones(mddev, &priv_conf);
- priv_conf->scale_raid_disks = 2;
return priv_conf;
}
static void *raid0_takeover(mddev_t *mddev)
{
/* raid0 can take over:
+ * raid4 - if all data disks are active.
* raid5 - providing it is Raid4 layout and one disk is faulty
* raid10 - assuming we have all necessary active disks
*/
+ if (mddev->level == 4)
+ return raid0_takeover_raid45(mddev);
+
if (mddev->level == 5) {
if (mddev->layout == ALGORITHM_PARITY_N)
- return raid0_takeover_raid5(mddev);
+ return raid0_takeover_raid45(mddev);
printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
mdname(mddev), ALGORITHM_PARITY_N);
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index d724e664ca4d..91f8e876ee64 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -13,9 +13,6 @@ struct raid0_private_data
struct strip_zone *strip_zone;
mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
int nr_strip_zones;
- int scale_raid_disks; /* divide rdev->raid_disks by this in run()
- * to handle conversion from raid10
- */
};
typedef struct raid0_private_data raid0_conf_t;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 03724992cdf2..42e64e4e5e25 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
int sectors = r10_bio->sectors;
mdk_rdev_t*rdev;
int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
+ int d = r10_bio->devs[r10_bio->read_slot].devnum;
rcu_read_lock();
- {
- int d = r10_bio->devs[r10_bio->read_slot].devnum;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
+ if (rdev) { /* If rdev is not NULL */
char b[BDEVNAME_SIZE];
int cur_read_error_count = 0;
- rdev = rcu_dereference(conf->mirrors[d].rdev);
bdevname(rdev->bdev, b);
if (test_bit(Faulty, &rdev->flags)) {
@@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
rcu_read_lock();
do {
- int d = r10_bio->devs[sl].devnum;
+ d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
@@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
rcu_read_lock();
while (sl != r10_bio->read_slot) {
char b[BDEVNAME_SIZE];
- int d;
+
if (sl==0)
sl = conf->copies;
sl--;
@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
}
sl = start;
while (sl != r10_bio->read_slot) {
- int d;
+
if (sl==0)
sl = conf->copies;
sl--;
@@ -2161,22 +2161,22 @@ static conf_t *setup_conf(mddev_t *mddev)
sector_t stride, size;
int err = -EINVAL;
- if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
- !is_power_of_2(mddev->chunk_sectors)) {
+ if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
+ !is_power_of_2(mddev->new_chunk_sectors)) {
printk(KERN_ERR "md/raid10:%s: chunk size must be "
"at least PAGE_SIZE(%ld) and be a power of 2.\n",
mdname(mddev), PAGE_SIZE);
goto out;
}
- nc = mddev->layout & 255;
- fc = (mddev->layout >> 8) & 255;
- fo = mddev->layout & (1<<16);
+ nc = mddev->new_layout & 255;
+ fc = (mddev->new_layout >> 8) & 255;
+ fo = mddev->new_layout & (1<<16);
if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
- (mddev->layout >> 17)) {
+ (mddev->new_layout >> 17)) {
printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
- mdname(mddev), mddev->layout);
+ mdname(mddev), mddev->new_layout);
goto out;
}
@@ -2241,7 +2241,6 @@ static conf_t *setup_conf(mddev_t *mddev)
if (!conf->thread)
goto out;
- conf->scale_disks = 0;
conf->mddev = mddev;
return conf;
@@ -2300,11 +2299,6 @@ static int run(mddev_t *mddev)
if (disk_idx >= conf->raid_disks
|| disk_idx < 0)
continue;
- if (conf->scale_disks) {
- disk_idx *= conf->scale_disks;
- rdev->raid_disk = disk_idx;
- /* MOVE 'rd%d' link !! */
- }
disk = conf->mirrors + disk_idx;
disk->rdev = rdev;
@@ -2435,26 +2429,22 @@ static void *raid10_takeover_raid0(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
- /* Update slot numbers to obtain
- * degraded raid10 with missing mirrors
- */
- list_for_each_entry(rdev, &mddev->disks, same_set) {
- rdev->raid_disk *= 2;
- }
-
/* Set new parameters */
mddev->new_level = 10;
/* new layout: far_copies = 1, near_copies = 2 */
mddev->new_layout = (1<<8) + 2;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = mddev->raid_disks;
- mddev->degraded = mddev->raid_disks;
mddev->raid_disks *= 2;
/* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector;
conf = setup_conf(mddev);
- conf->scale_disks = 2;
+ if (!IS_ERR(conf))
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (rdev->raid_disk >= 0)
+ rdev->new_raid_disk = rdev->raid_disk * 2;
+
return conf;
}
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 3824a087e17c..2316ac2e8e21 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -38,11 +38,6 @@ struct r10_private_data_s {
int chunk_shift; /* shift from chunks to sectors */
sector_t chunk_mask;
- int scale_disks; /* When starting array, multiply
- * each ->raid_disk by this.
- * Need for raid0->raid10 migration
- */
-
struct list_head retry_list;
/* queue pending writes and submit them on unplug */
struct bio_list pending_bio_list;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index d2c0f94fa37d..96c690279fc6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -277,12 +277,13 @@ out:
return sh;
}
-static void shrink_buffers(struct stripe_head *sh, int num)
+static void shrink_buffers(struct stripe_head *sh)
{
struct page *p;
int i;
+ int num = sh->raid_conf->pool_size;
- for (i=0; i<num ; i++) {
+ for (i = 0; i < num ; i++) {
p = sh->dev[i].page;
if (!p)
continue;
@@ -291,11 +292,12 @@ static void shrink_buffers(struct stripe_head *sh, int num)
}
}
-static int grow_buffers(struct stripe_head *sh, int num)
+static int grow_buffers(struct stripe_head *sh)
{
int i;
+ int num = sh->raid_conf->pool_size;
- for (i=0; i<num; i++) {
+ for (i = 0; i < num; i++) {
struct page *page;
if (!(page = alloc_page(GFP_KERNEL))) {
@@ -364,6 +366,73 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
return NULL;
}
+/*
+ * Need to check if array has failed when deciding whether to:
+ * - start an array
+ * - remove non-faulty devices
+ * - add a spare
+ * - allow a reshape
+ * This determination is simple when no reshape is happening.
+ * However if there is a reshape, we need to carefully check
+ * both the before and after sections.
+ * This is because some failed devices may only affect one
+ * of the two sections, and some non-in_sync devices may
+ * be insync in the section most affected by failed devices.
+ */
+static int has_failed(raid5_conf_t *conf)
+{
+ int degraded;
+ int i;
+ if (conf->mddev->reshape_position == MaxSector)
+ return conf->mddev->degraded > conf->max_degraded;
+
+ rcu_read_lock();
+ degraded = 0;
+ for (i = 0; i < conf->previous_raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (test_bit(In_sync, &rdev->flags))
+ ;
+ else
+ /* not in-sync or faulty.
+ * If the reshape increases the number of devices,
+ * this is being recovered by the reshape, so
+ * this 'previous' section is not in_sync.
+ * If the number of devices is being reduced however,
+ * the device can only be part of the array if
+ * we are reverting a reshape, so this section will
+ * be in-sync.
+ */
+ if (conf->raid_disks >= conf->previous_raid_disks)
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (degraded > conf->max_degraded)
+ return 1;
+ rcu_read_lock();
+ degraded = 0;
+ for (i = 0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (test_bit(In_sync, &rdev->flags))
+ ;
+ else
+ /* not in-sync or faulty.
+ * If reshape increases the number of devices, this
+ * section has already been recovered, else it
+ * almost certainly hasn't.
+ */
+ if (conf->raid_disks <= conf->previous_raid_disks)
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (degraded > conf->max_degraded)
+ return 1;
+ return 0;
+}
+
static void unplug_slaves(mddev_t *mddev);
static void raid5_unplug_device(struct request_queue *q);
@@ -1240,19 +1309,18 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
static int grow_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
- int disks = max(conf->raid_disks, conf->previous_raid_disks);
sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
if (!sh)
return 0;
- memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev));
+ memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev));
sh->raid_conf = conf;
spin_lock_init(&sh->lock);
#ifdef CONFIG_MULTICORE_RAID456
init_waitqueue_head(&sh->ops.wait_for_ops);
#endif
- if (grow_buffers(sh, disks)) {
- shrink_buffers(sh, disks);
+ if (grow_buffers(sh)) {
+ shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
return 0;
}
@@ -1468,7 +1536,7 @@ static int drop_one_stripe(raid5_conf_t *conf)
if (!sh)
return 0;
BUG_ON(atomic_read(&sh->count));
- shrink_buffers(sh, conf->pool_size);
+ shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
return 1;
@@ -2963,7 +3031,6 @@ static void handle_stripe5(struct stripe_head *sh)
mdk_rdev_t *rdev;
dev = &sh->dev[i];
- clear_bit(R5_Insync, &dev->flags);
pr_debug("check %d: state 0x%lx toread %p read %p write %p "
"written %p\n", i, dev->flags, dev->toread, dev->read,
@@ -3000,17 +3067,27 @@ static void handle_stripe5(struct stripe_head *sh)
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ clear_bit(R5_Insync, &dev->flags);
+ if (!rdev)
+ /* Not in-sync */;
+ else if (test_bit(In_sync, &rdev->flags))
+ set_bit(R5_Insync, &dev->flags);
+ else {
+ /* could be in-sync depending on recovery/reshape status */
+ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ if (!test_bit(R5_Insync, &dev->flags)) {
/* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)
- || test_bit(R5_ReadError, &dev->flags)) {
+ if (test_bit(R5_ReadError, &dev->flags))
+ clear_bit(R5_Insync, &dev->flags);
+ if (!test_bit(R5_Insync, &dev->flags)) {
s.failed++;
s.failed_num = i;
- } else
- set_bit(R5_Insync, &dev->flags);
+ }
}
rcu_read_unlock();
@@ -3244,7 +3321,6 @@ static void handle_stripe6(struct stripe_head *sh)
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
- clear_bit(R5_Insync, &dev->flags);
pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -3282,18 +3358,28 @@ static void handle_stripe6(struct stripe_head *sh)
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ clear_bit(R5_Insync, &dev->flags);
+ if (!rdev)
+ /* Not in-sync */;
+ else if (test_bit(In_sync, &rdev->flags))
+ set_bit(R5_Insync, &dev->flags);
+ else {
+ /* in sync if before recovery_offset */
+ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ if (!test_bit(R5_Insync, &dev->flags)) {
/* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)
- || test_bit(R5_ReadError, &dev->flags)) {
+ if (test_bit(R5_ReadError, &dev->flags))
+ clear_bit(R5_Insync, &dev->flags);
+ if (!test_bit(R5_Insync, &dev->flags)) {
if (s.failed < 2)
r6s.failed_num[s.failed] = i;
s.failed++;
- } else
- set_bit(R5_Insync, &dev->flags);
+ }
}
rcu_read_unlock();
@@ -4971,8 +5057,10 @@ static int run(mddev_t *mddev)
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk < 0)
continue;
- if (test_bit(In_sync, &rdev->flags))
+ if (test_bit(In_sync, &rdev->flags)) {
working_disks++;
+ continue;
+ }
/* This disc is not fully in-sync. However if it
* just stored parity (beyond the recovery_offset),
* when we don't need to be concerned about the
@@ -5005,7 +5093,7 @@ static int run(mddev_t *mddev)
mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
- working_disks);
- if (mddev->degraded > conf->max_degraded) {
+ if (has_failed(conf)) {
printk(KERN_ERR "md/raid:%s: not enough operational devices"
" (%d/%d failed)\n",
mdname(mddev), mddev->degraded, conf->raid_disks);
@@ -5207,6 +5295,7 @@ static int raid5_spare_active(mddev_t *mddev)
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->disks + i;
if (tmp->rdev
+ && tmp->rdev->recovery_offset == MaxSector
&& !test_bit(Faulty, &tmp->rdev->flags)
&& !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
unsigned long flags;
@@ -5242,7 +5331,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number)
* isn't possible.
*/
if (!test_bit(Faulty, &rdev->flags) &&
- mddev->degraded <= conf->max_degraded &&
+ !has_failed(conf) &&
number < conf->raid_disks) {
err = -EBUSY;
goto abort;
@@ -5270,7 +5359,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int first = 0;
int last = conf->raid_disks - 1;
- if (mddev->degraded > conf->max_degraded)
+ if (has_failed(conf))
/* no point adding a device */
return -EINVAL;
@@ -5362,7 +5451,7 @@ static int check_reshape(mddev_t *mddev)
if (mddev->bitmap)
/* Cannot grow a bitmap yet */
return -EBUSY;
- if (mddev->degraded > conf->max_degraded)
+ if (has_failed(conf))
return -EINVAL;
if (mddev->delta_disks < 0) {
/* We might be able to shrink, but the devices must
@@ -5437,8 +5526,13 @@ static int raid5_start_reshape(mddev_t *mddev)
/* Add some new drives, as many as will fit.
* We know there are enough to make the newly sized array work.
+ * Don't add devices if we are reducing the number of
+ * devices in the array. This is because it is not possible
+ * to correctly record the "partially reconstructed" state of
+ * such devices during the reshape and confusion could result.
*/
- list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (mddev->delta_disks >= 0)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) {
if (raid5_add_disk(mddev, rdev) == 0) {
@@ -5460,7 +5554,7 @@ static int raid5_start_reshape(mddev_t *mddev)
}
/* When a reshape changes the number of devices, ->degraded
- * is measured against the large of the pre and post number of
+ * is measured against the larger of the pre and post number of
* devices.*/
if (mddev->delta_disks > 0) {
spin_lock_irqsave(&conf->device_lock, flags);
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index 8abbcc5fcf95..8cf2ab609d5e 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -524,6 +524,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
buffer[3] = 0x39;
break;
case TUNER_PHILIPS_FQ1216LME_MK3:
+ case TUNER_PHILIPS_FQ1236_MK5:
tuner_err("This tuner doesn't have FM\n");
/* Set the low band for sanity, since it covers 88-108 MHz */
buffer[3] = 0x01;
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c
index d9aaaca620c9..58a513bcd747 100644
--- a/drivers/media/common/tuners/tuner-types.c
+++ b/drivers/media/common/tuners/tuner-types.c
@@ -1353,6 +1353,17 @@ static struct tuner_params tuner_sony_btf_pxn01z_params[] = {
},
};
+/* ------------ TUNER_PHILIPS_FQ1236_MK5 - Philips NTSC ------------ */
+
+static struct tuner_params tuner_philips_fq1236_mk5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_fm1236_mk3_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+ .has_tda9887 = 1, /* TDA9885, no FM radio */
+ },
+};
+
/* --------------------------------------------------------------------- */
struct tunertype tuners[] = {
@@ -1826,6 +1837,11 @@ struct tunertype tuners[] = {
.params = tuner_sony_btf_pxn01z_params,
.count = ARRAY_SIZE(tuner_sony_btf_pxn01z_params),
},
+ [TUNER_PHILIPS_FQ1236_MK5] = { /* NTSC, TDA9885, no FM radio */
+ .name = "Philips FQ1236 MK5",
+ .params = tuner_philips_fq1236_mk5_params,
+ .count = ARRAY_SIZE(tuner_philips_fq1236_mk5_params),
+ },
};
EXPORT_SYMBOL(tuners);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index bdbc9d305419..27e2acce3c3a 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -969,6 +969,19 @@ config VIDEO_OMAP2
---help---
This is a v4l2 driver for the TI OMAP2 camera capture interface
+config VIDEO_MX2_HOSTSUPPORT
+ bool
+
+config VIDEO_MX2
+ tristate "i.MX27/i.MX25 Camera Sensor Interface driver"
+ depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25)
+ select VIDEOBUF_DMA_CONTIG
+ select VIDEO_MX2_HOSTSUPPORT
+ ---help---
+ This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor
+ Interface
+
+
#
# USB Multimedia device configuration
#
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index cc93859d3164..b08bd2b65cd0 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o
obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
# soc-camera host drivers have to be linked after camera drivers
obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
+obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 9ecacab4b89b..a937e2ff9b6e 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -912,6 +912,9 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
ivtv_flush_queues(s);
+ /* decoder needs time to settle */
+ ivtv_msleep_timeout(40, 0);
+
/* decrement decoding */
atomic_dec(&itv->decoding);
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index 554eaf140128..10ddeccc70eb 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -988,6 +988,9 @@ static int m2mtest_probe(struct platform_device *pdev)
goto err_m2m;
}
+ q_data[V4L2_M2M_SRC].fmt = &formats[0];
+ q_data[V4L2_M2M_DST].fmt = &formats[0];
+
return 0;
err_m2m:
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
new file mode 100644
index 000000000000..026bef0ba403
--- /dev/null
+++ b/drivers/media/video/mx2_camera.c
@@ -0,0 +1,1513 @@
+/*
+ * V4L2 Driver for i.MX27/i.MX25 camera host
+ *
+ * Copyright (C) 2008, Sascha Hauer, Pengutronix
+ * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf-dma-contig.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+
+#include <linux/videodev2.h>
+
+#include <mach/mx2_cam.h>
+#ifdef CONFIG_MACH_MX27
+#include <mach/dma-mx1-mx2.h>
+#endif
+#include <mach/hardware.h>
+
+#include <asm/dma.h>
+
+#define MX2_CAM_DRV_NAME "mx2-camera"
+#define MX2_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
+#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera"
+
+/* reset values */
+#define CSICR1_RESET_VAL 0x40000800
+#define CSICR2_RESET_VAL 0x0
+#define CSICR3_RESET_VAL 0x0
+
+/* csi control reg 1 */
+#define CSICR1_SWAP16_EN (1 << 31)
+#define CSICR1_EXT_VSYNC (1 << 30)
+#define CSICR1_EOF_INTEN (1 << 29)
+#define CSICR1_PRP_IF_EN (1 << 28)
+#define CSICR1_CCIR_MODE (1 << 27)
+#define CSICR1_COF_INTEN (1 << 26)
+#define CSICR1_SF_OR_INTEN (1 << 25)
+#define CSICR1_RF_OR_INTEN (1 << 24)
+#define CSICR1_STATFF_LEVEL (3 << 22)
+#define CSICR1_STATFF_INTEN (1 << 21)
+#define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19) /* MX27 */
+#define CSICR1_FB2_DMA_INTEN (1 << 20) /* MX25 */
+#define CSICR1_FB1_DMA_INTEN (1 << 19) /* MX25 */
+#define CSICR1_RXFF_INTEN (1 << 18)
+#define CSICR1_SOF_POL (1 << 17)
+#define CSICR1_SOF_INTEN (1 << 16)
+#define CSICR1_MCLKDIV(d) (((d) & 0xF) << 12)
+#define CSICR1_HSYNC_POL (1 << 11)
+#define CSICR1_CCIR_EN (1 << 10)
+#define CSICR1_MCLKEN (1 << 9)
+#define CSICR1_FCC (1 << 8)
+#define CSICR1_PACK_DIR (1 << 7)
+#define CSICR1_CLR_STATFIFO (1 << 6)
+#define CSICR1_CLR_RXFIFO (1 << 5)
+#define CSICR1_GCLK_MODE (1 << 4)
+#define CSICR1_INV_DATA (1 << 3)
+#define CSICR1_INV_PCLK (1 << 2)
+#define CSICR1_REDGE (1 << 1)
+
+#define SHIFT_STATFF_LEVEL 22
+#define SHIFT_RXFF_LEVEL 19
+#define SHIFT_MCLKDIV 12
+
+/* control reg 3 */
+#define CSICR3_FRMCNT (0xFFFF << 16)
+#define CSICR3_FRMCNT_RST (1 << 15)
+#define CSICR3_DMA_REFLASH_RFF (1 << 14)
+#define CSICR3_DMA_REFLASH_SFF (1 << 13)
+#define CSICR3_DMA_REQ_EN_RFF (1 << 12)
+#define CSICR3_DMA_REQ_EN_SFF (1 << 11)
+#define CSICR3_RXFF_LEVEL(l) (((l) & 7) << 4) /* MX25 */
+#define CSICR3_CSI_SUP (1 << 3)
+#define CSICR3_ZERO_PACK_EN (1 << 2)
+#define CSICR3_ECC_INT_EN (1 << 1)
+#define CSICR3_ECC_AUTO_EN (1 << 0)
+
+#define SHIFT_FRMCNT 16
+
+/* csi status reg */
+#define CSISR_SFF_OR_INT (1 << 25)
+#define CSISR_RFF_OR_INT (1 << 24)
+#define CSISR_STATFF_INT (1 << 21)
+#define CSISR_DMA_TSF_FB2_INT (1 << 20) /* MX25 */
+#define CSISR_DMA_TSF_FB1_INT (1 << 19) /* MX25 */
+#define CSISR_RXFF_INT (1 << 18)
+#define CSISR_EOF_INT (1 << 17)
+#define CSISR_SOF_INT (1 << 16)
+#define CSISR_F2_INT (1 << 15)
+#define CSISR_F1_INT (1 << 14)
+#define CSISR_COF_INT (1 << 13)
+#define CSISR_ECC_INT (1 << 1)
+#define CSISR_DRDY (1 << 0)
+
+#define CSICR1 0x00
+#define CSICR2 0x04
+#define CSISR (cpu_is_mx27() ? 0x08 : 0x18)
+#define CSISTATFIFO 0x0c
+#define CSIRFIFO 0x10
+#define CSIRXCNT 0x14
+#define CSICR3 (cpu_is_mx27() ? 0x1C : 0x08)
+#define CSIDMASA_STATFIFO 0x20
+#define CSIDMATA_STATFIFO 0x24
+#define CSIDMASA_FB1 0x28
+#define CSIDMASA_FB2 0x2c
+#define CSIFBUF_PARA 0x30
+#define CSIIMAG_PARA 0x34
+
+/* EMMA PrP */
+#define PRP_CNTL 0x00
+#define PRP_INTR_CNTL 0x04
+#define PRP_INTRSTATUS 0x08
+#define PRP_SOURCE_Y_PTR 0x0c
+#define PRP_SOURCE_CB_PTR 0x10
+#define PRP_SOURCE_CR_PTR 0x14
+#define PRP_DEST_RGB1_PTR 0x18
+#define PRP_DEST_RGB2_PTR 0x1c
+#define PRP_DEST_Y_PTR 0x20
+#define PRP_DEST_CB_PTR 0x24
+#define PRP_DEST_CR_PTR 0x28
+#define PRP_SRC_FRAME_SIZE 0x2c
+#define PRP_DEST_CH1_LINE_STRIDE 0x30
+#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34
+#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38
+#define PRP_CH1_OUT_IMAGE_SIZE 0x3c
+#define PRP_CH2_OUT_IMAGE_SIZE 0x40
+#define PRP_SRC_LINE_STRIDE 0x44
+#define PRP_CSC_COEF_012 0x48
+#define PRP_CSC_COEF_345 0x4c
+#define PRP_CSC_COEF_678 0x50
+#define PRP_CH1_RZ_HORI_COEF1 0x54
+#define PRP_CH1_RZ_HORI_COEF2 0x58
+#define PRP_CH1_RZ_HORI_VALID 0x5c
+#define PRP_CH1_RZ_VERT_COEF1 0x60
+#define PRP_CH1_RZ_VERT_COEF2 0x64
+#define PRP_CH1_RZ_VERT_VALID 0x68
+#define PRP_CH2_RZ_HORI_COEF1 0x6c
+#define PRP_CH2_RZ_HORI_COEF2 0x70
+#define PRP_CH2_RZ_HORI_VALID 0x74
+#define PRP_CH2_RZ_VERT_COEF1 0x78
+#define PRP_CH2_RZ_VERT_COEF2 0x7c
+#define PRP_CH2_RZ_VERT_VALID 0x80
+
+#define PRP_CNTL_CH1EN (1 << 0)
+#define PRP_CNTL_CH2EN (1 << 1)
+#define PRP_CNTL_CSIEN (1 << 2)
+#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
+#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
+#define PRP_CNTL_DATA_IN_RGB16 (2 << 3)
+#define PRP_CNTL_DATA_IN_RGB32 (3 << 3)
+#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5)
+#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5)
+#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5)
+#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
+#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
+#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
+#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
+#define PRP_CNTL_CH1_LEN (1 << 9)
+#define PRP_CNTL_CH2_LEN (1 << 10)
+#define PRP_CNTL_SKIP_FRAME (1 << 11)
+#define PRP_CNTL_SWRST (1 << 12)
+#define PRP_CNTL_CLKEN (1 << 13)
+#define PRP_CNTL_WEN (1 << 14)
+#define PRP_CNTL_CH1BYP (1 << 15)
+#define PRP_CNTL_IN_TSKIP(x) ((x) << 16)
+#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19)
+#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22)
+#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25)
+#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27)
+#define PRP_CNTL_CH2B1EN (1 << 29)
+#define PRP_CNTL_CH2B2EN (1 << 30)
+#define PRP_CNTL_CH2FEN (1 << 31)
+
+/* IRQ Enable and status register */
+#define PRP_INTR_RDERR (1 << 0)
+#define PRP_INTR_CH1WERR (1 << 1)
+#define PRP_INTR_CH2WERR (1 << 2)
+#define PRP_INTR_CH1FC (1 << 3)
+#define PRP_INTR_CH2FC (1 << 5)
+#define PRP_INTR_LBOVF (1 << 7)
+#define PRP_INTR_CH2OVF (1 << 8)
+
+#define mx27_camera_emma(pcdev) (cpu_is_mx27() && pcdev->use_emma)
+
+#define MAX_VIDEO_MEM 16
+
+struct mx2_camera_dev {
+ struct device *dev;
+ struct soc_camera_host soc_host;
+ struct soc_camera_device *icd;
+ struct clk *clk_csi, *clk_emma;
+
+ unsigned int irq_csi, irq_emma;
+ void __iomem *base_csi, *base_emma;
+ unsigned long base_dma;
+
+ struct mx2_camera_platform_data *pdata;
+ struct resource *res_csi, *res_emma;
+ unsigned long platform_flags;
+
+ struct list_head capture;
+ struct list_head active_bufs;
+
+ spinlock_t lock;
+
+ int dma;
+ struct mx2_buffer *active;
+ struct mx2_buffer *fb1_active;
+ struct mx2_buffer *fb2_active;
+
+ int use_emma;
+
+ u32 csicr1;
+
+ void *discard_buffer;
+ dma_addr_t discard_buffer_dma;
+ size_t discard_size;
+};
+
+/* buffer for one video frame */
+struct mx2_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct videobuf_buffer vb;
+
+ enum v4l2_mbus_pixelcode code;
+
+ int bufnum;
+};
+
+static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
+{
+ unsigned long flags;
+
+ clk_disable(pcdev->clk_csi);
+ writel(0, pcdev->base_csi + CSICR1);
+ if (mx27_camera_emma(pcdev)) {
+ writel(0, pcdev->base_emma + PRP_CNTL);
+ } else if (cpu_is_mx25()) {
+ spin_lock_irqsave(&pcdev->lock, flags);
+ pcdev->fb1_active = NULL;
+ pcdev->fb2_active = NULL;
+ writel(0, pcdev->base_csi + CSIDMASA_FB1);
+ writel(0, pcdev->base_csi + CSIDMASA_FB2);
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+ }
+}
+
+/*
+ * The following two functions absolutely depend on the fact, that
+ * there can be only one camera on mx2 camera sensor interface
+ */
+static int mx2_camera_add_device(struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+ int ret;
+ u32 csicr1;
+
+ if (pcdev->icd)
+ return -EBUSY;
+
+ ret = clk_enable(pcdev->clk_csi);
+ if (ret < 0)
+ return ret;
+
+ csicr1 = CSICR1_MCLKEN;
+
+ if (mx27_camera_emma(pcdev)) {
+ csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
+ CSICR1_RXFF_LEVEL(0);
+ } else if (cpu_is_mx27())
+ csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2);
+
+ pcdev->csicr1 = csicr1;
+ writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
+
+ pcdev->icd = icd;
+
+ dev_info(icd->dev.parent, "Camera driver attached to camera %d\n",
+ icd->devnum);
+
+ return 0;
+}
+
+static void mx2_camera_remove_device(struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+
+ BUG_ON(icd != pcdev->icd);
+
+ dev_info(icd->dev.parent, "Camera driver detached from camera %d\n",
+ icd->devnum);
+
+ mx2_camera_deactivate(pcdev);
+
+ if (pcdev->discard_buffer) {
+ dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size,
+ pcdev->discard_buffer,
+ pcdev->discard_buffer_dma);
+ pcdev->discard_buffer = NULL;
+ }
+
+ pcdev->icd = NULL;
+}
+
+#ifdef CONFIG_MACH_MX27
+static void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev)
+{
+ u32 tmp;
+
+ imx_dma_enable(pcdev->dma);
+
+ tmp = readl(pcdev->base_csi + CSICR1);
+ tmp |= CSICR1_RF_OR_INTEN;
+ writel(tmp, pcdev->base_csi + CSICR1);
+}
+
+static irqreturn_t mx27_camera_irq(int irq_csi, void *data)
+{
+ struct mx2_camera_dev *pcdev = data;
+ u32 status = readl(pcdev->base_csi + CSISR);
+
+ if (status & CSISR_SOF_INT && pcdev->active) {
+ u32 tmp;
+
+ tmp = readl(pcdev->base_csi + CSICR1);
+ writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1);
+ mx27_camera_dma_enable(pcdev);
+ }
+
+ writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR);
+
+ return IRQ_HANDLED;
+}
+#else
+static irqreturn_t mx27_camera_irq(int irq_csi, void *data)
+{
+ return IRQ_NONE;
+}
+#endif /* CONFIG_MACH_MX27 */
+
+static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
+ int state)
+{
+ struct videobuf_buffer *vb;
+ struct mx2_buffer *buf;
+ struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active :
+ &pcdev->fb2_active;
+ u32 fb_reg = fb == 1 ? CSIDMASA_FB1 : CSIDMASA_FB2;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcdev->lock, flags);
+
+ vb = &(*fb_active)->vb;
+ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ vb->state = state;
+ do_gettimeofday(&vb->ts);
+ vb->field_count++;
+
+ wake_up(&vb->done);
+
+ if (list_empty(&pcdev->capture)) {
+ buf = NULL;
+ writel(0, pcdev->base_csi + fb_reg);
+ } else {
+ buf = list_entry(pcdev->capture.next, struct mx2_buffer,
+ vb.queue);
+ vb = &buf->vb;
+ list_del(&vb->queue);
+ vb->state = VIDEOBUF_ACTIVE;
+ writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg);
+ }
+
+ *fb_active = buf;
+
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
+{
+ struct mx2_camera_dev *pcdev = data;
+ u32 status = readl(pcdev->base_csi + CSISR);
+
+ if (status & CSISR_DMA_TSF_FB1_INT)
+ mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE);
+ else if (status & CSISR_DMA_TSF_FB2_INT)
+ mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE);
+
+ /* FIXME: handle CSISR_RFF_OR_INT */
+
+ writel(status, pcdev->base_csi + CSISR);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Videobuf operations
+ */
+static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
+ unsigned int *size)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
+
+ dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
+
+ if (bytes_per_line < 0)
+ return bytes_per_line;
+
+ *size = bytes_per_line * icd->user_height;
+
+ if (0 == *count)
+ *count = 32;
+ if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
+ *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
+
+ return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct videobuf_buffer *vb = &buf->vb;
+
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ /*
+ * This waits until this buffer is out of danger, i.e., until it is no
+ * longer in STATE_QUEUED or STATE_ACTIVE
+ */
+ videobuf_waiton(vb, 0, 0);
+
+ videobuf_dma_contig_free(vq, vb);
+ dev_dbg(&icd->dev, "%s freed\n", __func__);
+
+ vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int mx2_videobuf_prepare(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb, enum v4l2_field field)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
+ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
+ int ret = 0;
+
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ if (bytes_per_line < 0)
+ return bytes_per_line;
+
+#ifdef DEBUG
+ /*
+ * This can be useful if you want to see if we actually fill
+ * the buffer with something
+ */
+ memset((void *)vb->baddr, 0xaa, vb->bsize);
+#endif
+
+ if (buf->code != icd->current_fmt->code ||
+ vb->width != icd->user_width ||
+ vb->height != icd->user_height ||
+ vb->field != field) {
+ buf->code = icd->current_fmt->code;
+ vb->width = icd->user_width;
+ vb->height = icd->user_height;
+ vb->field = field;
+ vb->state = VIDEOBUF_NEEDS_INIT;
+ }
+
+ vb->size = bytes_per_line * vb->height;
+ if (vb->baddr && vb->bsize < vb->size) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
+ ret = videobuf_iolock(vq, vb, NULL);
+ if (ret)
+ goto fail;
+
+ vb->state = VIDEOBUF_PREPARED;
+ }
+
+ return 0;
+
+fail:
+ free_buffer(vq, buf);
+out:
+ return ret;
+}
+
+static void mx2_videobuf_queue(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+ struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
+ unsigned long flags;
+
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ spin_lock_irqsave(&pcdev->lock, flags);
+
+ vb->state = VIDEOBUF_QUEUED;
+ list_add_tail(&vb->queue, &pcdev->capture);
+
+ if (mx27_camera_emma(pcdev)) {
+ goto out;
+#ifdef CONFIG_MACH_MX27
+ } else if (cpu_is_mx27()) {
+ int ret;
+
+ if (pcdev->active == NULL) {
+ ret = imx_dma_setup_single(pcdev->dma,
+ videobuf_to_dma_contig(vb), vb->size,
+ (u32)pcdev->base_dma + 0x10,
+ DMA_MODE_READ);
+ if (ret) {
+ vb->state = VIDEOBUF_ERROR;
+ wake_up(&vb->done);
+ goto out;
+ }
+
+ vb->state = VIDEOBUF_ACTIVE;
+ pcdev->active = buf;
+ }
+#endif
+ } else { /* cpu_is_mx25() */
+ u32 csicr3, dma_inten = 0;
+
+ if (pcdev->fb1_active == NULL) {
+ writel(videobuf_to_dma_contig(vb),
+ pcdev->base_csi + CSIDMASA_FB1);
+ pcdev->fb1_active = buf;
+ dma_inten = CSICR1_FB1_DMA_INTEN;
+ } else if (pcdev->fb2_active == NULL) {
+ writel(videobuf_to_dma_contig(vb),
+ pcdev->base_csi + CSIDMASA_FB2);
+ pcdev->fb2_active = buf;
+ dma_inten = CSICR1_FB2_DMA_INTEN;
+ }
+
+ if (dma_inten) {
+ list_del(&vb->queue);
+ vb->state = VIDEOBUF_ACTIVE;
+
+ csicr3 = readl(pcdev->base_csi + CSICR3);
+
+ /* Reflash DMA */
+ writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
+ pcdev->base_csi + CSICR3);
+
+ /* clear & enable interrupts */
+ writel(dma_inten, pcdev->base_csi + CSISR);
+ pcdev->csicr1 |= dma_inten;
+ writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
+
+ /* enable DMA */
+ csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
+ writel(csicr3, pcdev->base_csi + CSICR3);
+ }
+ }
+
+out:
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void mx2_videobuf_release(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+ struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
+ unsigned long flags;
+
+#ifdef DEBUG
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ switch (vb->state) {
+ case VIDEOBUF_ACTIVE:
+ dev_info(&icd->dev, "%s (active)\n", __func__);
+ break;
+ case VIDEOBUF_QUEUED:
+ dev_info(&icd->dev, "%s (queued)\n", __func__);
+ break;
+ case VIDEOBUF_PREPARED:
+ dev_info(&icd->dev, "%s (prepared)\n", __func__);
+ break;
+ default:
+ dev_info(&icd->dev, "%s (unknown) %d\n", __func__,
+ vb->state);
+ break;
+ }
+#endif
+
+ /*
+ * Terminate only queued but inactive buffers. Active buffers are
+ * released when they become inactive after videobuf_waiton().
+ *
+ * FIXME: implement forced termination of active buffers, so that the
+ * user won't get stuck in an uninterruptible state. This requires a
+ * specific handling for each of the three DMA types that this driver
+ * supports.
+ */
+ spin_lock_irqsave(&pcdev->lock, flags);
+ if (vb->state == VIDEOBUF_QUEUED) {
+ list_del(&vb->queue);
+ vb->state = VIDEOBUF_ERROR;
+ }
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+
+ free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops mx2_videobuf_ops = {
+ .buf_setup = mx2_videobuf_setup,
+ .buf_prepare = mx2_videobuf_prepare,
+ .buf_queue = mx2_videobuf_queue,
+ .buf_release = mx2_videobuf_release,
+};
+
+static void mx2_camera_init_videobuf(struct videobuf_queue *q,
+ struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+
+ videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev,
+ &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_NONE, sizeof(struct mx2_buffer), icd);
+}
+
+#define MX2_BUS_FLAGS (SOCAM_DATAWIDTH_8 | \
+ SOCAM_MASTER | \
+ SOCAM_VSYNC_ACTIVE_HIGH | \
+ SOCAM_VSYNC_ACTIVE_LOW | \
+ SOCAM_HSYNC_ACTIVE_HIGH | \
+ SOCAM_HSYNC_ACTIVE_LOW | \
+ SOCAM_PCLK_SAMPLE_RISING | \
+ SOCAM_PCLK_SAMPLE_FALLING | \
+ SOCAM_DATA_ACTIVE_HIGH | \
+ SOCAM_DATA_ACTIVE_LOW)
+
+static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev)
+{
+ u32 cntl;
+ int count = 0;
+
+ cntl = readl(pcdev->base_emma + PRP_CNTL);
+ writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
+ while (count++ < 100) {
+ if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST))
+ return 0;
+ barrier();
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
+ int bytesperline)
+{
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+
+ writel(pcdev->discard_buffer_dma,
+ pcdev->base_emma + PRP_DEST_RGB1_PTR);
+ writel(pcdev->discard_buffer_dma,
+ pcdev->base_emma + PRP_DEST_RGB2_PTR);
+
+ /*
+ * We only use the EMMA engine to get rid of the broken
+ * DMA Engine. No color space consversion at the moment.
+ * We adjust incoming and outgoing pixelformat to rgb16
+ * and adjust the bytesperline accordingly.
+ */
+ writel(PRP_CNTL_CH1EN |
+ PRP_CNTL_CSIEN |
+ PRP_CNTL_DATA_IN_RGB16 |
+ PRP_CNTL_CH1_OUT_RGB16 |
+ PRP_CNTL_CH1_LEN |
+ PRP_CNTL_CH1BYP |
+ PRP_CNTL_CH1_TSKIP(0) |
+ PRP_CNTL_IN_TSKIP(0),
+ pcdev->base_emma + PRP_CNTL);
+
+ writel(((bytesperline >> 1) << 16) | icd->user_height,
+ pcdev->base_emma + PRP_SRC_FRAME_SIZE);
+ writel(((bytesperline >> 1) << 16) | icd->user_height,
+ pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
+ writel(bytesperline,
+ pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
+ writel(0x2ca00565, /* RGB565 */
+ pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
+ writel(0x2ca00565, /* RGB565 */
+ pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
+
+ /* Enable interrupts */
+ writel(PRP_INTR_RDERR |
+ PRP_INTR_CH1WERR |
+ PRP_INTR_CH2WERR |
+ PRP_INTR_CH1FC |
+ PRP_INTR_CH2FC |
+ PRP_INTR_LBOVF |
+ PRP_INTR_CH2OVF,
+ pcdev->base_emma + PRP_INTR_CNTL);
+}
+
+static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
+ __u32 pixfmt)
+{
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+ unsigned long camera_flags, common_flags;
+ int ret = 0;
+ int bytesperline;
+ u32 csicr1 = pcdev->csicr1;
+
+ camera_flags = icd->ops->query_bus_param(icd);
+
+ common_flags = soc_camera_bus_param_compatible(camera_flags,
+ MX2_BUS_FLAGS);
+ if (!common_flags)
+ return -EINVAL;
+
+ if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
+ (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+ if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH)
+ common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+ else
+ common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+ }
+
+ if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
+ (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+ if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING)
+ common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+ else
+ common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+ }
+
+ ret = icd->ops->set_bus_param(icd, common_flags);
+ if (ret < 0)
+ return ret;
+
+ if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+ csicr1 |= CSICR1_INV_PCLK;
+ if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
+ csicr1 |= CSICR1_SOF_POL;
+ if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
+ csicr1 |= CSICR1_HSYNC_POL;
+ if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
+ csicr1 |= CSICR1_SWAP16_EN;
+ if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC)
+ csicr1 |= CSICR1_EXT_VSYNC;
+ if (pcdev->platform_flags & MX2_CAMERA_CCIR)
+ csicr1 |= CSICR1_CCIR_EN;
+ if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE)
+ csicr1 |= CSICR1_CCIR_MODE;
+ if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK)
+ csicr1 |= CSICR1_GCLK_MODE;
+ if (pcdev->platform_flags & MX2_CAMERA_INV_DATA)
+ csicr1 |= CSICR1_INV_DATA;
+ if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB)
+ csicr1 |= CSICR1_PACK_DIR;
+
+ pcdev->csicr1 = csicr1;
+
+ bytesperline = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
+ if (bytesperline < 0)
+ return bytesperline;
+
+ if (mx27_camera_emma(pcdev)) {
+ ret = mx27_camera_emma_prp_reset(pcdev);
+ if (ret)
+ return ret;
+
+ if (pcdev->discard_buffer)
+ dma_free_coherent(ici->v4l2_dev.dev,
+ pcdev->discard_size, pcdev->discard_buffer,
+ pcdev->discard_buffer_dma);
+
+ /*
+ * I didn't manage to properly enable/disable the prp
+ * on a per frame basis during running transfers,
+ * thus we allocate a buffer here and use it to
+ * discard frames when no buffer is available.
+ * Feel free to work on this ;)
+ */
+ pcdev->discard_size = icd->user_height * bytesperline;
+ pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
+ pcdev->discard_size, &pcdev->discard_buffer_dma,
+ GFP_KERNEL);
+ if (!pcdev->discard_buffer)
+ return -ENOMEM;
+
+ mx27_camera_emma_buf_init(icd, bytesperline);
+ } else if (cpu_is_mx25()) {
+ writel((bytesperline * icd->user_height) >> 2,
+ pcdev->base_csi + CSIRXCNT);
+ writel((bytesperline << 16) | icd->user_height,
+ pcdev->base_csi + CSIIMAG_PARA);
+ }
+
+ writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
+
+ return 0;
+}
+
+static int mx2_camera_set_crop(struct soc_camera_device *icd,
+ struct v4l2_crop *a)
+{
+ struct v4l2_rect *rect = &a->c;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ struct v4l2_mbus_framefmt mf;
+ int ret;
+
+ soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
+ soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096);
+
+ ret = v4l2_subdev_call(sd, video, s_crop, a);
+ if (ret < 0)
+ return ret;
+
+ /* The capture device might have changed its output */
+ ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
+ mf.width, mf.height);
+
+ icd->user_width = mf.width;
+ icd->user_height = mf.height;
+
+ return ret;
+}
+
+static int mx2_camera_set_fmt(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ const struct soc_camera_format_xlate *xlate;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_mbus_framefmt mf;
+ int ret;
+
+ xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+ if (!xlate) {
+ dev_warn(icd->dev.parent, "Format %x not found\n",
+ pix->pixelformat);
+ return -EINVAL;
+ }
+
+ /* eMMA can only do RGB565 */
+ if (mx27_camera_emma(pcdev) && pix->pixelformat != V4L2_PIX_FMT_RGB565)
+ return -EINVAL;
+
+ mf.width = pix->width;
+ mf.height = pix->height;
+ mf.field = pix->field;
+ mf.colorspace = pix->colorspace;
+ mf.code = xlate->code;
+
+ ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ return ret;
+
+ if (mf.code != xlate->code)
+ return -EINVAL;
+
+ pix->width = mf.width;
+ pix->height = mf.height;
+ pix->field = mf.field;
+ pix->colorspace = mf.colorspace;
+ icd->current_fmt = xlate;
+
+ return 0;
+}
+
+static int mx2_camera_try_fmt(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ const struct soc_camera_format_xlate *xlate;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_mbus_framefmt mf;
+ __u32 pixfmt = pix->pixelformat;
+ unsigned int width_limit;
+ int ret;
+
+ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+ if (pixfmt && !xlate) {
+ dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
+ return -EINVAL;
+ }
+
+ /* FIXME: implement MX27 limits */
+
+ /* eMMA can only do RGB565 */
+ if (mx27_camera_emma(pcdev) && pixfmt != V4L2_PIX_FMT_RGB565)
+ return -EINVAL;
+
+ /* limit to MX25 hardware capabilities */
+ if (cpu_is_mx25()) {
+ if (xlate->host_fmt->bits_per_sample <= 8)
+ width_limit = 0xffff * 4;
+ else
+ width_limit = 0xffff * 2;
+ /* CSIIMAG_PARA limit */
+ if (pix->width > width_limit)
+ pix->width = width_limit;
+ if (pix->height > 0xffff)
+ pix->height = 0xffff;
+
+ pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+ xlate->host_fmt);
+ if (pix->bytesperline < 0)
+ return pix->bytesperline;
+ pix->sizeimage = pix->height * pix->bytesperline;
+ if (pix->sizeimage > (4 * 0x3ffff)) { /* CSIRXCNT limit */
+ dev_warn(icd->dev.parent,
+ "Image size (%u) above limit\n",
+ pix->sizeimage);
+ return -EINVAL;
+ }
+ }
+
+ /* limit to sensor capabilities */
+ mf.width = pix->width;
+ mf.height = pix->height;
+ mf.field = pix->field;
+ mf.colorspace = pix->colorspace;
+ mf.code = xlate->code;
+
+ ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+ if (ret < 0)
+ return ret;
+
+ if (mf.field == V4L2_FIELD_ANY)
+ mf.field = V4L2_FIELD_NONE;
+ if (mf.field != V4L2_FIELD_NONE) {
+ dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+ mf.field);
+ return -EINVAL;
+ }
+
+ pix->width = mf.width;
+ pix->height = mf.height;
+ pix->field = mf.field;
+ pix->colorspace = mf.colorspace;
+
+ return 0;
+}
+
+static int mx2_camera_querycap(struct soc_camera_host *ici,
+ struct v4l2_capability *cap)
+{
+ /* cap->name is set by the friendly caller:-> */
+ strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
+ cap->version = MX2_CAM_VERSION_CODE;
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+ return 0;
+}
+
+static int mx2_camera_reqbufs(struct soc_camera_file *icf,
+ struct v4l2_requestbuffers *p)
+{
+ int i;
+
+ for (i = 0; i < p->count; i++) {
+ struct mx2_buffer *buf = container_of(icf->vb_vidq.bufs[i],
+ struct mx2_buffer, vb);
+ INIT_LIST_HEAD(&buf->vb.queue);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_MACH_MX27
+static void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state)
+{
+ struct videobuf_buffer *vb;
+ struct mx2_buffer *buf;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pcdev->lock, flags);
+
+ if (!pcdev->active) {
+ dev_err(pcdev->dev, "%s called with no active buffer!\n",
+ __func__);
+ goto out;
+ }
+
+ vb = &pcdev->active->vb;
+ buf = container_of(vb, struct mx2_buffer, vb);
+ WARN_ON(list_empty(&vb->queue));
+ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
+ list_del_init(&vb->queue);
+ vb->state = state;
+ do_gettimeofday(&vb->ts);
+ vb->field_count++;
+
+ wake_up(&vb->done);
+
+ if (list_empty(&pcdev->capture)) {
+ pcdev->active = NULL;
+ goto out;
+ }
+
+ pcdev->active = list_entry(pcdev->capture.next,
+ struct mx2_buffer, vb.queue);
+
+ vb = &pcdev->active->vb;
+ vb->state = VIDEOBUF_ACTIVE;
+
+ ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb),
+ vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ);
+
+ if (ret) {
+ vb->state = VIDEOBUF_ERROR;
+ pcdev->active = NULL;
+ wake_up(&vb->done);
+ }
+
+out:
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void mx27_camera_dma_err_callback(int channel, void *data, int err)
+{
+ struct mx2_camera_dev *pcdev = data;
+
+ mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR);
+}
+
+static void mx27_camera_dma_callback(int channel, void *data)
+{
+ struct mx2_camera_dev *pcdev = data;
+
+ mx27_camera_frame_done(pcdev, VIDEOBUF_DONE);
+}
+
+#define DMA_REQ_CSI_RX 31 /* FIXME: Add this to a resource */
+
+static int __devinit mx27_camera_dma_init(struct platform_device *pdev,
+ struct mx2_camera_dev *pcdev)
+{
+ int err;
+
+ pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH);
+ if (pcdev->dma < 0) {
+ dev_err(&pdev->dev, "%s failed to request DMA channel\n",
+ __func__);
+ return pcdev->dma;
+ }
+
+ err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback,
+ mx27_camera_dma_err_callback, pcdev);
+ if (err) {
+ dev_err(&pdev->dev, "%s failed to set DMA callback\n",
+ __func__);
+ goto err_out;
+ }
+
+ err = imx_dma_config_channel(pcdev->dma,
+ IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
+ IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+ DMA_REQ_CSI_RX, 1);
+ if (err) {
+ dev_err(&pdev->dev, "%s failed to config DMA channel\n",
+ __func__);
+ goto err_out;
+ }
+
+ imx_dma_config_burstlen(pcdev->dma, 64);
+
+ return 0;
+
+err_out:
+ imx_dma_free(pcdev->dma);
+
+ return err;
+}
+#endif /* CONFIG_MACH_MX27 */
+
+static unsigned int mx2_camera_poll(struct file *file, poll_table *pt)
+{
+ struct soc_camera_file *icf = file->private_data;
+
+ return videobuf_poll_stream(file, &icf->vb_vidq, pt);
+}
+
+static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
+ .owner = THIS_MODULE,
+ .add = mx2_camera_add_device,
+ .remove = mx2_camera_remove_device,
+ .set_fmt = mx2_camera_set_fmt,
+ .set_crop = mx2_camera_set_crop,
+ .try_fmt = mx2_camera_try_fmt,
+ .init_videobuf = mx2_camera_init_videobuf,
+ .reqbufs = mx2_camera_reqbufs,
+ .poll = mx2_camera_poll,
+ .querycap = mx2_camera_querycap,
+ .set_bus_param = mx2_camera_set_bus_param,
+};
+
+static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
+ int bufnum, int state)
+{
+ struct mx2_buffer *buf;
+ struct videobuf_buffer *vb;
+ unsigned long phys;
+
+ if (!list_empty(&pcdev->active_bufs)) {
+ buf = list_entry(pcdev->active_bufs.next,
+ struct mx2_buffer, vb.queue);
+
+ BUG_ON(buf->bufnum != bufnum);
+
+ vb = &buf->vb;
+#ifdef DEBUG
+ phys = videobuf_to_dma_contig(vb);
+ if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum)
+ != phys) {
+ dev_err(pcdev->dev, "%p != %p\n", phys,
+ readl(pcdev->base_emma +
+ PRP_DEST_RGB1_PTR +
+ 4 * bufnum));
+ }
+#endif
+ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb,
+ vb->baddr, vb->bsize);
+
+ list_del(&vb->queue);
+ vb->state = state;
+ do_gettimeofday(&vb->ts);
+ vb->field_count++;
+
+ wake_up(&vb->done);
+ }
+
+ if (list_empty(&pcdev->capture)) {
+ writel(pcdev->discard_buffer_dma, pcdev->base_emma +
+ PRP_DEST_RGB1_PTR + 4 * bufnum);
+ return;
+ }
+
+ buf = list_entry(pcdev->capture.next,
+ struct mx2_buffer, vb.queue);
+
+ buf->bufnum = bufnum;
+
+ list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
+
+ vb = &buf->vb;
+ vb->state = VIDEOBUF_ACTIVE;
+
+ phys = videobuf_to_dma_contig(vb);
+ writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
+}
+
+static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
+{
+ struct mx2_camera_dev *pcdev = data;
+ unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS);
+ struct mx2_buffer *buf;
+
+ if (status & (1 << 7)) { /* overflow */
+ u32 cntl;
+ /*
+ * We only disable channel 1 here since this is the only
+ * enabled channel
+ *
+ * FIXME: the correct DMA overflow handling should be resetting
+ * the buffer, returning an error frame, and continuing with
+ * the next one.
+ */
+ cntl = readl(pcdev->base_emma + PRP_CNTL);
+ writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL);
+ writel(cntl, pcdev->base_emma + PRP_CNTL);
+ }
+ if ((status & (3 << 5)) == (3 << 5)
+ && !list_empty(&pcdev->active_bufs)) {
+ /*
+ * Both buffers have triggered, process the one we're expecting
+ * to first
+ */
+ buf = list_entry(pcdev->active_bufs.next,
+ struct mx2_buffer, vb.queue);
+ mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE);
+ status &= ~(1 << (6 - buf->bufnum)); /* mark processed */
+ }
+ if (status & (1 << 6))
+ mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE);
+ if (status & (1 << 5))
+ mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE);
+
+ writel(status, pcdev->base_emma + PRP_INTRSTATUS);
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev)
+{
+ struct resource *res_emma = pcdev->res_emma;
+ int err = 0;
+
+ if (!request_mem_region(res_emma->start, resource_size(res_emma),
+ MX2_CAM_DRV_NAME)) {
+ err = -EBUSY;
+ goto out;
+ }
+
+ pcdev->base_emma = ioremap(res_emma->start, resource_size(res_emma));
+ if (!pcdev->base_emma) {
+ err = -ENOMEM;
+ goto exit_release;
+ }
+
+ err = request_irq(pcdev->irq_emma, mx27_camera_emma_irq, 0,
+ MX2_CAM_DRV_NAME, pcdev);
+ if (err) {
+ dev_err(pcdev->dev, "Camera EMMA interrupt register failed \n");
+ goto exit_iounmap;
+ }
+
+ pcdev->clk_emma = clk_get(NULL, "emma");
+ if (IS_ERR(pcdev->clk_emma)) {
+ err = PTR_ERR(pcdev->clk_emma);
+ goto exit_free_irq;
+ }
+
+ clk_enable(pcdev->clk_emma);
+
+ err = mx27_camera_emma_prp_reset(pcdev);
+ if (err)
+ goto exit_clk_emma_put;
+
+ return err;
+
+exit_clk_emma_put:
+ clk_disable(pcdev->clk_emma);
+ clk_put(pcdev->clk_emma);
+exit_free_irq:
+ free_irq(pcdev->irq_emma, pcdev);
+exit_iounmap:
+ iounmap(pcdev->base_emma);
+exit_release:
+ release_mem_region(res_emma->start, resource_size(res_emma));
+out:
+ return err;
+}
+
+static int __devinit mx2_camera_probe(struct platform_device *pdev)
+{
+ struct mx2_camera_dev *pcdev;
+ struct resource *res_csi, *res_emma;
+ void __iomem *base_csi;
+ int irq_csi, irq_emma;
+ irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq
+ : mx27_camera_irq;
+ int err = 0;
+
+ dev_dbg(&pdev->dev, "initialising\n");
+
+ res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq_csi = platform_get_irq(pdev, 0);
+ if (res_csi == NULL || irq_csi < 0) {
+ dev_err(&pdev->dev, "Missing platform resources data\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
+ if (!pcdev) {
+ dev_err(&pdev->dev, "Could not allocate pcdev\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ pcdev->clk_csi = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pcdev->clk_csi)) {
+ err = PTR_ERR(pcdev->clk_csi);
+ goto exit_kfree;
+ }
+
+ dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n",
+ clk_get_rate(pcdev->clk_csi));
+
+ /* Initialize DMA */
+#ifdef CONFIG_MACH_MX27
+ if (cpu_is_mx27()) {
+ err = mx27_camera_dma_init(pdev, pcdev);
+ if (err)
+ goto exit_clk_put;
+ }
+#endif /* CONFIG_MACH_MX27 */
+
+ pcdev->res_csi = res_csi;
+ pcdev->pdata = pdev->dev.platform_data;
+ if (pcdev->pdata) {
+ long rate;
+
+ pcdev->platform_flags = pcdev->pdata->flags;
+
+ rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2);
+ if (rate <= 0) {
+ err = -ENODEV;
+ goto exit_dma_free;
+ }
+ err = clk_set_rate(pcdev->clk_csi, rate);
+ if (err < 0)
+ goto exit_dma_free;
+ }
+
+ INIT_LIST_HEAD(&pcdev->capture);
+ INIT_LIST_HEAD(&pcdev->active_bufs);
+ spin_lock_init(&pcdev->lock);
+
+ /*
+ * Request the regions.
+ */
+ if (!request_mem_region(res_csi->start, resource_size(res_csi),
+ MX2_CAM_DRV_NAME)) {
+ err = -EBUSY;
+ goto exit_dma_free;
+ }
+
+ base_csi = ioremap(res_csi->start, resource_size(res_csi));
+ if (!base_csi) {
+ err = -ENOMEM;
+ goto exit_release;
+ }
+ pcdev->irq_csi = irq_csi;
+ pcdev->base_csi = base_csi;
+ pcdev->base_dma = res_csi->start;
+ pcdev->dev = &pdev->dev;
+
+ err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0,
+ MX2_CAM_DRV_NAME, pcdev);
+ if (err) {
+ dev_err(pcdev->dev, "Camera interrupt register failed \n");
+ goto exit_iounmap;
+ }
+
+ if (cpu_is_mx27()) {
+ /* EMMA support */
+ res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ irq_emma = platform_get_irq(pdev, 1);
+
+ if (res_emma && irq_emma >= 0) {
+ dev_info(&pdev->dev, "Using EMMA\n");
+ pcdev->use_emma = 1;
+ pcdev->res_emma = res_emma;
+ pcdev->irq_emma = irq_emma;
+ if (mx27_camera_emma_init(pcdev))
+ goto exit_free_irq;
+ }
+ }
+
+ pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME,
+ pcdev->soc_host.ops = &mx2_soc_camera_host_ops,
+ pcdev->soc_host.priv = pcdev;
+ pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
+ pcdev->soc_host.nr = pdev->id;
+ err = soc_camera_host_register(&pcdev->soc_host);
+ if (err)
+ goto exit_free_emma;
+
+ return 0;
+
+exit_free_emma:
+ if (mx27_camera_emma(pcdev)) {
+ free_irq(pcdev->irq_emma, pcdev);
+ clk_disable(pcdev->clk_emma);
+ clk_put(pcdev->clk_emma);
+ iounmap(pcdev->base_emma);
+ release_mem_region(res_emma->start, resource_size(res_emma));
+ }
+exit_free_irq:
+ free_irq(pcdev->irq_csi, pcdev);
+exit_iounmap:
+ iounmap(base_csi);
+exit_release:
+ release_mem_region(res_csi->start, resource_size(res_csi));
+exit_dma_free:
+#ifdef CONFIG_MACH_MX27
+ if (cpu_is_mx27())
+ imx_dma_free(pcdev->dma);
+exit_clk_put:
+ clk_put(pcdev->clk_csi);
+#endif /* CONFIG_MACH_MX27 */
+exit_kfree:
+ kfree(pcdev);
+exit:
+ return err;
+}
+
+static int __devexit mx2_camera_remove(struct platform_device *pdev)
+{
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct mx2_camera_dev *pcdev = container_of(soc_host,
+ struct mx2_camera_dev, soc_host);
+ struct resource *res;
+
+ clk_put(pcdev->clk_csi);
+#ifdef CONFIG_MACH_MX27
+ if (cpu_is_mx27())
+ imx_dma_free(pcdev->dma);
+#endif /* CONFIG_MACH_MX27 */
+ free_irq(pcdev->irq_csi, pcdev);
+ if (mx27_camera_emma(pcdev))
+ free_irq(pcdev->irq_emma, pcdev);
+
+ soc_camera_host_unregister(&pcdev->soc_host);
+
+ iounmap(pcdev->base_csi);
+
+ if (mx27_camera_emma(pcdev)) {
+ clk_disable(pcdev->clk_emma);
+ clk_put(pcdev->clk_emma);
+ iounmap(pcdev->base_emma);
+ res = pcdev->res_emma;
+ release_mem_region(res->start, resource_size(res));
+ }
+
+ res = pcdev->res_csi;
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(pcdev);
+
+ dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");
+
+ return 0;
+}
+
+static struct platform_driver mx2_camera_driver = {
+ .driver = {
+ .name = MX2_CAM_DRV_NAME,
+ },
+ .remove = __devexit_p(mx2_camera_remove),
+};
+
+
+static int __init mx2_camera_init(void)
+{
+ return platform_driver_probe(&mx2_camera_driver, &mx2_camera_probe);
+}
+
+static void __exit mx2_camera_exit(void)
+{
+ return platform_driver_unregister(&mx2_camera_driver);
+}
+
+module_init(mx2_camera_init);
+module_exit(mx2_camera_exit);
+
+MODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver");
+MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig
index 97c53949ca89..e63233fd2aaa 100644
--- a/drivers/media/video/omap/Kconfig
+++ b/drivers/media/video/omap/Kconfig
@@ -1,8 +1,8 @@
config VIDEO_OMAP2_VOUT
tristate "OMAP2/OMAP3 V4L2-Display driver"
- depends on ARCH_OMAP24XX || ARCH_OMAP34XX
+ depends on ARCH_OMAP2 || ARCH_OMAP3
select VIDEOBUF_GEN
- select VIDEOBUF_DMA_SG
+ select VIDEOBUF_DMA_CONTIG
select OMAP2_DSS
select OMAP2_VRAM
select OMAP2_VRFB
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
index b8bab00ad010..b28788070ae1 100644
--- a/drivers/media/video/omap/Makefile
+++ b/drivers/media/video/omap/Makefile
@@ -3,5 +3,5 @@
#
# OMAP2/3 Display driver
-omap-vout-mod-objs := omap_vout.o omap_voutlib.o
-obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout-mod.o
+omap-vout-y := omap_vout.o omap_voutlib.o
+obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index e7db0554949a..929073e792c9 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -38,8 +38,9 @@
#include <linux/dma-mapping.h>
#include <linux/irq.h>
#include <linux/videodev2.h>
+#include <linux/slab.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
@@ -1053,9 +1054,9 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb,
enum v4l2_field field)
{
+ dma_addr_t dmabuf;
struct vid_vrfb_dma *tx;
enum dss_rotation rotation;
- struct videobuf_dmabuf *dmabuf = NULL;
struct omap_vout_device *vout = q->priv_data;
u32 dest_frame_index = 0, src_element_index = 0;
u32 dest_element_index = 0, src_frame_index = 0;
@@ -1074,24 +1075,17 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
if (V4L2_MEMORY_USERPTR == vb->memory) {
if (0 == vb->baddr)
return -EINVAL;
- /* Virtual address */
- /* priv points to struct videobuf_pci_sg_memory. But we went
- * pointer to videobuf_dmabuf, which is member of
- * videobuf_pci_sg_memory */
- dmabuf = videobuf_to_dma(q->bufs[vb->i]);
- dmabuf->vmalloc = (void *) vb->baddr;
-
/* Physical address */
- dmabuf->bus_addr =
- (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr);
+ vout->queued_buf_addr[vb->i] = (u8 *)
+ omap_vout_uservirt_to_phys(vb->baddr);
+ } else {
+ vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
}
- if (!rotation_enabled(vout)) {
- dmabuf = videobuf_to_dma(q->bufs[vb->i]);
- vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr;
+ if (!rotation_enabled(vout))
return 0;
- }
- dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+
+ dmabuf = vout->buf_phy_addr[vb->i];
/* If rotation is enabled, copy input buffer into VRFB
* memory space using DMA. We are copying input buffer
* into VRFB memory space of desired angle and DSS will
@@ -1120,7 +1114,7 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
tx->dev_id, 0x0);
/* src_port required only for OMAP1 */
omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
- dmabuf->bus_addr, src_element_index, src_frame_index);
+ dmabuf, src_element_index, src_frame_index);
/*set dma source burst mode for VRFB */
omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
rotation = calc_rotation(vout);
@@ -1211,7 +1205,6 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
void *pos;
unsigned long start = vma->vm_start;
unsigned long size = (vma->vm_end - vma->vm_start);
- struct videobuf_dmabuf *dmabuf = NULL;
struct omap_vout_device *vout = file->private_data;
struct videobuf_queue *q = &vout->vbq;
@@ -1241,8 +1234,7 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &omap_vout_vm_ops;
vma->vm_private_data = (void *) vout;
- dmabuf = videobuf_to_dma(q->bufs[i]);
- pos = dmabuf->vmalloc;
+ pos = (void *)vout->buf_virt_addr[i];
vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT;
while (size > 0) {
unsigned long pfn;
@@ -1347,8 +1339,8 @@ static int omap_vout_open(struct file *file)
video_vbq_ops.buf_queue = omap_vout_buffer_queue;
spin_lock_init(&vout->vbq_lock);
- videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock,
- vout->type, V4L2_FIELD_NONE,
+ videobuf_queue_dma_contig_init(q, &video_vbq_ops, q->dev,
+ &vout->vbq_lock, vout->type, V4L2_FIELD_NONE,
sizeof(struct videobuf_buffer), vout);
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
@@ -1799,7 +1791,6 @@ static int vidioc_reqbufs(struct file *file, void *fh,
unsigned int i, num_buffers = 0;
struct omap_vout_device *vout = fh;
struct videobuf_queue *q = &vout->vbq;
- struct videobuf_dmabuf *dmabuf = NULL;
if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0))
return -EINVAL;
@@ -1825,8 +1816,7 @@ static int vidioc_reqbufs(struct file *file, void *fh,
num_buffers = (vout->vid == OMAP_VIDEO1) ?
video1_numbuffers : video2_numbuffers;
for (i = num_buffers; i < vout->buffer_allocated; i++) {
- dmabuf = videobuf_to_dma(q->bufs[i]);
- omap_vout_free_buffer((u32)dmabuf->vmalloc,
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
vout->buffer_size);
vout->buf_virt_addr[i] = 0;
vout->buf_phy_addr[i] = 0;
@@ -1855,12 +1845,7 @@ static int vidioc_reqbufs(struct file *file, void *fh,
goto reqbuf_err;
vout->buffer_allocated = req->count;
- for (i = 0; i < req->count; i++) {
- dmabuf = videobuf_to_dma(q->bufs[i]);
- dmabuf->vmalloc = (void *) vout->buf_virt_addr[i];
- dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i];
- dmabuf->sglen = 1;
- }
+
reqbuf_err:
mutex_unlock(&vout->lock);
return ret;
@@ -2488,7 +2473,7 @@ static int omap_vout_remove(struct platform_device *pdev)
for (k = 0; k < vid_dev->num_displays; k++) {
if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
- vid_dev->displays[k]->disable(vid_dev->displays[k]);
+ vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);
omap_dss_put_device(vid_dev->displays[k]);
}
@@ -2545,7 +2530,9 @@ static int __init omap_vout_probe(struct platform_device *pdev)
def_display = NULL;
}
if (def_display) {
- ret = def_display->enable(def_display);
+ struct omap_dss_driver *dssdrv = def_display->driver;
+
+ ret = dssdrv->enable(def_display);
if (ret) {
/* Here we are not considering a error
* as display may be enabled by frame
@@ -2559,21 +2546,21 @@ static int __init omap_vout_probe(struct platform_device *pdev)
if (def_display->caps &
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
- if (def_display->enable_te)
- def_display->enable_te(def_display, 1);
- if (def_display->set_update_mode)
- def_display->set_update_mode(def_display,
+ if (dssdrv->enable_te)
+ dssdrv->enable_te(def_display, 1);
+ if (dssdrv->set_update_mode)
+ dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_AUTO);
#else /* MANUAL_UPDATE */
- if (def_display->enable_te)
- def_display->enable_te(def_display, 0);
- if (def_display->set_update_mode)
- def_display->set_update_mode(def_display,
+ if (dssdrv->enable_te)
+ dssdrv->enable_te(def_display, 0);
+ if (dssdrv->set_update_mode)
+ dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_MANUAL);
#endif
} else {
- if (def_display->set_update_mode)
- def_display->set_update_mode(def_display,
+ if (dssdrv->set_update_mode)
+ dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_AUTO);
}
}
@@ -2592,8 +2579,8 @@ static int __init omap_vout_probe(struct platform_device *pdev)
for (i = 0; i < vid_dev->num_displays; i++) {
struct omap_dss_device *display = vid_dev->displays[i];
- if (display->update)
- display->update(display, 0, 0,
+ if (display->driver->update)
+ display->driver->update(display, 0, 0,
display->panel.timings.x_res,
display->panel.timings.y_res);
}
@@ -2608,8 +2595,8 @@ probe_err1:
if (ovl->manager && ovl->manager->device)
def_display = ovl->manager->device;
- if (def_display)
- def_display->disable(def_display);
+ if (def_display && def_display->driver)
+ def_display->driver->disable(def_display);
}
probe_err0:
kfree(vid_dev);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 0a877497b93f..07fabdd9b465 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -267,6 +267,21 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Xceive XC4000"},
{ TUNER_ABSENT, "Dibcom 7070"},
{ TUNER_PHILIPS_TDA8290, "NXP 18271C2"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ /* 160-169 */
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_ABSENT, "unknown"},
+ { TUNER_PHILIPS_FQ1236_MK5, "TCL M30WTP-4N-E"},
+ { TUNER_ABSENT, "unknown"},
};
/* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index aa0720af07a0..27a79f087b15 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -122,8 +122,8 @@ static struct uvc_control_info uvc_ctrls[] = {
.selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
.index = 10,
.size = 1,
- .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
- | UVC_CONTROL_RESTORE,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+ | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
},
{
.entity = UVC_GUID_UVC_PROCESSING,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 26386a92f5aa..9b089dfb173e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -353,6 +353,16 @@ config VMWARE_BALLOON
To compile this driver as a module, choose M here: the
module will be called vmware_balloon.
+config ARM_CHARLCD
+ bool "ARM Ltd. Character LCD Driver"
+ depends on PLAT_VERSATILE
+ help
+ This is a driver for the character LCD found on the ARM Ltd.
+ Versatile and RealView Platform Baseboards. It doesn't do
+ very much more than display the text "ARM Linux" on the first
+ line and the Linux version on the second line, but that's
+ still useful.
+
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 6ed06a19474a..67552d6e9327 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o
+obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c
new file mode 100644
index 000000000000..9e3879ef58f2
--- /dev/null
+++ b/drivers/misc/arm-charlcd.c
@@ -0,0 +1,396 @@
+/*
+ * Driver for the on-board character LCD found on some ARM reference boards
+ * This is basically an Hitachi HD44780 LCD with a custom IP block to drive it
+ * http://en.wikipedia.org/wiki/HD44780_Character_LCD
+ * Currently it will just display the text "ARM Linux" and the linux version
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Linus Walleij <triad@df.lth.se>
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <generated/utsrelease.h>
+
+#define DRIVERNAME "arm-charlcd"
+#define CHARLCD_TIMEOUT (msecs_to_jiffies(1000))
+
+/* Offsets to registers */
+#define CHAR_COM 0x00U
+#define CHAR_DAT 0x04U
+#define CHAR_RD 0x08U
+#define CHAR_RAW 0x0CU
+#define CHAR_MASK 0x10U
+#define CHAR_STAT 0x14U
+
+#define CHAR_RAW_CLEAR 0x00000000U
+#define CHAR_RAW_VALID 0x00000100U
+
+/* Hitachi HD44780 display commands */
+#define HD_CLEAR 0x01U
+#define HD_HOME 0x02U
+#define HD_ENTRYMODE 0x04U
+#define HD_ENTRYMODE_INCREMENT 0x02U
+#define HD_ENTRYMODE_SHIFT 0x01U
+#define HD_DISPCTRL 0x08U
+#define HD_DISPCTRL_ON 0x04U
+#define HD_DISPCTRL_CURSOR_ON 0x02U
+#define HD_DISPCTRL_CURSOR_BLINK 0x01U
+#define HD_CRSR_SHIFT 0x10U
+#define HD_CRSR_SHIFT_DISPLAY 0x08U
+#define HD_CRSR_SHIFT_DISPLAY_RIGHT 0x04U
+#define HD_FUNCSET 0x20U
+#define HD_FUNCSET_8BIT 0x10U
+#define HD_FUNCSET_2_LINES 0x08U
+#define HD_FUNCSET_FONT_5X10 0x04U
+#define HD_SET_CGRAM 0x40U
+#define HD_SET_DDRAM 0x80U
+#define HD_BUSY_FLAG 0x80U
+
+/**
+ * @dev: a pointer back to containing device
+ * @phybase: the offset to the controller in physical memory
+ * @physize: the size of the physical page
+ * @virtbase: the offset to the controller in virtual memory
+ * @irq: reserved interrupt number
+ * @complete: completion structure for the last LCD command
+ */
+struct charlcd {
+ struct device *dev;
+ u32 phybase;
+ u32 physize;
+ void __iomem *virtbase;
+ int irq;
+ struct completion complete;
+ struct delayed_work init_work;
+};
+
+static irqreturn_t charlcd_interrupt(int irq, void *data)
+{
+ struct charlcd *lcd = data;
+ u8 status;
+
+ status = readl(lcd->virtbase + CHAR_STAT) & 0x01;
+ /* Clear IRQ */
+ writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW);
+ if (status)
+ complete(&lcd->complete);
+ else
+ dev_info(lcd->dev, "Spurious IRQ (%02x)\n", status);
+ return IRQ_HANDLED;
+}
+
+
+static void charlcd_wait_complete_irq(struct charlcd *lcd)
+{
+ int ret;
+
+ ret = wait_for_completion_interruptible_timeout(&lcd->complete,
+ CHARLCD_TIMEOUT);
+ /* Disable IRQ after completion */
+ writel(0x00, lcd->virtbase + CHAR_MASK);
+
+ if (ret < 0) {
+ dev_err(lcd->dev,
+ "wait_for_completion_interruptible_timeout() "
+ "returned %d waiting for ready\n", ret);
+ return;
+ }
+
+ if (ret == 0) {
+ dev_err(lcd->dev, "charlcd controller timed out "
+ "waiting for ready\n");
+ return;
+ }
+}
+
+static u8 charlcd_4bit_read_char(struct charlcd *lcd)
+{
+ u8 data;
+ u32 val;
+ int i;
+
+ /* If we can, use an IRQ to wait for the data, else poll */
+ if (lcd->irq >= 0)
+ charlcd_wait_complete_irq(lcd);
+ else {
+ i = 0;
+ val = 0;
+ while (!(val & CHAR_RAW_VALID) && i < 10) {
+ udelay(100);
+ val = readl(lcd->virtbase + CHAR_RAW);
+ i++;
+ }
+
+ writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW);
+ }
+ msleep(1);
+
+ /* Read the 4 high bits of the data */
+ data = readl(lcd->virtbase + CHAR_RD) & 0xf0;
+
+ /*
+ * The second read for the low bits does not trigger an IRQ
+ * so in this case we have to poll for the 4 lower bits
+ */
+ i = 0;
+ val = 0;
+ while (!(val & CHAR_RAW_VALID) && i < 10) {
+ udelay(100);
+ val = readl(lcd->virtbase + CHAR_RAW);
+ i++;
+ }
+ writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW);
+ msleep(1);
+
+ /* Read the 4 low bits of the data */
+ data |= (readl(lcd->virtbase + CHAR_RD) >> 4) & 0x0f;
+
+ return data;
+}
+
+static bool charlcd_4bit_read_bf(struct charlcd *lcd)
+{
+ if (lcd->irq >= 0) {
+ /*
+ * If we'll use IRQs to wait for the busyflag, clear any
+ * pending flag and enable IRQ
+ */
+ writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW);
+ init_completion(&lcd->complete);
+ writel(0x01, lcd->virtbase + CHAR_MASK);
+ }
+ readl(lcd->virtbase + CHAR_COM);
+ return charlcd_4bit_read_char(lcd) & HD_BUSY_FLAG ? true : false;
+}
+
+static void charlcd_4bit_wait_busy(struct charlcd *lcd)
+{
+ int retries = 50;
+
+ udelay(100);
+ while (charlcd_4bit_read_bf(lcd) && retries)
+ retries--;
+ if (!retries)
+ dev_err(lcd->dev, "timeout waiting for busyflag\n");
+}
+
+static void charlcd_4bit_command(struct charlcd *lcd, u8 cmd)
+{
+ u32 cmdlo = (cmd << 4) & 0xf0;
+ u32 cmdhi = (cmd & 0xf0);
+
+ writel(cmdhi, lcd->virtbase + CHAR_COM);
+ udelay(10);
+ writel(cmdlo, lcd->virtbase + CHAR_COM);
+ charlcd_4bit_wait_busy(lcd);
+}
+
+static void charlcd_4bit_char(struct charlcd *lcd, u8 ch)
+{
+ u32 chlo = (ch << 4) & 0xf0;
+ u32 chhi = (ch & 0xf0);
+
+ writel(chhi, lcd->virtbase + CHAR_DAT);
+ udelay(10);
+ writel(chlo, lcd->virtbase + CHAR_DAT);
+ charlcd_4bit_wait_busy(lcd);
+}
+
+static void charlcd_4bit_print(struct charlcd *lcd, int line, const char *str)
+{
+ u8 offset;
+ int i;
+
+ /*
+ * We support line 0, 1
+ * Line 1 runs from 0x00..0x27
+ * Line 2 runs from 0x28..0x4f
+ */
+ if (line == 0)
+ offset = 0;
+ else if (line == 1)
+ offset = 0x28;
+ else
+ return;
+
+ /* Set offset */
+ charlcd_4bit_command(lcd, HD_SET_DDRAM | offset);
+
+ /* Send string */
+ for (i = 0; i < strlen(str) && i < 0x28; i++)
+ charlcd_4bit_char(lcd, str[i]);
+}
+
+static void charlcd_4bit_init(struct charlcd *lcd)
+{
+ /* These commands cannot be checked with the busy flag */
+ writel(HD_FUNCSET | HD_FUNCSET_8BIT, lcd->virtbase + CHAR_COM);
+ msleep(5);
+ writel(HD_FUNCSET | HD_FUNCSET_8BIT, lcd->virtbase + CHAR_COM);
+ udelay(100);
+ writel(HD_FUNCSET | HD_FUNCSET_8BIT, lcd->virtbase + CHAR_COM);
+ udelay(100);
+ /* Go to 4bit mode */
+ writel(HD_FUNCSET, lcd->virtbase + CHAR_COM);
+ udelay(100);
+ /*
+ * 4bit mode, 2 lines, 5x8 font, after this the number of lines
+ * and the font cannot be changed until the next initialization sequence
+ */
+ charlcd_4bit_command(lcd, HD_FUNCSET | HD_FUNCSET_2_LINES);
+ charlcd_4bit_command(lcd, HD_DISPCTRL | HD_DISPCTRL_ON);
+ charlcd_4bit_command(lcd, HD_ENTRYMODE | HD_ENTRYMODE_INCREMENT);
+ charlcd_4bit_command(lcd, HD_CLEAR);
+ charlcd_4bit_command(lcd, HD_HOME);
+ /* Put something useful in the display */
+ charlcd_4bit_print(lcd, 0, "ARM Linux");
+ charlcd_4bit_print(lcd, 1, UTS_RELEASE);
+}
+
+static void charlcd_init_work(struct work_struct *work)
+{
+ struct charlcd *lcd =
+ container_of(work, struct charlcd, init_work.work);
+
+ charlcd_4bit_init(lcd);
+}
+
+static int __init charlcd_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct charlcd *lcd;
+ struct resource *res;
+
+ lcd = kzalloc(sizeof(struct charlcd), GFP_KERNEL);
+ if (!lcd)
+ return -ENOMEM;
+
+ lcd->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENOENT;
+ goto out_no_resource;
+ }
+ lcd->phybase = res->start;
+ lcd->physize = resource_size(res);
+
+ if (request_mem_region(lcd->phybase, lcd->physize,
+ DRIVERNAME) == NULL) {
+ ret = -EBUSY;
+ goto out_no_memregion;
+ }
+
+ lcd->virtbase = ioremap(lcd->phybase, lcd->physize);
+ if (!lcd->virtbase) {
+ ret = -ENOMEM;
+ goto out_no_remap;
+ }
+
+ lcd->irq = platform_get_irq(pdev, 0);
+ /* If no IRQ is supplied, we'll survive without it */
+ if (lcd->irq >= 0) {
+ if (request_irq(lcd->irq, charlcd_interrupt, IRQF_DISABLED,
+ DRIVERNAME, lcd)) {
+ ret = -EIO;
+ goto out_no_irq;
+ }
+ }
+
+ platform_set_drvdata(pdev, lcd);
+
+ /*
+ * Initialize the display in a delayed work, because
+ * it is VERY slow and would slow down the boot of the system.
+ */
+ INIT_DELAYED_WORK(&lcd->init_work, charlcd_init_work);
+ schedule_delayed_work(&lcd->init_work, 0);
+
+ dev_info(&pdev->dev, "initalized ARM character LCD at %08x\n",
+ lcd->phybase);
+
+ return 0;
+
+out_no_irq:
+ iounmap(lcd->virtbase);
+out_no_remap:
+ platform_set_drvdata(pdev, NULL);
+out_no_memregion:
+ release_mem_region(lcd->phybase, SZ_4K);
+out_no_resource:
+ kfree(lcd);
+ return ret;
+}
+
+static int __exit charlcd_remove(struct platform_device *pdev)
+{
+ struct charlcd *lcd = platform_get_drvdata(pdev);
+
+ if (lcd) {
+ free_irq(lcd->irq, lcd);
+ iounmap(lcd->virtbase);
+ release_mem_region(lcd->phybase, lcd->physize);
+ platform_set_drvdata(pdev, NULL);
+ kfree(lcd);
+ }
+
+ return 0;
+}
+
+static int charlcd_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct charlcd *lcd = platform_get_drvdata(pdev);
+
+ /* Power the display off */
+ charlcd_4bit_command(lcd, HD_DISPCTRL);
+ return 0;
+}
+
+static int charlcd_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct charlcd *lcd = platform_get_drvdata(pdev);
+
+ /* Turn the display back on */
+ charlcd_4bit_command(lcd, HD_DISPCTRL | HD_DISPCTRL_ON);
+ return 0;
+}
+
+static const struct dev_pm_ops charlcd_pm_ops = {
+ .suspend = charlcd_suspend,
+ .resume = charlcd_resume,
+};
+
+static struct platform_driver charlcd_driver = {
+ .driver = {
+ .name = DRIVERNAME,
+ .owner = THIS_MODULE,
+ .pm = &charlcd_pm_ops,
+ },
+ .remove = __exit_p(charlcd_remove),
+};
+
+static int __init charlcd_init(void)
+{
+ return platform_driver_probe(&charlcd_driver, charlcd_probe);
+}
+
+static void __exit charlcd_exit(void)
+{
+ platform_driver_unregister(&charlcd_driver);
+}
+
+module_init(charlcd_init);
+module_exit(charlcd_exit);
+
+MODULE_AUTHOR("Linus Walleij <triad@df.lth.se>");
+MODULE_DESCRIPTION("ARM Character LCD Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index 9bec24db4d41..2d44b3300104 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -366,6 +366,6 @@ static int __init cs5535_mfgpt_init(void)
module_init(cs5535_mfgpt_init);
-MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>");
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("CS5535/CS5536 MFGPT timer driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4917af96bae1..840b301b5671 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -26,7 +26,6 @@
#include <linux/amba/mmci.h>
#include <linux/regulator/consumer.h>
-#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/sizes.h>
@@ -37,12 +36,39 @@
static unsigned int fmax = 515633;
+/**
+ * struct variant_data - MMCI variant-specific quirks
+ * @clkreg: default value for MCICLOCK register
+ * @clkreg_enable: enable value for MMCICLOCK register
+ * @datalength_bits: number of bits in the MMCIDATALENGTH register
+ */
+struct variant_data {
+ unsigned int clkreg;
+ unsigned int clkreg_enable;
+ unsigned int datalength_bits;
+};
+
+static struct variant_data variant_arm = {
+ .datalength_bits = 16,
+};
+
+static struct variant_data variant_u300 = {
+ .clkreg_enable = 1 << 13, /* HWFCEN */
+ .datalength_bits = 16,
+};
+
+static struct variant_data variant_ux500 = {
+ .clkreg = MCI_CLK_ENABLE,
+ .clkreg_enable = 1 << 14, /* HWFCEN */
+ .datalength_bits = 24,
+};
/*
* This must be called with host->lock held
*/
static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
{
- u32 clk = 0;
+ struct variant_data *variant = host->variant;
+ u32 clk = variant->clkreg;
if (desired) {
if (desired >= host->mclk) {
@@ -54,8 +80,8 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
clk = 255;
host->cclk = host->mclk / (2 * (clk + 1));
}
- if (host->hw_designer == AMBA_VENDOR_ST)
- clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */
+
+ clk |= variant->clkreg_enable;
clk |= MCI_CLK_ENABLE;
/* This hasn't proven to be worthwhile */
/* clk |= MCI_CLK_PWRSAVE; */
@@ -98,6 +124,18 @@ static void mmci_stop_data(struct mmci_host *host)
host->data = NULL;
}
+static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
+{
+ unsigned int flags = SG_MITER_ATOMIC;
+
+ if (data->flags & MMC_DATA_READ)
+ flags |= SG_MITER_TO_SG;
+ else
+ flags |= SG_MITER_FROM_SG;
+
+ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
+}
+
static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
{
unsigned int datactrl, timeout, irqmask;
@@ -109,7 +147,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
data->blksz, data->blocks, data->flags);
host->data = data;
- host->size = data->blksz;
+ host->size = data->blksz * data->blocks;
host->data_xfered = 0;
mmci_init_sg(host, data);
@@ -210,8 +248,17 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
* We hit an error condition. Ensure that any data
* partially written to a page is properly coherent.
*/
- if (host->sg_len && data->flags & MMC_DATA_READ)
- flush_dcache_page(sg_page(host->sg_ptr));
+ if (data->flags & MMC_DATA_READ) {
+ struct sg_mapping_iter *sg_miter = &host->sg_miter;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (sg_miter_next(sg_miter)) {
+ flush_dcache_page(sg_miter->page);
+ sg_miter_stop(sg_miter);
+ }
+ local_irq_restore(flags);
+ }
}
if (status & MCI_DATAEND) {
mmci_stop_data(host);
@@ -314,15 +361,18 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
{
struct mmci_host *host = dev_id;
+ struct sg_mapping_iter *sg_miter = &host->sg_miter;
void __iomem *base = host->base;
+ unsigned long flags;
u32 status;
status = readl(base + MMCISTATUS);
dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status);
+ local_irq_save(flags);
+
do {
- unsigned long flags;
unsigned int remain, len;
char *buffer;
@@ -336,11 +386,11 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
break;
- /*
- * Map the current scatter buffer.
- */
- buffer = mmci_kmap_atomic(host, &flags) + host->sg_off;
- remain = host->sg_ptr->length - host->sg_off;
+ if (!sg_miter_next(sg_miter))
+ break;
+
+ buffer = sg_miter->addr;
+ remain = sg_miter->length;
len = 0;
if (status & MCI_RXACTIVE)
@@ -348,31 +398,24 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
if (status & MCI_TXACTIVE)
len = mmci_pio_write(host, buffer, remain, status);
- /*
- * Unmap the buffer.
- */
- mmci_kunmap_atomic(host, buffer, &flags);
+ sg_miter->consumed = len;
- host->sg_off += len;
host->size -= len;
remain -= len;
if (remain)
break;
- /*
- * If we were reading, and we have completed this
- * page, ensure that the data cache is coherent.
- */
if (status & MCI_RXACTIVE)
- flush_dcache_page(sg_page(host->sg_ptr));
-
- if (!mmci_next_sg(host))
- break;
+ flush_dcache_page(sg_miter->page);
status = readl(base + MMCISTATUS);
} while (1);
+ sg_miter_stop(sg_miter);
+
+ local_irq_restore(flags);
+
/*
* If we're nearing the end of the read, switch to
* "any data available" mode.
@@ -477,16 +520,9 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* This implicitly enables the regulator */
mmc_regulator_set_ocr(host->vcc, ios->vdd);
#endif
- /*
- * The translate_vdd function is not used if you have
- * an external regulator, or your design is really weird.
- * Using it would mean sending in power control BOTH using
- * a regulator AND the 4 MMCIPWR bits. If we don't have
- * a regulator, we might have some other platform specific
- * power control behind this translate function.
- */
- if (!host->vcc && host->plat->translate_vdd)
- pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
+ if (host->plat->vdd_handler)
+ pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd,
+ ios->power_mode);
/* The ST version does not have this, fall through to POWER_ON */
if (host->hw_designer != AMBA_VENDOR_ST) {
pwr |= MCI_PWR_UP;
@@ -539,9 +575,13 @@ static int mmci_get_cd(struct mmc_host *mmc)
if (host->gpio_cd == -ENOSYS)
status = host->plat->status(mmc_dev(host->mmc));
else
- status = gpio_get_value(host->gpio_cd);
+ status = !gpio_get_value(host->gpio_cd);
- return !status;
+ /*
+ * Use positive logic throughout - status is zero for no card,
+ * non-zero for card inserted.
+ */
+ return status;
}
static const struct mmc_host_ops mmci_ops = {
@@ -551,21 +591,10 @@ static const struct mmc_host_ops mmci_ops = {
.get_cd = mmci_get_cd,
};
-static void mmci_check_status(unsigned long data)
-{
- struct mmci_host *host = (struct mmci_host *)data;
- unsigned int status = mmci_get_cd(host->mmc);
-
- if (status ^ host->oldstat)
- mmc_detect_change(host->mmc, 0);
-
- host->oldstat = status;
- mod_timer(&host->timer, jiffies + HZ);
-}
-
static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
{
struct mmci_platform_data *plat = dev->dev.platform_data;
+ struct variant_data *variant = id->data;
struct mmci_host *host;
struct mmc_host *mmc;
int ret;
@@ -609,6 +638,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
goto clk_free;
host->plat = plat;
+ host->variant = variant;
host->mclk = clk_get_rate(host->clk);
/*
* According to the spec, mclk is max 100 MHz,
@@ -669,6 +699,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
if (host->vcc == NULL)
mmc->ocr_avail = plat->ocr_mask;
mmc->caps = plat->capabilities;
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
/*
* We can do SGIO
@@ -677,10 +708,11 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
mmc->max_phys_segs = NR_SG;
/*
- * Since we only have a 16-bit data length register, we must
- * ensure that we don't exceed 2^16-1 bytes in a single request.
+ * Since only a certain number of bits are valid in the data length
+ * register, we must ensure that we don't exceed 2^num-1 bytes in a
+ * single request.
*/
- mmc->max_req_size = 65535;
+ mmc->max_req_size = (1 << variant->datalength_bits) - 1;
/*
* Set the maximum segment size. Since we aren't doing DMA
@@ -734,7 +766,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
amba_set_drvdata(dev, mmc);
- host->oldstat = mmci_get_cd(host->mmc);
mmc_add_host(mmc);
@@ -742,12 +773,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
(unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
- init_timer(&host->timer);
- host->timer.data = (unsigned long)host;
- host->timer.function = mmci_check_status;
- host->timer.expires = jiffies + HZ;
- add_timer(&host->timer);
-
return 0;
irq0_free:
@@ -781,8 +806,6 @@ static int __devexit mmci_remove(struct amba_device *dev)
if (mmc) {
struct mmci_host *host = mmc_priv(mmc);
- del_timer_sync(&host->timer);
-
mmc_remove_host(mmc);
writel(0, host->base + MMCIMASK0);
@@ -856,19 +879,28 @@ static struct amba_id mmci_ids[] = {
{
.id = 0x00041180,
.mask = 0x000fffff,
+ .data = &variant_arm,
},
{
.id = 0x00041181,
.mask = 0x000fffff,
+ .data = &variant_arm,
},
/* ST Micro variants */
{
.id = 0x00180180,
.mask = 0x00ffffff,
+ .data = &variant_u300,
},
{
.id = 0x00280180,
.mask = 0x00ffffff,
+ .data = &variant_u300,
+ },
+ {
+ .id = 0x00480180,
+ .mask = 0x00ffffff,
+ .data = &variant_ux500,
},
{ 0, 0 },
};
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index d77062e5e3af..68970cfb81e1 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -28,8 +28,6 @@
#define MCI_4BIT_BUS (1 << 11)
/* 8bit wide buses supported in ST Micro versions */
#define MCI_ST_8BIT_BUS (1 << 12)
-/* HW flow control on the ST Micro version */
-#define MCI_ST_FCEN (1 << 13)
#define MMCIARGUMENT 0x008
#define MMCICOMMAND 0x00c
@@ -145,6 +143,7 @@
#define NR_SG 16
struct clk;
+struct variant_data;
struct mmci_host {
void __iomem *base;
@@ -164,6 +163,7 @@ struct mmci_host {
unsigned int cclk;
u32 pwr;
struct mmci_platform_data *plat;
+ struct variant_data *variant;
u8 hw_designer;
u8 hw_revision:4;
@@ -171,42 +171,9 @@ struct mmci_host {
struct timer_list timer;
unsigned int oldstat;
- unsigned int sg_len;
-
/* pio stuff */
- struct scatterlist *sg_ptr;
- unsigned int sg_off;
+ struct sg_mapping_iter sg_miter;
unsigned int size;
struct regulator *vcc;
};
-static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
-{
- /*
- * Ideally, we want the higher levels to pass us a scatter list.
- */
- host->sg_len = data->sg_len;
- host->sg_ptr = data->sg;
- host->sg_off = 0;
-}
-
-static inline int mmci_next_sg(struct mmci_host *host)
-{
- host->sg_ptr++;
- host->sg_off = 0;
- return --host->sg_len;
-}
-
-static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags)
-{
- struct scatterlist *sg = host->sg_ptr;
-
- local_irq_save(*flags);
- return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-}
-
-static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
-{
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
- local_irq_restore(*flags);
-}
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index d9d4a72e0ec7..350f78e86245 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -119,6 +119,7 @@ struct mxcmci_host {
int detect_irq;
int dma;
int do_dma;
+ int default_irq_mask;
int use_sdio;
unsigned int power_mode;
struct imxmmc_platform_data *pdata;
@@ -228,7 +229,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
unsigned int cmdat)
{
- u32 int_cntr;
+ u32 int_cntr = host->default_irq_mask;
unsigned long flags;
WARN_ON(host->cmd != NULL);
@@ -275,7 +276,7 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
static void mxcmci_finish_request(struct mxcmci_host *host,
struct mmc_request *req)
{
- u32 int_cntr = 0;
+ u32 int_cntr = host->default_irq_mask;
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
@@ -585,6 +586,9 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
(stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
mxcmci_data_done(host, stat);
#endif
+ if (host->default_irq_mask &&
+ (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
+ mmc_detect_change(host->mmc, msecs_to_jiffies(200));
return IRQ_HANDLED;
}
@@ -809,6 +813,12 @@ static int mxcmci_probe(struct platform_device *pdev)
else
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+ if (host->pdata && host->pdata->dat3_card_detect)
+ host->default_irq_mask =
+ INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN;
+ else
+ host->default_irq_mask = 0;
+
host->res = r;
host->irq = irq;
@@ -835,7 +845,7 @@ static int mxcmci_probe(struct platform_device *pdev)
/* recommended in data sheet */
writew(0x2db4, host->base + MMC_REG_READ_TO);
- writel(0, host->base + MMC_REG_INT_CNTR);
+ writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
#ifdef HAS_DMA
host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
@@ -926,43 +936,47 @@ static int mxcmci_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int mxcmci_suspend(struct platform_device *dev, pm_message_t state)
+static int mxcmci_suspend(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct mxcmci_host *host = mmc_priv(mmc);
int ret = 0;
if (mmc)
ret = mmc_suspend_host(mmc);
+ clk_disable(host->clk);
return ret;
}
-static int mxcmci_resume(struct platform_device *dev)
+static int mxcmci_resume(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
- struct mxcmci_host *host;
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct mxcmci_host *host = mmc_priv(mmc);
int ret = 0;
- if (mmc) {
- host = mmc_priv(mmc);
+ clk_enable(host->clk);
+ if (mmc)
ret = mmc_resume_host(mmc);
- }
return ret;
}
-#else
-#define mxcmci_suspend NULL
-#define mxcmci_resume NULL
-#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops mxcmci_pm_ops = {
+ .suspend = mxcmci_suspend,
+ .resume = mxcmci_resume,
+};
+#endif
static struct platform_driver mxcmci_driver = {
.probe = mxcmci_probe,
.remove = mxcmci_remove,
- .suspend = mxcmci_suspend,
- .resume = mxcmci_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &mxcmci_pm_ops,
+#endif
}
};
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index af217924a76e..ad30f074ee15 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -365,6 +365,26 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_s3c *sc = sdhci_priv(host);
+ int ptr;
+
+ sdhci_remove_host(host, 1);
+
+ for (ptr = 0; ptr < 3; ptr++) {
+ clk_disable(sc->clk_bus[ptr]);
+ clk_put(sc->clk_bus[ptr]);
+ }
+ clk_disable(sc->clk_io);
+ clk_put(sc->clk_io);
+
+ iounmap(host->ioaddr);
+ release_resource(sc->ioarea);
+ kfree(sc->ioarea);
+
+ sdhci_free_host(host);
+ platform_set_drvdata(pdev, NULL);
+
return 0;
}
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 82e94389824e..0d76b169482f 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -623,8 +623,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
else
host->buf_start = column + mtd->writesize;
- if (mtd->writesize > 512)
- command = NAND_CMD_READ0; /* only READ0 is valid */
+ command = NAND_CMD_READ0; /* only READ0 is valid */
send_cmd(host, command, false);
mxc_do_addr_cycle(mtd, column, page_addr);
@@ -639,31 +638,11 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
break;
case NAND_CMD_SEQIN:
- if (column >= mtd->writesize) {
- /*
- * FIXME: before send SEQIN command for write OOB,
- * We must read one page out.
- * For K9F1GXX has no READ1 command to set current HW
- * pointer to spare area, we must write the whole page
- * including OOB together.
- */
- if (mtd->writesize > 512)
- /* call ourself to read a page */
- mxc_nand_command(mtd, NAND_CMD_READ0, 0,
- page_addr);
-
- host->buf_start = column;
-
- /* Set program pointer to spare region */
- if (mtd->writesize == 512)
- send_cmd(host, NAND_CMD_READOOB, false);
- } else {
- host->buf_start = column;
+ if (column >= mtd->writesize)
+ /* call ourself to read a page */
+ mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
- /* Set program pointer to page start */
- if (mtd->writesize == 512)
- send_cmd(host, NAND_CMD_READ0, false);
- }
+ host->buf_start = column;
send_cmd(host, command, false);
mxc_do_addr_cycle(mtd, column, page_addr);
@@ -853,6 +832,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
if (nr_parts > 0)
add_mtd_partitions(mtd, host->parts, nr_parts);
+ else if (pdata->parts)
+ add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
else
#endif
{
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 13b05cb33b08..78ae89488a4f 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -593,6 +593,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
ubi->max_ec = si->max_ec;
ubi->mean_ec = si->mean_ec;
+ ubi_msg("max. sequence number: %llu", si->max_sqnum);
err = ubi_read_volume_table(ubi, si);
if (err)
@@ -981,7 +982,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_msg("number of PEBs reserved for bad PEB handling: %d",
ubi->beb_rsvd_pebs);
ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
- ubi_msg("image sequence number: %d", ubi->image_seq);
+ ubi_msg("image sequence number: %d", ubi->image_seq);
/*
* The below lock makes sure we do not race with 'ubi_thread()' which
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 9f87c99189a9..fe74749e0dae 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -418,7 +418,8 @@ retry:
* may try to recover data. FIXME: but this is
* not implemented.
*/
- if (err == UBI_IO_BAD_VID_HDR) {
+ if (err == UBI_IO_BAD_HDR_READ ||
+ err == UBI_IO_BAD_HDR) {
ubi_warn("corrupted VID header at PEB "
"%d, LEB %d:%d", pnum, vol_id,
lnum);
@@ -961,8 +962,8 @@ write_error:
*/
static int is_error_sane(int err)
{
- if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR ||
- err == -ETIMEDOUT)
+ if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
+ err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)
return 0;
return 1;
}
@@ -1165,6 +1166,44 @@ out_unlock_leb:
}
/**
+ * print_rsvd_warning - warn about not having enough reserved PEBs.
+ * @ubi: UBI device description object
+ *
+ * This is a helper function for 'ubi_eba_init_scan()' which is called when UBI
+ * cannot reserve enough PEBs for bad block handling. This function makes a
+ * decision whether we have to print a warning or not. The algorithm is as
+ * follows:
+ * o if this is a new UBI image, then just print the warning
+ * o if this is an UBI image which has already been used for some time, print
+ * a warning only if we can reserve less than 10% of the expected amount of
+ * the reserved PEB.
+ *
+ * The idea is that when UBI is used, PEBs become bad, and the reserved pool
+ * of PEBs becomes smaller, which is normal and we do not want to scare users
+ * with a warning every time they attach the MTD device. This was an issue
+ * reported by real users.
+ */
+static void print_rsvd_warning(struct ubi_device *ubi,
+ struct ubi_scan_info *si)
+{
+ /*
+ * The 1 << 18 (256KiB) number is picked randomly, just a reasonably
+ * large number to distinguish between newly flashed and used images.
+ */
+ if (si->max_sqnum > (1 << 18)) {
+ int min = ubi->beb_rsvd_level / 10;
+
+ if (!min)
+ min = 1;
+ if (ubi->beb_rsvd_pebs > min)
+ return;
+ }
+
+ ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
+ " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
+}
+
+/**
* ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
* @ubi: UBI device description object
* @si: scanning information
@@ -1236,9 +1275,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < ubi->beb_rsvd_level) {
/* No enough free physical eraseblocks */
ubi->beb_rsvd_pebs = ubi->avail_pebs;
- ubi_warn("cannot reserve enough PEBs for bad PEB "
- "handling, reserved %d, need %d",
- ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
+ print_rsvd_warning(ubi, si);
} else
ubi->beb_rsvd_pebs = ubi->beb_rsvd_level;
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 4b979e34b159..332f992f13d9 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -150,6 +150,8 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
retry:
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
if (err) {
+ const char *errstr = (err == -EBADMSG) ? " (ECC error)" : "";
+
if (err == -EUCLEAN) {
/*
* -EUCLEAN is reported if there was a bit-flip which
@@ -165,15 +167,15 @@ retry:
}
if (read != len && retries++ < UBI_IO_RETRIES) {
- dbg_io("error %d while reading %d bytes from PEB %d:%d,"
+ dbg_io("error %d%s while reading %d bytes from PEB %d:%d,"
" read only %zd bytes, retry",
- err, len, pnum, offset, read);
+ err, errstr, len, pnum, offset, read);
yield();
goto retry;
}
- ubi_err("error %d while reading %d bytes from PEB %d:%d, "
- "read %zd bytes", err, len, pnum, offset, read);
+ ubi_err("error %d%s while reading %d bytes from PEB %d:%d, "
+ "read %zd bytes", err, errstr, len, pnum, offset, read);
ubi_dbg_dump_stack();
/*
@@ -515,7 +517,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
* In this case we probably anyway have garbage in this PEB.
*/
err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
- if (err1 == UBI_IO_BAD_VID_HDR)
+ if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)
/*
* The VID header is corrupted, so we can safely erase this
* PEB and not afraid that it will be treated as a valid PEB in
@@ -709,7 +711,7 @@ bad:
* o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
* and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon (but may be not);
- * o %UBI_IO_BAD_EC_HDR if the erase counter header is corrupted (a CRC error);
+ * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);
* o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
* o a negative error code in case of failure.
*/
@@ -736,23 +738,21 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
* header is still OK, we just report this as there was a
* bit-flip.
*/
- read_err = err;
+ if (err == -EBADMSG)
+ read_err = UBI_IO_BAD_HDR_READ;
}
magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) {
+ if (read_err)
+ return read_err;
+
/*
* The magic field is wrong. Let's check if we have read all
* 0xFF. If yes, this physical eraseblock is assumed to be
* empty.
- *
- * But if there was a read error, we do not test it for all
- * 0xFFs. Even if it does contain all 0xFFs, this error
- * indicates that something is still wrong with this physical
- * eraseblock and we anyway cannot treat it as empty.
*/
- if (read_err != -EBADMSG &&
- check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
+ if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
/* The physical eraseblock is supposedly empty */
if (verbose)
ubi_warn("no EC header found at PEB %d, "
@@ -774,7 +774,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
- return UBI_IO_BAD_EC_HDR;
+ return UBI_IO_BAD_HDR;
}
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -788,7 +788,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
- return UBI_IO_BAD_EC_HDR;
+ return read_err ?: UBI_IO_BAD_HDR;
}
/* And of course validate what has just been read from the media */
@@ -798,6 +798,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
return -EINVAL;
}
+ /*
+ * If there was %-EBADMSG, but the header CRC is still OK, report about
+ * a bit-flip to force scrubbing on this PEB.
+ */
return read_err ? UBI_IO_BITFLIPS : 0;
}
@@ -977,7 +981,7 @@ bad:
* o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
* and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon;
- * o %UBI_IO_BAD_VID_HDR if the volume identifier header is corrupted (a CRC
+ * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC
* error detected);
* o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
* header there);
@@ -1008,22 +1012,20 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
* CRC check-sum and we will identify this. If the VID header is
* still OK, we just report this as there was a bit-flip.
*/
- read_err = err;
+ if (err == -EBADMSG)
+ read_err = UBI_IO_BAD_HDR_READ;
}
magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) {
+ if (read_err)
+ return read_err;
+
/*
* If we have read all 0xFF bytes, the VID header probably does
* not exist and the physical eraseblock is assumed to be free.
- *
- * But if there was a read error, we do not test the data for
- * 0xFFs. Even if it does contain all 0xFFs, this error
- * indicates that something is still wrong with this physical
- * eraseblock and it cannot be regarded as free.
*/
- if (read_err != -EBADMSG &&
- check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
+ if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
/* The physical eraseblock is supposedly free */
if (verbose)
ubi_warn("no VID header found at PEB %d, "
@@ -1045,7 +1047,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
- return UBI_IO_BAD_VID_HDR;
+ return UBI_IO_BAD_HDR;
}
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
@@ -1059,7 +1061,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
- return UBI_IO_BAD_VID_HDR;
+ return read_err ?: UBI_IO_BAD_HDR;
}
/* Validate the VID header that we have just read */
@@ -1069,6 +1071,10 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
return -EINVAL;
}
+ /*
+ * If there was a read error (%-EBADMSG), but the header CRC is still
+ * OK, report about a bit-flip to force scrubbing on this PEB.
+ */
return read_err ? UBI_IO_BITFLIPS : 0;
}
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index aed19f33b8f3..372a15ac9995 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -44,6 +44,7 @@
#include <linux/slab.h>
#include <linux/crc32.h>
#include <linux/math64.h>
+#include <linux/random.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
@@ -72,16 +73,19 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
{
struct ubi_scan_leb *seb;
- if (list == &si->free)
+ if (list == &si->free) {
dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
- else if (list == &si->erase)
+ si->free_peb_count += 1;
+ } else if (list == &si->erase) {
dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
- else if (list == &si->corr) {
+ si->erase_peb_count += 1;
+ } else if (list == &si->corr) {
dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
- si->corr_count += 1;
- } else if (list == &si->alien)
+ si->corr_peb_count += 1;
+ } else if (list == &si->alien) {
dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
- else
+ si->alien_peb_count += 1;
+ } else
BUG();
seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
@@ -517,6 +521,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
sv->leb_count += 1;
rb_link_node(&seb->u.rb, parent, p);
rb_insert_color(&seb->u.rb, &sv->root);
+ si->used_peb_count += 1;
return 0;
}
@@ -745,19 +750,17 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
bitflips = 1;
else if (err == UBI_IO_PEB_EMPTY)
return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
- else if (err == UBI_IO_BAD_EC_HDR) {
+ else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) {
/*
* We have to also look at the VID header, possibly it is not
* corrupted. Set %bitflips flag in order to make this PEB be
* moved and EC be re-created.
*/
- ec_corr = 1;
+ ec_corr = err;
ec = UBI_SCAN_UNKNOWN_EC;
bitflips = 1;
}
- si->is_empty = 0;
-
if (!ec_corr) {
int image_seq;
@@ -813,9 +816,12 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
return err;
else if (err == UBI_IO_BITFLIPS)
bitflips = 1;
- else if (err == UBI_IO_BAD_VID_HDR ||
+ else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR ||
(err == UBI_IO_PEB_FREE && ec_corr)) {
/* VID header is corrupted */
+ if (err == UBI_IO_BAD_HDR_READ ||
+ ec_corr == UBI_IO_BAD_HDR_READ)
+ si->read_err_count += 1;
err = add_to_list(si, pnum, ec, &si->corr);
if (err)
return err;
@@ -836,11 +842,11 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
switch (vidh->compat) {
case UBI_COMPAT_DELETE:
ubi_msg("\"delete\" compatible internal volume %d:%d"
- " found, remove it", vol_id, lnum);
+ " found, will remove it", vol_id, lnum);
err = add_to_list(si, pnum, ec, &si->corr);
if (err)
return err;
- break;
+ return 0;
case UBI_COMPAT_RO:
ubi_msg("read-only compatible internal volume %d:%d"
@@ -855,7 +861,6 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
err = add_to_list(si, pnum, ec, &si->alien);
if (err)
return err;
- si->alien_peb_count += 1;
return 0;
case UBI_COMPAT_REJECT:
@@ -886,6 +891,85 @@ adjust_mean_ec:
}
/**
+ * check_what_we_have - check what PEB were found by scanning.
+ * @ubi: UBI device description object
+ * @si: scanning information
+ *
+ * This is a helper function which takes a look what PEBs were found by
+ * scanning, and decides whether the flash is empty and should be formatted and
+ * whether there are too many corrupted PEBs and we should not attach this
+ * MTD device. Returns zero if we should proceed with attaching the MTD device,
+ * and %-EINVAL if we should not.
+ */
+static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
+{
+ struct ubi_scan_leb *seb;
+ int max_corr;
+
+ max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
+ max_corr = max_corr / 20 ?: 8;
+
+ /*
+ * Few corrupted PEBs are not a problem and may be just a result of
+ * unclean reboots. However, many of them may indicate some problems
+ * with the flash HW or driver.
+ */
+ if (si->corr_peb_count >= 8) {
+ ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
+ printk(KERN_WARNING "corrupted PEBs are:");
+ list_for_each_entry(seb, &si->corr, u.list)
+ printk(KERN_CONT " %d", seb->pnum);
+ printk(KERN_CONT "\n");
+
+ /*
+ * If too many PEBs are corrupted, we refuse attaching,
+ * otherwise, only print a warning.
+ */
+ if (si->corr_peb_count >= max_corr) {
+ ubi_err("too many corrupted PEBs, refusing this device");
+ return -EINVAL;
+ }
+ }
+
+ if (si->free_peb_count + si->used_peb_count +
+ si->alien_peb_count == 0) {
+ /* No UBI-formatted eraseblocks were found */
+ if (si->corr_peb_count == si->read_err_count &&
+ si->corr_peb_count < 8) {
+ /* No or just few corrupted PEBs, and all of them had a
+ * read error. We assume that those are bad PEBs, which
+ * were just not marked as bad so far.
+ *
+ * This piece of code basically tries to distinguish
+ * between the following 2 situations:
+ *
+ * 1. Flash is empty, but there are few bad PEBs, which
+ * are not marked as bad so far, and which were read
+ * with error. We want to go ahead and format this
+ * flash. While formating, the faulty PEBs will
+ * probably be marked as bad.
+ *
+ * 2. Flash probably contains non-UBI data and we do
+ * not want to format it and destroy possibly needed
+ * data (e.g., consider the case when the bootloader
+ * MTD partition was accidentally fed to UBI).
+ */
+ si->is_empty = 1;
+ ubi_msg("empty MTD device detected");
+ get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq));
+ } else {
+ ubi_err("MTD device possibly contains non-UBI data, "
+ "refusing it");
+ return -EINVAL;
+ }
+ }
+
+ if (si->corr_peb_count > 0)
+ ubi_msg("corrupted PEBs will be formatted");
+ return 0;
+}
+
+/**
* ubi_scan - scan an MTD device.
* @ubi: UBI device description object
*
@@ -909,7 +993,6 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
INIT_LIST_HEAD(&si->erase);
INIT_LIST_HEAD(&si->alien);
si->volumes = RB_ROOT;
- si->is_empty = 1;
err = -ENOMEM;
ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
@@ -935,21 +1018,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
if (si->ec_count)
si->mean_ec = div_u64(si->ec_sum, si->ec_count);
- if (si->is_empty)
- ubi_msg("empty MTD device detected");
-
- /*
- * Few corrupted PEBs are not a problem and may be just a result of
- * unclean reboots. However, many of them may indicate some problems
- * with the flash HW or driver. Print a warning in this case.
- */
- if (si->corr_count >= 8 || si->corr_count >= ubi->peb_count / 4) {
- ubi_warn("%d PEBs are corrupted", si->corr_count);
- printk(KERN_WARNING "corrupted PEBs are:");
- list_for_each_entry(seb, &si->corr, u.list)
- printk(KERN_CONT " %d", seb->pnum);
- printk(KERN_CONT "\n");
- }
+ err = check_what_we_have(ubi, si);
+ if (err)
+ goto out_vidh;
/*
* In case of unknown erase counter we use the mean erase counter
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index ff179ad7ca55..2576a8d1532b 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -91,10 +91,16 @@ struct ubi_scan_volume {
* @erase: list of physical eraseblocks which have to be erased
* @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
* those belonging to "preserve"-compatible internal volumes)
+ * @used_peb_count: count of used PEBs
+ * @corr_peb_count: count of PEBs in the @corr list
+ * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was
+ * returned)
+ * @free_peb_count: count of PEBs in the @free list
+ * @erase_peb_count: count of PEBs in the @erase list
+ * @alien_peb_count: count of PEBs in the @alien list
* @bad_peb_count: count of bad physical eraseblocks
* @vols_found: number of volumes found during scanning
* @highest_vol_id: highest volume ID
- * @alien_peb_count: count of physical eraseblocks in the @alien list
* @is_empty: flag indicating whether the MTD device is empty or not
* @min_ec: lowest erase counter value
* @max_ec: highest erase counter value
@@ -102,7 +108,6 @@ struct ubi_scan_volume {
* @mean_ec: mean erase counter value
* @ec_sum: a temporary variable used when calculating @mean_ec
* @ec_count: a temporary variable used when calculating @mean_ec
- * @corr_count: count of corrupted PEBs
*
* This data structure contains the result of scanning and may be used by other
* UBI sub-systems to build final UBI data structures, further error-recovery
@@ -114,10 +119,15 @@ struct ubi_scan_info {
struct list_head free;
struct list_head erase;
struct list_head alien;
+ int used_peb_count;
+ int corr_peb_count;
+ int read_err_count;
+ int free_peb_count;
+ int erase_peb_count;
+ int alien_peb_count;
int bad_peb_count;
int vols_found;
int highest_vol_id;
- int alien_peb_count;
int is_empty;
int min_ec;
int max_ec;
@@ -125,7 +135,6 @@ struct ubi_scan_info {
int mean_ec;
uint64_t ec_sum;
int ec_count;
- int corr_count;
};
struct ubi_device;
@@ -135,7 +144,7 @@ struct ubi_vid_hdr;
* ubi_scan_move_to_list - move a PEB from the volume tree to a list.
*
* @sv: volume scanning information
- * @seb: scanning eraseblock infprmation
+ * @seb: scanning eraseblock information
* @list: the list to move to
*/
static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index a637f0283add..0359e0cce482 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -89,16 +89,16 @@
* %0xFF bytes
* UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
* valid erase counter header, and the rest are %0xFF bytes
- * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC)
- * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or
- * CRC)
+ * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
+ * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read
+ * error reported by the flash driver
* UBI_IO_BITFLIPS: bit-flips were detected and corrected
*/
enum {
UBI_IO_PEB_EMPTY = 1,
UBI_IO_PEB_FREE,
- UBI_IO_BAD_EC_HDR,
- UBI_IO_BAD_VID_HDR,
+ UBI_IO_BAD_HDR,
+ UBI_IO_BAD_HDR_READ,
UBI_IO_BITFLIPS
};
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2decc597bda7..ce2fcdd4ab90 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2754,6 +2754,7 @@ config MYRI10GE_DCA
config NETXEN_NIC
tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
depends on PCI
+ select FW_LOADER
help
This enables the support for NetXen's Gigabit Ethernet card.
@@ -2819,6 +2820,7 @@ config BNX2X
config QLCNIC
tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
depends on PCI
+ select FW_LOADER
help
This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
devices.
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 949d7a9dcf92..117432222a09 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -3073,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
struct l2_fhdr *rx_hdr;
int rx_pkt = 0, pg_ring_used = 0;
- struct pci_dev *pdev = bp->pdev;
hw_cons = bnx2_get_hw_rx_cons(bnapi);
sw_cons = rxr->rx_cons;
@@ -3099,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
skb = rx_buf->skb;
prefetchw(skb);
- if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) {
- next_rx_buf =
- &rxr->rx_buf_ring[
- RX_RING_IDX(NEXT_RX_BD(sw_cons))];
- prefetch(next_rx_buf->desc);
- }
+ next_rx_buf =
+ &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+ prefetch(next_rx_buf->desc);
+
rx_buf->skb = NULL;
dma_addr = dma_unmap_addr(rx_buf, mapping);
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index 8bd23687c530..bb0872a63315 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -1062,6 +1062,10 @@ struct bnx2x {
/* used to synchronize stats collecting */
int stats_state;
+
+ /* used for synchronization of concurrent threads statistics handling */
+ spinlock_t stats_lock;
+
/* used by dmae command loader */
struct dmae_command stats_dmae;
int executer_idx;
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 57ff5b3bcce6..46167c081727 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -57,8 +57,8 @@
#include "bnx2x_init_ops.h"
#include "bnx2x_dump.h"
-#define DRV_MODULE_VERSION "1.52.53-1"
-#define DRV_MODULE_RELDATE "2010/18/04"
+#define DRV_MODULE_VERSION "1.52.53-2"
+#define DRV_MODULE_RELDATE "2010/21/07"
#define BNX2X_BC_VER 0x040200
#include <linux/firmware.h>
@@ -3789,6 +3789,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
struct eth_query_ramrod_data ramrod_data = {0};
int i, rc;
+ spin_lock_bh(&bp->stats_lock);
+
ramrod_data.drv_counter = bp->stats_counter++;
ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
for_each_queue(bp, i)
@@ -3802,6 +3804,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
bp->spq_left++;
bp->stats_pending = 1;
}
+
+ spin_unlock_bh(&bp->stats_lock);
}
}
@@ -4367,6 +4371,14 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
struct bnx2x_eth_stats *estats = &bp->eth_stats;
int i;
+ u16 cur_stats_counter;
+
+ /* Make sure we use the value of the counter
+ * used for sending the last stats ramrod.
+ */
+ spin_lock_bh(&bp->stats_lock);
+ cur_stats_counter = bp->stats_counter - 1;
+ spin_unlock_bh(&bp->stats_lock);
memcpy(&(fstats->total_bytes_received_hi),
&(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
@@ -4394,25 +4406,22 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
u32 diff;
/* are storm stats valid? */
- if ((u16)(le16_to_cpu(xclient->stats_counter) + 1) !=
- bp->stats_counter) {
+ if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {
DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
" xstorm counter (0x%x) != stats_counter (0x%x)\n",
- i, xclient->stats_counter, bp->stats_counter);
+ i, xclient->stats_counter, cur_stats_counter + 1);
return -1;
}
- if ((u16)(le16_to_cpu(tclient->stats_counter) + 1) !=
- bp->stats_counter) {
+ if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {
DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
" tstorm counter (0x%x) != stats_counter (0x%x)\n",
- i, tclient->stats_counter, bp->stats_counter);
+ i, tclient->stats_counter, cur_stats_counter + 1);
return -2;
}
- if ((u16)(le16_to_cpu(uclient->stats_counter) + 1) !=
- bp->stats_counter) {
+ if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {
DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
" ustorm counter (0x%x) != stats_counter (0x%x)\n",
- i, uclient->stats_counter, bp->stats_counter);
+ i, uclient->stats_counter, cur_stats_counter + 1);
return -4;
}
@@ -4849,16 +4858,18 @@ static const struct {
static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
{
- enum bnx2x_stats_state state = bp->stats_state;
+ enum bnx2x_stats_state state;
if (unlikely(bp->panic))
return;
- bnx2x_stats_stm[state][event].action(bp);
+ /* Protect a state change flow */
+ spin_lock_bh(&bp->stats_lock);
+ state = bp->stats_state;
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
+ spin_unlock_bh(&bp->stats_lock);
- /* Make sure the state has been "changed" */
- smp_wmb();
+ bnx2x_stats_stm[state][event].action(bp);
if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
@@ -9908,6 +9919,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
mutex_init(&bp->fw_mb_mutex);
+ spin_lock_init(&bp->stats_lock);
#ifdef BCM_CNIC
mutex_init(&bp->cnic_mutex);
#endif
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 40fdc41446cc..8d7dfd2f1e90 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -340,7 +340,8 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
if ((client_info->assigned) &&
(client_info->ip_src == arp->ip_dst) &&
- (client_info->ip_dst == arp->ip_src)) {
+ (client_info->ip_dst == arp->ip_src) &&
+ (compare_ether_addr_64bits(client_info->mac_dst, arp->mac_src))) {
/* update the clients MAC address */
memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
client_info->ntt = 1;
@@ -821,7 +822,7 @@ static int rlb_initialize(struct bonding *bond)
/*initialize packet type*/
pk_type->type = cpu_to_be16(ETH_P_ARP);
- pk_type->dev = NULL;
+ pk_type->dev = bond->dev;
pk_type->func = rlb_arp_recv;
/* register to receive ARPs */
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5e12462a9d5e..c3d98dde2f86 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -168,7 +168,7 @@ static int arp_ip_count;
static int bond_mode = BOND_MODE_ROUNDROBIN;
static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
static int lacp_fast;
-
+static int disable_netpoll = 1;
const struct bond_parm_tbl bond_lacp_tbl[] = {
{ "slow", AD_LACP_SLOW},
@@ -1742,15 +1742,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_set_carrier(bond);
#ifdef CONFIG_NET_POLL_CONTROLLER
- if (slaves_support_netpoll(bond_dev)) {
- bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
- if (bond_dev->npinfo)
- slave_dev->npinfo = bond_dev->npinfo;
- } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+ /*
+ * Netpoll and bonding is broken, make sure it is not initialized
+ * until it is fixed.
+ */
+ if (disable_netpoll) {
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
- pr_info("New slave device %s does not support netpoll\n",
- slave_dev->name);
- pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+ } else {
+ if (slaves_support_netpoll(bond_dev)) {
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (bond_dev->npinfo)
+ slave_dev->npinfo = bond_dev->npinfo;
+ } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+ bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
+ pr_info("New slave device %s does not support netpoll\n",
+ slave_dev->name);
+ pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+ }
}
#endif
read_unlock(&bond->lock);
@@ -1950,8 +1958,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
read_lock_bh(&bond->lock);
- if (slaves_support_netpoll(bond_dev))
- bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+
+ /* Make sure netpoll over stays disabled until fixed. */
+ if (!disable_netpoll)
+ if (slaves_support_netpoll(bond_dev))
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
read_unlock_bh(&bond->lock);
if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index fe925663d39a..80471269977a 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
- context->xstorm_st_context.statistics_data = (cli |
- XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+ if (cli < MAX_X_STAT_COUNTER_ID)
+ context->xstorm_st_context.statistics_data = cli |
+ XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
context->xstorm_ag_context.cdu_reserved =
CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
@@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
ETH_CONNECTION_TYPE);
/* reset xstorm per client statistics */
- val = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_X_STAT_COUNTER_ID) {
+ val = BAR_XSTRORM_INTMEM +
+ XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
cp->tx_cons_ptr =
&cp->bnx2x_def_status_blk->c_def_status_block.index_values[
@@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
BNX2X_ISCSI_RX_SB_INDEX_NUM;
context->ustorm_st_context.common.clientId = cli;
context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
- context->ustorm_st_context.common.flags =
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
- context->ustorm_st_context.common.statistics_counter_id = cli;
+ if (cli < MAX_U_STAT_COUNTER_ID) {
+ context->ustorm_st_context.common.flags =
+ USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
+ context->ustorm_st_context.common.statistics_counter_id = cli;
+ }
context->ustorm_st_context.common.mc_alignment_log_size = 0;
context->ustorm_st_context.common.bd_buff_size =
cp->l2_single_buf_size;
@@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
/* client tstorm info */
tstorm_client.mtu = cp->l2_single_buf_size - 14;
- tstorm_client.config_flags =
- (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE |
- TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE);
- tstorm_client.statistics_counter_id = cli;
+ tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+
+ if (cli < MAX_T_STAT_COUNTER_ID) {
+ tstorm_client.config_flags |=
+ TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+ tstorm_client.statistics_counter_id = cli;
+ }
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
@@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
((u32 *)&tstorm_client)[1]);
/* reset tstorm per client statistics */
- val = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_T_STAT_COUNTER_ID) {
+
+ val = BAR_TSTRORM_INTMEM +
+ TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
/* reset ustorm per client statistics */
- val = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_U_STAT_COUNTER_ID) {
+ val = BAR_USTRORM_INTMEM +
+ USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
cp->rx_cons_ptr =
&cp->bnx2x_def_status_blk->u_def_status_block.index_values[
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 3c58db595285..23786ee34bed 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Could not attach to PHY\n",
dev->name);
- return PTR_ERR(priv->phy);
+ rc = PTR_ERR(priv->phy);
+ goto fail;
}
if ((rc = register_netdev(dev))) {
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 1d973db27c32..d7de376d7178 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -1022,7 +1022,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __init dec_lance_probe(struct device *bdev, const int type)
+static int __devinit dec_lance_probe(struct device *bdev, const int type)
{
static unsigned version_printed;
static const char fmt[] = "declance%d";
@@ -1326,7 +1326,7 @@ static void __exit dec_lance_platform_remove(void)
}
#ifdef CONFIG_TC
-static int __init dec_lance_tc_probe(struct device *dev);
+static int __devinit dec_lance_tc_probe(struct device *dev);
static int __exit dec_lance_tc_remove(struct device *dev);
static const struct tc_device_id dec_lance_tc_table[] = {
@@ -1345,7 +1345,7 @@ static struct tc_driver dec_lance_tc_driver = {
},
};
-static int __init dec_lance_tc_probe(struct device *dev)
+static int __devinit dec_lance_tc_probe(struct device *dev)
{
int status = dec_lance_probe(dev, PMAD_LANCE);
if (!status)
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index ebdea0891665..68a80893dce1 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
goto err_register;
/* print bus type/speed/width info */
- e_info("(PCI%s:%s:%s) ",
- ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
- ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
- (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
- (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
- (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
- ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
-
- e_info("%pM\n", netdev->dev_addr);
+ e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+ ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
+ (hw->bus_speed == e1000_bus_speed_120) ? 120 :
+ (hw->bus_speed == e1000_bus_speed_100) ? 100 :
+ (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
+ ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
+ netdev->dev_addr);
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 0630980a2722..0060e422f171 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0103"
+#define DRV_VERSION "EHEA_0105"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index f547894ff48f..8b92acb448c2 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
ehea_reset_cq_ep(pr->send_cq);
ehea_reset_cq_n1(pr->recv_cq);
ehea_reset_cq_n1(pr->send_cq);
+ rmb();
cqe = ehea_poll_rq1(pr->qp, &wqe_index);
cqe_skb = ehea_poll_cq(pr->send_cq);
@@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work)
container_of(work, struct ehea_port, reset_task);
struct net_device *dev = port->netdev;
+ mutex_lock(&dlpar_mem_lock);
port->resets++;
mutex_lock(&port->port_lock);
netif_stop_queue(dev);
@@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work)
netif_wake_queue(dev);
out:
mutex_unlock(&port->port_lock);
+ mutex_unlock(&dlpar_mem_lock);
}
static void ehea_rereg_mrs(struct work_struct *work)
@@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
int ret = NOTIFY_BAD;
struct memory_notify *arg = data;
- if (!mutex_trylock(&dlpar_mem_lock)) {
- ehea_info("ehea_mem_notifier must not be called parallelized");
- goto out;
- }
+ mutex_lock(&dlpar_mem_lock);
switch (action) {
case MEM_CANCEL_OFFLINE:
@@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb,
out_unlock:
mutex_unlock(&dlpar_mem_lock);
-out:
return ret;
}
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 2b3e16db5c82..e0d33281ec98 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
{
u64 a0, a1 = len;
int wait = 1000;
- u64 prov_pa;
+ dma_addr_t prov_pa;
void *prov_buf;
int ret;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index ba190376e030..efd4c70753db 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev)
/* Insert receive time stamps into padding alignment bytes */
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
rctrl &= ~RCTRL_PAL_MASK;
- rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8);
+ rctrl |= RCTRL_PADDING(8);
priv->padding = 8;
}
+ /* Enable HW time stamping if requested from user space */
+ if (priv->hwts_rx_en)
+ rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+
/* keep vlan related bits if it's enabled */
if (priv->vlgrp) {
rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
@@ -747,7 +751,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
FSL_GIANFAR_DEV_HAS_CSUM |
FSL_GIANFAR_DEV_HAS_VLAN |
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
- FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
+ FSL_GIANFAR_DEV_HAS_TIMER;
ctype = of_get_property(np, "phy-connection-type", NULL);
@@ -805,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
- priv->hwts_rx_en = 0;
+ if (priv->hwts_rx_en) {
+ stop_gfar(netdev);
+ priv->hwts_rx_en = 0;
+ startup_gfar(netdev);
+ }
break;
default:
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
return -ERANGE;
- priv->hwts_rx_en = 1;
+ if (!priv->hwts_rx_en) {
+ stop_gfar(netdev);
+ priv->hwts_rx_en = 1;
+ startup_gfar(netdev);
+ }
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
}
@@ -2642,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
priv->rx_buffer_size, DMA_FROM_DEVICE);
+ if (unlikely(!(bdp->status & RXBD_ERR) &&
+ bdp->length > priv->rx_buffer_size))
+ bdp->status = RXBD_LARGE;
+
/* We drop the frame if we failed to allocate a new buffer */
if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
bdp->status & RXBD_ERR)) {
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 7acb3edc47ef..2602852cc55a 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -677,7 +677,7 @@ static int ibmveth_close(struct net_device *netdev)
if (!adapter->pool_config)
netif_stop_queue(netdev);
- free_irq(netdev->irq, netdev);
+ h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
do {
lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
@@ -689,6 +689,8 @@ static int ibmveth_close(struct net_device *netdev)
lpar_rc);
}
+ free_irq(netdev->irq, netdev);
+
adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
ibmveth_cleanup(adapter);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 3881918f5382..cea37e0837ff 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1722,6 +1722,15 @@ static int __devinit igb_probe(struct pci_dev *pdev,
u16 eeprom_apme_mask = IGB_EEPROM_APME;
u32 part_num;
+ /* Catch broken hardware that put the wrong VF device ID in
+ * the PCIe SR-IOV capability.
+ */
+ if (pdev->is_virtfn) {
+ WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
+ pci_name(pdev), pdev->vendor, pdev->device);
+ return -EINVAL;
+ }
+
err = pci_enable_device_mem(pdev);
if (err)
return err;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index c50a7541ffec..3a93a81872b8 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
return 0;
}
-/*
- * this function must be called before setting the new value of
- * rx_itr_setting
- */
-static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
- struct ethtool_coalesce *ec)
-{
- /* check the old value and enable RSC if necessary */
- if ((adapter->rx_itr_setting == 0) &&
- (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
- adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
- adapter->netdev->features |= NETIF_F_LRO;
- DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
- ec->rx_coalesce_usecs);
- return true;
- }
- return false;
-}
-
static int ixgbe_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
@@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
(1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
return -EINVAL;
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_reenable_rsc(adapter, ec);
-
/* store the value in ints/second */
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
/* clear the lower bit as its used for dynamic state */
adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_reenable_rsc(adapter, ec);
-
/* 1 means dynamic mode */
adapter->rx_eitr_param = 20000;
adapter->rx_itr_setting = 1;
@@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
*/
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
- netdev->features &= ~NETIF_F_LRO;
- DPRINTK(PROBE, INFO,
- "rx-usecs set to 0, disabling RSC\n");
-
+ if (netdev->features & NETIF_F_LRO) {
+ netdev->features &= ~NETIF_F_LRO;
+ DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+ "disabling LRO/RSC\n");
+ }
need_reset = true;
}
}
@@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
}
} else if (!adapter->rx_itr_setting) {
netdev->features &= ~ETH_FLAG_LRO;
+ if (data & ETH_FLAG_LRO)
+ DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+ "LRO/RSC cannot be enabled.\n");
}
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index b2af2f67f604..74d9b6df3029 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3684,10 +3684,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
- /* power down the optics */
- if (hw->phy.multispeed_fiber)
- hw->mac.ops.disable_tx_laser(hw);
-
/* disable receive for all VFs and wait one second */
if (adapter->num_vfs) {
/* ping all the active vfs to let them know we are going down */
@@ -3742,6 +3738,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
~IXGBE_DMATXCTL_TE));
+ /* power down the optics */
+ if (hw->phy.multispeed_fiber)
+ hw->mac.ops.disable_tx_laser(hw);
+
/* clear n-tuple filters that are cached */
ethtool_ntuple_flush(netdev);
@@ -4001,7 +4001,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
done:
/* Notify the stack of the (possibly) reduced Tx Queue count. */
- adapter->netdev->real_num_tx_queues = adapter->num_tx_queues;
+ netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
}
static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
@@ -5195,7 +5195,6 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
}
- ixgbe_clear_interrupt_scheme(adapter);
#ifdef CONFIG_PM
retval = pci_save_state(pdev);
@@ -5230,6 +5229,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
*enable_wake = !!wufc;
+ ixgbe_clear_interrupt_scheme(adapter);
+
ixgbe_release_hw_control(adapter);
pci_disable_device(pdev);
@@ -5282,6 +5283,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
u64 non_eop_descs = 0, restart_queue = 0;
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
+ return;
+
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
u64 rsc_count = 0;
u64 rsc_flush = 0;
@@ -6019,7 +6024,6 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
int queue, u32 tx_flags)
{
- /* Right now, we support IPv4 only */
struct ixgbe_atr_input atr_input;
struct tcphdr *th;
struct iphdr *iph = ip_hdr(skb);
@@ -6028,6 +6032,9 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
u32 src_ipv4_addr, dst_ipv4_addr;
u8 l4type = 0;
+ /* Right now, we support IPv4 only */
+ if (skb->protocol != htons(ETH_P_IP))
+ return;
/* check if we're UDP or TCP */
if (iph->protocol == IPPROTO_TCP) {
th = tcp_hdr(skb);
@@ -6485,6 +6492,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
#endif
u32 part_num, eec;
+ /* Catch broken hardware that put the wrong VF device ID in
+ * the PCIe SR-IOV capability.
+ */
+ if (pdev->is_virtfn) {
+ WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
+ pci_name(pdev), pdev->vendor, pdev->device);
+ return -EINVAL;
+ }
+
err = pci_enable_device_mem(pdev);
if (err)
return err;
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 09e1911ff510..48325a5beff2 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
* 4 SFP_DA_CORE1 - 82599-specific
* 5 SFP_SR/LR_CORE0 - 82599-specific
* 6 SFP_SR/LR_CORE1 - 82599-specific
+ * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
+ * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
*/
if (hw->mac.type == ixgbe_mac_82598EB) {
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index ce5d6e909218..c27f4291b350 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev)
DEB(DEB_MULTI,
printk(KERN_DEBUG
"%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
- dev->name, dev->mc_count,
+ dev->name, netdev_mc_count(dev),
dev->flags & IFF_PROMISC ? "ON" : "OFF",
dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 315eb4cdb58e..dc6bf042579d 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -964,7 +964,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);
if (!np) {
dev_err(&op->dev, "could not find DMA node\n");
- goto nodev;
+ goto err_iounmap;
}
/* Setup the DMA register accesses, could be DCR or memory mapped */
@@ -978,7 +978,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
} else {
dev_err(&op->dev, "unable to map DMA registers\n");
- goto nodev;
+ goto err_iounmap;
}
}
@@ -987,7 +987,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
dev_err(&op->dev, "could not determine irqs\n");
rc = -ENOMEM;
- goto nodev;
+ goto err_iounmap_2;
}
of_node_put(np); /* Finished with the DMA node; drop the reference */
@@ -997,7 +997,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
if ((!addr) || (size != 6)) {
dev_err(&op->dev, "could not find MAC address\n");
rc = -ENODEV;
- goto nodev;
+ goto err_iounmap_2;
}
temac_set_mac_address(ndev, (void *)addr);
@@ -1013,7 +1013,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group);
if (rc) {
dev_err(lp->dev, "Error creating sysfs files\n");
- goto nodev;
+ goto err_iounmap_2;
}
rc = register_netdev(lp->ndev);
@@ -1026,6 +1026,11 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
err_register_ndev:
sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
+ err_iounmap_2:
+ if (lp->sdma_regs)
+ iounmap(lp->sdma_regs);
+ err_iounmap:
+ iounmap(lp->regs);
nodev:
free_netdev(ndev);
ndev = NULL;
@@ -1044,6 +1049,9 @@ static int __devexit temac_of_remove(struct of_device *op)
of_node_put(lp->phy_node);
lp->phy_node = NULL;
dev_set_drvdata(&op->dev, NULL);
+ iounmap(lp->regs);
+ if (lp->sdma_regs)
+ iounmap(lp->sdma_regs);
free_netdev(ndev);
return 0;
}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 87e8d4cb4057..f15fe2cf72ae 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -499,7 +499,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static void macvlan_setup(struct net_device *dev)
+void macvlan_common_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -508,6 +508,12 @@ static void macvlan_setup(struct net_device *dev)
dev->destructor = free_netdev;
dev->header_ops = &macvlan_hard_header_ops,
dev->ethtool_ops = &macvlan_ethtool_ops;
+}
+EXPORT_SYMBOL_GPL(macvlan_common_setup);
+
+static void macvlan_setup(struct net_device *dev)
+{
+ macvlan_common_setup(dev);
dev->tx_queue_len = 0;
}
@@ -705,7 +711,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
/* common fields */
ops->priv_size = sizeof(struct macvlan_dev);
ops->get_tx_queues = macvlan_get_tx_queues;
- ops->setup = macvlan_setup;
ops->validate = macvlan_validate;
ops->maxtype = IFLA_MACVLAN_MAX;
ops->policy = macvlan_policy;
@@ -719,6 +724,7 @@ EXPORT_SYMBOL_GPL(macvlan_link_register);
static struct rtnl_link_ops macvlan_link_ops = {
.kind = "macvlan",
+ .setup = macvlan_setup,
.newlink = macvlan_newlink,
.dellink = macvlan_dellink,
};
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index a8a94e2f6ddc..ff02b836c3c4 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -180,11 +180,18 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
{
struct macvtap_queue *q = macvtap_get_queue(dev, skb);
if (!q)
- return -ENOLINK;
+ goto drop;
+
+ if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len)
+ goto drop;
skb_queue_tail(&q->sk.sk_receive_queue, skb);
wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
- return 0;
+ return NET_RX_SUCCESS;
+
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
}
/*
@@ -235,8 +242,15 @@ static void macvtap_dellink(struct net_device *dev,
macvlan_dellink(dev, head);
}
+static void macvtap_setup(struct net_device *dev)
+{
+ macvlan_common_setup(dev);
+ dev->tx_queue_len = TUN_READQ_SIZE;
+}
+
static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
.kind = "macvtap",
+ .setup = macvtap_setup,
.newlink = macvtap_newlink,
.dellink = macvtap_dellink,
};
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 8e9704f5c122..869f0ea43a5b 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __init mipsnet_probe(struct platform_device *dev)
+static int __devinit mipsnet_probe(struct platform_device *dev)
{
struct net_device *netdev;
int err;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index e345ec8cb473..73bb8ea6f54a 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -289,6 +289,7 @@ struct mv643xx_eth_shared_private {
unsigned int t_clk;
int extended_rx_coal_limit;
int tx_bw_control;
+ int tx_csum_limit;
};
#define TX_BW_CONTROL_ABSENT 0
@@ -776,13 +777,16 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
l4i_chk = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ int hdr_len;
int tag_bytes;
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_8021Q));
- tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN;
- if (unlikely(tag_bytes & ~12)) {
+ hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
+ tag_bytes = hdr_len - ETH_HLEN;
+ if (skb->len - hdr_len > mp->shared->tx_csum_limit ||
+ unlikely(tag_bytes & ~12)) {
if (skb_checksum_help(skb) == 0)
goto no_csum;
kfree_skb(skb);
@@ -2666,6 +2670,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
* Detect hardware parameters.
*/
msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000;
+ msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024;
infer_hw_params(msp);
platform_set_drvdata(pdev, msp);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index b8e2923a1d69..1063093b3afc 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -806,8 +806,10 @@ static int __init ne_drv_probe(struct platform_device *pdev)
dev->base_addr = res->start;
dev->irq = platform_get_irq(pdev, 0);
} else {
- if (this_dev < 0 || this_dev >= MAX_NE_CARDS)
+ if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
+ free_netdev(dev);
return -EINVAL;
+ }
dev->base_addr = io[this_dev];
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f26e54716c88..3a41b6a84a68 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
if (addr == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
netdev->name);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out_free;
}
tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 5c496f8d7c49..29d7b93d0493 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
window = CRB_HI(off);
- if (adapter->ahw.crb_win == window)
- return;
-
writel(window, addr);
if (readl(addr) != window) {
if (printk_ratelimit())
@@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
"failed to set CRB window to %d off 0x%lx\n",
window, off);
}
- adapter->ahw.crb_win = window;
}
static void __iomem *
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 045a7c8f5bdf..c865dda2adf1 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
if (cmd_buf_arr == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
netdev->name);
- return -ENOMEM;
+ goto err_out;
}
memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
tx_ring->cmd_buf_arr = cmd_buf_arr;
@@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
if (rds_ring == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
netdev->name);
- return -ENOMEM;
+ goto err_out;
}
recv_ctx->rds_rings = rds_ring;
@@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
netxen_ctx_msg msg = 0;
struct list_head *head;
+ spin_lock(&rds_ring->lock);
+
producer = rds_ring->producer;
- spin_lock(&rds_ring->lock);
head = &rds_ring->free_list;
while (!list_empty(head)) {
@@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
producer = get_next_index(producer, rds_ring->num_desc);
}
- spin_unlock(&rds_ring->lock);
if (count) {
rds_ring->producer = producer;
@@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
NETXEN_RCV_PRODUCER_OFFSET), msg);
}
}
+
+ spin_unlock(&rds_ring->lock);
}
static void
@@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
int producer, count = 0;
struct list_head *head;
- producer = rds_ring->producer;
if (!spin_trylock(&rds_ring->lock))
return;
+ producer = rds_ring->producer;
+
head = &rds_ring->free_list;
while (!list_empty(head)) {
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 5b3dfb4ab279..33525bf2a3d3 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -1168,6 +1168,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
int interrupts, nr_serviced = 0, i;
struct ei_device *ei_local;
int handled = 0;
+ unsigned long flags;
e8390_base = dev->base_addr;
ei_local = netdev_priv(dev);
@@ -1176,7 +1177,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
* Protect the irq test too.
*/
- spin_lock(&ei_local->page_lock);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
if (ei_local->irqlock)
{
@@ -1188,7 +1189,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
dev->name, inb_p(e8390_base + EN0_ISR),
inb_p(e8390_base + EN0_IMR));
#endif
- spin_unlock(&ei_local->page_lock);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
return IRQ_NONE;
}
@@ -1261,7 +1262,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
- spin_unlock(&ei_local->page_lock);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
return IRQ_RETVAL(handled);
}
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 6f77a768ba88..bfdef72c5d5e 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 64e6a84bbbbe..307cd1721e91 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1505,12 +1505,20 @@ irq_done:
writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
writeb(cor, smc->base + MOT_LAN + CISREG_COR);
}
-#ifdef DOES_NOT_WORK
- if (smc->base != NULL) { /* Megahertz MFC's */
- readb(smc->base+MEGAHERTZ_ISR);
- readb(smc->base+MEGAHERTZ_ISR);
+
+ if ((smc->base != NULL) && /* Megahertz MFC's */
+ (smc->manfid == MANFID_MEGAHERTZ) &&
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288)) {
+
+ u_char tmp;
+ tmp = readb(smc->base+MEGAHERTZ_ISR);
+ tmp = readb(smc->base+MEGAHERTZ_ISR);
+
+ /* Retrigger interrupt if needed */
+ writeb(tmp, smc->base + MEGAHERTZ_ISR);
+ writeb(tmp, smc->base + MEGAHERTZ_ISR);
}
-#endif
+
spin_unlock(&smc->lock);
return IRQ_RETVAL(handled);
}
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index dbd003453737..29c39ff85de5 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -226,6 +226,7 @@ module_exit(lxt_exit);
static struct mdio_device_id lxt_tbl[] = {
{ 0x78100000, 0xfffffff0 },
{ 0x001378e0, 0xfffffff0 },
+ { 0x00137a10, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 78b74e83ce5d..5a1bd5db2a93 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -29,6 +29,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/marvell_phy.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -48,8 +49,6 @@
#define MII_M1145_RGMII_RX_DELAY 0x0080
#define MII_M1145_RGMII_TX_DELAY 0x0002
-#define M1145_DEV_FLAGS_RESISTANCE 0x00000001
-
#define MII_M1111_PHY_LED_CONTROL 0x18
#define MII_M1111_PHY_LED_DIRECT 0x4100
#define MII_M1111_PHY_LED_COMBINE 0x411c
@@ -350,7 +349,10 @@ static int m88e1118_config_init(struct phy_device *phydev)
return err;
/* Adjust LED Control */
- err = phy_write(phydev, 0x10, 0x021e);
+ if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
+ err = phy_write(phydev, 0x10, 0x1100);
+ else
+ err = phy_write(phydev, 0x10, 0x021e);
if (err < 0)
return err;
@@ -398,7 +400,7 @@ static int m88e1145_config_init(struct phy_device *phydev)
if (err < 0)
return err;
- if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) {
+ if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {
err = phy_write(phydev, 0x1d, 0x0012);
if (err < 0)
return err;
@@ -529,8 +531,8 @@ static int m88e1121_did_interrupt(struct phy_device *phydev)
static struct phy_driver marvell_drivers[] = {
{
- .phy_id = 0x01410c60,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1101,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1101",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
@@ -541,8 +543,8 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
- .phy_id = 0x01410c90,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1112,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1112",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
@@ -554,8 +556,8 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
- .phy_id = 0x01410cc0,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1111,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1111",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
@@ -567,8 +569,8 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
- .phy_id = 0x01410e10,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1118,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1118",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
@@ -580,8 +582,8 @@ static struct phy_driver marvell_drivers[] = {
.driver = {.owner = THIS_MODULE,},
},
{
- .phy_id = 0x01410cb0,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1121R,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1121R",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
@@ -593,8 +595,8 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
- .phy_id = 0x01410cd0,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1145,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1145",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
@@ -606,8 +608,8 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
- .phy_id = 0x01410e30,
- .phy_id_mask = 0xfffffff0,
+ .phy_id = MARVELL_PHY_ID_88E1240,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1240",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index fa4b24c49f42..d10bcefc0e45 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -4611,8 +4611,7 @@ static void ql_timer(unsigned long data)
return;
}
- qdev->timer.expires = jiffies + (5*HZ);
- add_timer(&qdev->timer);
+ mod_timer(&qdev->timer, jiffies + (5*HZ));
}
static int __devinit qlge_probe(struct pci_dev *pdev,
@@ -4713,6 +4712,8 @@ static void ql_eeh_close(struct net_device *ndev)
netif_stop_queue(ndev);
}
+ /* Disabling the timer */
+ del_timer_sync(&qdev->timer);
if (test_bit(QL_ADAPTER_UP, &qdev->flags))
cancel_delayed_work_sync(&qdev->asic_reset_work);
cancel_delayed_work_sync(&qdev->mpi_reset_work);
@@ -4808,8 +4809,7 @@ static void qlge_io_resume(struct pci_dev *pdev)
netif_err(qdev, ifup, qdev->ndev,
"Device was not running prior to EEH.\n");
}
- qdev->timer.expires = jiffies + (5*HZ);
- add_timer(&qdev->timer);
+ mod_timer(&qdev->timer, jiffies + (5*HZ));
netif_device_attach(ndev);
}
@@ -4871,8 +4871,7 @@ static int qlge_resume(struct pci_dev *pdev)
return err;
}
- qdev->timer.expires = jiffies + (5*HZ);
- add_timer(&qdev->timer);
+ mod_timer(&qdev->timer, jiffies + (5*HZ));
netif_device_attach(ndev);
return 0;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 96b6cfbf0a3a..cdc6a5c2e70d 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1316,7 +1316,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
{ 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
/* 8168C family. */
- { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 },
+ { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
{ 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
{ 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
{ 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 668327ccd8d0..1d37f0c310ca 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3130,7 +3130,6 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
pkt_cnt++;
/* Updating the statistics block */
- nic->dev->stats.tx_bytes += skb->len;
swstats->mem_freed += skb->truesize;
dev_kfree_skb_irq(skb);
@@ -4901,48 +4900,81 @@ static void s2io_updt_stats(struct s2io_nic *sp)
* Return value:
* pointer to the updated net_device_stats structure.
*/
-
static struct net_device_stats *s2io_get_stats(struct net_device *dev)
{
struct s2io_nic *sp = netdev_priv(dev);
- struct config_param *config = &sp->config;
struct mac_info *mac_control = &sp->mac_control;
struct stat_block *stats = mac_control->stats_info;
- int i;
+ u64 delta;
/* Configure Stats for immediate updt */
s2io_updt_stats(sp);
- /* Using sp->stats as a staging area, because reset (due to mtu
- change, for example) will clear some hardware counters */
- dev->stats.tx_packets += le32_to_cpu(stats->tmac_frms) -
- sp->stats.tx_packets;
- sp->stats.tx_packets = le32_to_cpu(stats->tmac_frms);
-
- dev->stats.tx_errors += le32_to_cpu(stats->tmac_any_err_frms) -
- sp->stats.tx_errors;
- sp->stats.tx_errors = le32_to_cpu(stats->tmac_any_err_frms);
-
- dev->stats.rx_errors += le64_to_cpu(stats->rmac_drop_frms) -
- sp->stats.rx_errors;
- sp->stats.rx_errors = le64_to_cpu(stats->rmac_drop_frms);
-
- dev->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms) -
- sp->stats.multicast;
- sp->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms);
-
- dev->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms) -
- sp->stats.rx_length_errors;
- sp->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms);
+ /* A device reset will cause the on-adapter statistics to be zero'ed.
+ * This can be done while running by changing the MTU. To prevent the
+ * system from having the stats zero'ed, the driver keeps a copy of the
+ * last update to the system (which is also zero'ed on reset). This
+ * enables the driver to accurately know the delta between the last
+ * update and the current update.
+ */
+ delta = ((u64) le32_to_cpu(stats->rmac_vld_frms_oflow) << 32 |
+ le32_to_cpu(stats->rmac_vld_frms)) - sp->stats.rx_packets;
+ sp->stats.rx_packets += delta;
+ dev->stats.rx_packets += delta;
+
+ delta = ((u64) le32_to_cpu(stats->tmac_frms_oflow) << 32 |
+ le32_to_cpu(stats->tmac_frms)) - sp->stats.tx_packets;
+ sp->stats.tx_packets += delta;
+ dev->stats.tx_packets += delta;
+
+ delta = ((u64) le32_to_cpu(stats->rmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stats->rmac_data_octets)) - sp->stats.rx_bytes;
+ sp->stats.rx_bytes += delta;
+ dev->stats.rx_bytes += delta;
+
+ delta = ((u64) le32_to_cpu(stats->tmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stats->tmac_data_octets)) - sp->stats.tx_bytes;
+ sp->stats.tx_bytes += delta;
+ dev->stats.tx_bytes += delta;
+
+ delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_errors;
+ sp->stats.rx_errors += delta;
+ dev->stats.rx_errors += delta;
+
+ delta = ((u64) le32_to_cpu(stats->tmac_any_err_frms_oflow) << 32 |
+ le32_to_cpu(stats->tmac_any_err_frms)) - sp->stats.tx_errors;
+ sp->stats.tx_errors += delta;
+ dev->stats.tx_errors += delta;
+
+ delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_dropped;
+ sp->stats.rx_dropped += delta;
+ dev->stats.rx_dropped += delta;
+
+ delta = le64_to_cpu(stats->tmac_drop_frms) - sp->stats.tx_dropped;
+ sp->stats.tx_dropped += delta;
+ dev->stats.tx_dropped += delta;
+
+ /* The adapter MAC interprets pause frames as multicast packets, but
+ * does not pass them up. This erroneously increases the multicast
+ * packet count and needs to be deducted when the multicast frame count
+ * is queried.
+ */
+ delta = (u64) le32_to_cpu(stats->rmac_vld_mcst_frms_oflow) << 32 |
+ le32_to_cpu(stats->rmac_vld_mcst_frms);
+ delta -= le64_to_cpu(stats->rmac_pause_ctrl_frms);
+ delta -= sp->stats.multicast;
+ sp->stats.multicast += delta;
+ dev->stats.multicast += delta;
- /* collect per-ring rx_packets and rx_bytes */
- dev->stats.rx_packets = dev->stats.rx_bytes = 0;
- for (i = 0; i < config->rx_ring_num; i++) {
- struct ring_info *ring = &mac_control->rings[i];
+ delta = ((u64) le32_to_cpu(stats->rmac_usized_frms_oflow) << 32 |
+ le32_to_cpu(stats->rmac_usized_frms)) +
+ le64_to_cpu(stats->rmac_long_frms) - sp->stats.rx_length_errors;
+ sp->stats.rx_length_errors += delta;
+ dev->stats.rx_length_errors += delta;
- dev->stats.rx_packets += ring->rx_packets;
- dev->stats.rx_bytes += ring->rx_bytes;
- }
+ delta = le64_to_cpu(stats->rmac_fcs_err_frms) - sp->stats.rx_crc_errors;
+ sp->stats.rx_crc_errors += delta;
+ dev->stats.rx_crc_errors += delta;
return &dev->stats;
}
@@ -7455,15 +7487,11 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
}
}
- /* Updating statistics */
- ring_data->rx_packets++;
rxdp->Host_Control = 0;
if (sp->rxd_mode == RXD_MODE_1) {
int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
- ring_data->rx_bytes += len;
skb_put(skb, len);
-
} else if (sp->rxd_mode == RXD_MODE_3B) {
int get_block = ring_data->rx_curr_get_info.block_index;
int get_off = ring_data->rx_curr_get_info.offset;
@@ -7472,7 +7500,6 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
unsigned char *buff = skb_push(skb, buf0_len);
struct buffAdd *ba = &ring_data->ba[get_block][get_off];
- ring_data->rx_bytes += buf0_len + buf2_len;
memcpy(buff, ba->ba_0, buf0_len);
skb_put(skb, buf2_len);
}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 47c36e0994f5..7f3a53dcc6ef 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -65,7 +65,7 @@ static int debug_level = ERR_DBG;
/* DEBUG message print. */
#define DBG_PRINT(dbg_level, fmt, args...) do { \
- if (dbg_level >= debug_level) \
+ if (dbg_level <= debug_level) \
pr_info(fmt, ##args); \
} while (0)
@@ -745,10 +745,6 @@ struct ring_info {
/* Buffer Address store. */
struct buffAdd **ba;
-
- /* per-Ring statistics */
- unsigned long rx_packets;
- unsigned long rx_bytes;
} ____cacheline_aligned;
/* Fifo specific structure */
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 1f3acc3a5dfd..79eee3062083 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2671,6 +2671,7 @@ static struct platform_driver sbmac_driver = {
.remove = __exit_p(sbmac_remove),
.driver = {
.name = sbmac_string,
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 2111c7bbf578..7985165e84fc 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
/* Force a renegotiation */
static void sky2_phy_reinit(struct sky2_port *sky2)
{
spin_lock_bh(&sky2->phy_lock);
sky2_phy_init(sky2->hw, sky2->port);
+ sky2_enable_rx_tx(sky2);
spin_unlock_bh(&sky2->phy_lock);
}
@@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2)
{
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u16 reg;
static const char *fc_name[] = {
[FC_NONE] = "none",
[FC_TX] = "tx",
@@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2)
[FC_BOTH] = "both",
};
- /* enable Rx/Tx */
- reg = gma_read16(hw, port, GM_GP_CTRL);
- reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
- gma_write16(hw, port, GM_GP_CTRL, reg);
+ sky2_enable_rx_tx(sky2);
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index c0e70006374e..06b552fca63d 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -367,8 +367,8 @@ static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };
static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
-#define dr32(reg) readl(de->regs + (reg))
-#define dw32(reg,val) writel((val), de->regs + (reg))
+#define dr32(reg) ioread32(de->regs + (reg))
+#define dw32(reg, val) iowrite32((val), de->regs + (reg))
static void de_rx_err_acct (struct de_private *de, unsigned rx_tail,
@@ -1706,6 +1706,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
int value, boguscnt = 100000;
do {
value = dr32(ROMCmd);
+ rmb();
} while (value < 0 && --boguscnt > 0);
de->dev->dev_addr[i] = value;
udelay(1);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 6ad6fe706312..63042596f0cf 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -736,8 +736,18 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
else if (sinfo->gso_type & SKB_GSO_UDP)
gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
- else
- BUG();
+ else {
+ printk(KERN_ERR "tun: unexpected GSO type: "
+ "0x%x, gso_size %d, hdr_len %d\n",
+ sinfo->gso_type, gso.gso_size,
+ gso.hdr_len);
+ print_hex_dump(KERN_ERR, "tun: ",
+ DUMP_PREFIX_NONE,
+ 16, 1, skb->head,
+ min((int)gso.hdr_len, 64), true);
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
} else
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 4a34833b85dd..807470e156af 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
__func__, __LINE__, (u32) skb);
if (skb) {
skb->data = skb->head + NET_SKB_PAD;
+ skb->len = 0;
+ skb_reset_tail_pointer(skb);
__skb_queue_head(&ugeth->rx_recycle, skb);
}
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 0a3c41faea9c..4dd23513c5af 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
/* check for port already opened, if not set the termios */
serial->open_count++;
if (serial->open_count == 1) {
- tty->low_latency = 1;
serial->rx_state = RX_IDLE;
/* Force default termio settings */
_hso_serial_set_termios(tty, NULL);
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 28d3ee175e7b..dd8a4adf48ca 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -104,10 +104,8 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
{
struct cdc_state *info = (void *) &dev->data;
- struct usb_cdc_notification notification;
int master_ifnum;
int retval;
- int partial;
unsigned count;
__le32 rsp;
u32 xid = 0, msg_len, request_id;
@@ -135,17 +133,13 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
if (unlikely(retval < 0 || xid == 0))
return retval;
- /* Some devices don't respond on the control channel until
- * polled on the status channel, so do that first. */
- retval = usb_interrupt_msg(
- dev->udev,
- usb_rcvintpipe(dev->udev, dev->status->desc.bEndpointAddress),
- &notification, sizeof(notification), &partial,
- RNDIS_CONTROL_TIMEOUT_MS);
- if (unlikely(retval < 0))
- return retval;
+ // FIXME Seems like some devices discard responses when
+ // we time out and cancel our "get response" requests...
+ // so, this is fragile. Probably need to poll for status.
- /* Poll the control channel; the request probably completed immediately */
+ /* ignore status endpoint, just poll the control channel;
+ * the request probably completed immediately
+ */
rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
for (count = 0; count < 10; count++) {
memset(buf, 0, CONTROL_BUFFER_SIZE);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index a95c73de5824..81c76ada8e56 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1293,6 +1293,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
goto out;
}
+ /* netdev_printk() needs this so do it as early as possible */
+ SET_NETDEV_DEV(net, &udev->dev);
+
dev = netdev_priv(net);
dev->udev = xdev;
dev->intf = udev;
@@ -1377,8 +1380,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->rx_urb_size = dev->hard_mtu;
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
- SET_NETDEV_DEV(net, &udev->dev);
-
if ((dev->driver_info->flags & FLAG_WLAN) != 0)
SET_NETDEV_DEVTYPE(net, &wlan_type);
if ((dev->driver_info->flags & FLAG_WWAN) != 0)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 1edb7a61983c..bb6b67f6b0cc 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -415,7 +415,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
{
int err;
- bool oom = false;
+ bool oom;
do {
if (vi->mergeable_rx_bufs)
@@ -425,10 +425,9 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
else
err = add_recvbuf_small(vi, gfp);
- if (err < 0) {
- oom = true;
+ oom = err == -ENOMEM;
+ if (err < 0)
break;
- }
++vi->num;
} while (err > 0);
if (unlikely(vi->num > vi->max))
@@ -563,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
struct virtnet_info *vi = netdev_priv(dev);
int capacity;
-again:
/* Free up any pending old buffers before queueing new ones. */
free_old_xmit_skbs(vi);
@@ -572,14 +570,20 @@ again:
/* This can happen with OOM and indirect buffers. */
if (unlikely(capacity < 0)) {
- netif_stop_queue(dev);
- dev_warn(&dev->dev, "Unexpected full queue\n");
- if (unlikely(!virtqueue_enable_cb(vi->svq))) {
- virtqueue_disable_cb(vi->svq);
- netif_start_queue(dev);
- goto again;
+ if (net_ratelimit()) {
+ if (likely(capacity == -ENOMEM)) {
+ dev_warn(&dev->dev,
+ "TX queue failure: out of memory\n");
+ } else {
+ dev->stats.tx_fifo_errors++;
+ dev_warn(&dev->dev,
+ "Unexpected TX queue failure: %d\n",
+ capacity);
+ }
}
- return NETDEV_TX_BUSY;
+ dev->stats.tx_dropped++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
}
virtqueue_kick(vi->svq);
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index b504bd561362..fc8b2d7a0919 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -2262,7 +2262,8 @@ start:
vxge_debug_init(VXGE_ERR,
"%s: memory allocation failed",
VXGE_DRIVER_NAME);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto alloc_entries_failed;
}
vdev->vxge_entries =
@@ -2271,8 +2272,8 @@ start:
if (!vdev->vxge_entries) {
vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
VXGE_DRIVER_NAME);
- kfree(vdev->entries);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto alloc_vxge_entries_failed;
}
for (i = 0, j = 0; i < vdev->no_of_vpath; i++) {
@@ -2303,22 +2304,32 @@ start:
vxge_debug_init(VXGE_ERR,
"%s: MSI-X enable failed for %d vectors, ret: %d",
VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
+ if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+ ret = -ENODEV;
+ goto enable_msix_failed;
+ }
+
kfree(vdev->entries);
kfree(vdev->vxge_entries);
vdev->entries = NULL;
vdev->vxge_entries = NULL;
-
- if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3))
- return -ENODEV;
/* Try with less no of vector by reducing no of vpaths count */
temp = (ret - 1)/2;
vxge_close_vpaths(vdev, temp);
vdev->no_of_vpath = temp;
goto start;
- } else if (ret < 0)
- return -ENODEV;
-
+ } else if (ret < 0) {
+ ret = -ENODEV;
+ goto enable_msix_failed;
+ }
return 0;
+
+enable_msix_failed:
+ kfree(vdev->vxge_entries);
+alloc_vxge_entries_failed:
+ kfree(vdev->entries);
+alloc_entries_failed:
+ return ret;
}
static int vxge_enable_msix(struct vxgedev *vdev)
@@ -4506,9 +4517,9 @@ vxge_starter(void)
char version[32];
snprintf(version, 32, "%s", DRV_VERSION);
- printk(KERN_CRIT "%s: Copyright(c) 2002-2009 Neterion Inc\n",
+ printk(KERN_INFO "%s: Copyright(c) 2002-2009 Neterion Inc\n",
VXGE_DRIVER_NAME);
- printk(KERN_CRIT "%s: Driver version: %s\n",
+ printk(KERN_INFO "%s: Driver version: %s\n",
VXGE_DRIVER_NAME, version);
verify_bandwidth();
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h
index 2d7c96d7e865..eb80243e22df 100644
--- a/drivers/net/wimax/i2400m/i2400m-usb.h
+++ b/drivers/net/wimax/i2400m/i2400m-usb.h
@@ -152,6 +152,7 @@ enum {
/* Device IDs */
USB_DEVICE_ID_I6050 = 0x0186,
USB_DEVICE_ID_I6050_2 = 0x0188,
+ USB_DEVICE_ID_I6250 = 0x0187,
};
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 0d5081d77dc0..d3365ac85dde 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -491,6 +491,7 @@ int i2400mu_probe(struct usb_interface *iface,
switch (id->idProduct) {
case USB_DEVICE_ID_I6050:
case USB_DEVICE_ID_I6050_2:
+ case USB_DEVICE_ID_I6250:
i2400mu->i6050 = 1;
break;
default:
@@ -739,6 +740,7 @@ static
struct usb_device_id i2400mu_id_table[] = {
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) },
+ { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) },
{ USB_DEVICE(0x8086, 0x0181) },
{ USB_DEVICE(0x8086, 0x1403) },
{ USB_DEVICE(0x8086, 0x1405) },
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index e0c244b02f05..31c008042bfe 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
ah->ah_noise_floor = -95; /* until first NF calibration is run */
sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+ ah->ah_current_channel = &sc->channels[0];
/*
* Find the mac version
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index fbb7dec6ddeb..5ea87736a6ae 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -445,6 +445,7 @@ void ath_deinit_leds(struct ath_softc *sc);
#define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
+#define SC_OP_ANI_RUN BIT(14)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 77b359162d6c..23c15aa9fbd5 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -730,13 +730,17 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
/* RX */
if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0)
- goto err;
+ goto err_rx;
/* Register Read */
if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
- goto err;
+ goto err_reg;
return 0;
+err_reg:
+ ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
+err_rx:
+ ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
err:
return -ENOMEM;
}
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index abfa0493236f..1e2a68ea9355 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -336,6 +336,10 @@ set_timer:
static void ath_start_ani(struct ath_common *common)
{
unsigned long timestamp = jiffies_to_msecs(jiffies);
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+ if (!(sc->sc_flags & SC_OP_ANI_RUN))
+ return;
common->ani.longcal_timer = timestamp;
common->ani.shortcal_timer = timestamp;
@@ -872,11 +876,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
/* Reset rssi stats */
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
} else {
ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
common->curaid = 0;
/* Stop ANI */
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
}
}
@@ -1478,8 +1484,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC ||
- vif->type == NL80211_IFTYPE_MONITOR)
+ vif->type == NL80211_IFTYPE_MONITOR) {
+ sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
+ }
out:
mutex_unlock(&sc->mutex);
@@ -1500,6 +1508,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
/* Stop ANI */
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
/* Reclaim beacon resources */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ca6065b71b46..e3e52913d83a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -844,9 +844,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
int dma_type;
if (edma)
- dma_type = DMA_FROM_DEVICE;
- else
dma_type = DMA_BIDIRECTIONAL;
+ else
+ dma_type = DMA_FROM_DEVICE;
qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
spin_lock_bh(&sc->rx.rxbuflock);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index db72461c486b..29b31a694b59 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)
local_info_t *local;
int ret = 1;
struct hostap_cs_priv *hw_priv;
+ unsigned long flags;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)
local->hw_priv = hw_priv;
hw_priv->link = link;
+ /*
+ * Make sure the IRQ handler cannot proceed until at least
+ * dev->base_addr is initialized.
+ */
+ spin_lock_irqsave(&local->irq_init_lock, flags);
+
ret = pcmcia_request_irq(link, prism2_interrupt);
if (ret)
- goto failed;
+ goto failed_unlock;
/*
* This actually configures the PCMCIA socket -- setting up
@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
- goto failed;
+ goto failed_unlock;
dev->irq = link->irq;
dev->base_addr = link->io.BasePort1;
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
+
/* Finally, report what we've done */
printk(KERN_INFO "%s: index 0x%02x: ",
dev_info, link->conf.ConfigIndex);
@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
+ failed_unlock:
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 30c2976b3624..e9d9d622a9b0 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2621,6 +2621,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
iface = netdev_priv(dev);
local = iface->local;
+ /* Detect early interrupt before driver is fully configued */
+ spin_lock(&local->irq_init_lock);
+ if (!dev->base_addr) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
+ dev->name);
+ }
+ spin_unlock(&local->irq_init_lock);
+ return IRQ_HANDLED;
+ }
+ spin_unlock(&local->irq_init_lock);
+
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
if (local->func->card_present && !local->func->card_present(local)) {
@@ -3138,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
spin_lock_init(&local->cmdlock);
spin_lock_init(&local->baplock);
spin_lock_init(&local->lock);
+ spin_lock_init(&local->irq_init_lock);
mutex_init(&local->rid_bap_mtx);
if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index d24dc7dc0723..972a9c3af39e 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -330,6 +330,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,
dev->irq = pdev->irq;
hw_priv->mem_start = mem;
+ dev->base_addr = (unsigned long) mem;
prism2_pci_cor_sreset(local);
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 3d238917af07..1ba33be98b25 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -654,7 +654,7 @@ struct local_info {
rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
* when removing entries from the list.
* TX and RX paths can use read lock. */
- spinlock_t cmdlock, baplock, lock;
+ spinlock_t cmdlock, baplock, lock, irq_init_lock;
struct mutex rid_bap_mtx;
u16 infofid; /* MAC buffer id for info frame */
/* txfid, intransmitfid, next_txtid, and next_alloc are protected by
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 44ef5d93befc..01658cf82d39 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -212,11 +212,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags)
{
- if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
- (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
- *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
- else
- *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
+ *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
}
/* Calc max signal level (dBm) among 3 possible receivers */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index a732f1094e5d..7d614c4d3c62 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -1299,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
sta_id = ba_resp->sta_id;
tid = ba_resp->tid;
agg = &priv->stations[sta_id].tid[tid].agg;
+ if (unlikely(agg->txq_id != scd_flow)) {
+ IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+ scd_flow, agg->txq_id);
+ return;
+ }
/* Find index just before block-ack window */
index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7726e67044c0..24aff654fa9c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3391,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
int ret;
u8 sta_id;
- sta_priv->common.sta_id = IWL_INVALID_STATION;
-
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+ sta->addr);
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
atomic_set(&sta_priv->pending_frames, 0);
if (vif->type == NL80211_IFTYPE_AP)
@@ -3406,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -3415,6 +3418,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl_rs_rate_init(priv, sta, sta_id);
+ mutex_unlock(&priv->mutex);
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 426e95567de3..5bbc5298ef96 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1314,7 +1314,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
changed_flags, *total_flags);
CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
- CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);
CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
@@ -1329,6 +1328,12 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
+ /*
+ * Receiving all multicast frames is always enabled by the
+ * default flags setup in iwl_connection_init_rx_config()
+ * since we currently do not support programming multicast
+ * filters into the device.
+ */
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 5d3f51ff2f0d..386c5f96eff8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work)
mutex_lock(&priv->mutex);
+ cancel_delayed_work_sync(&priv->scan_check);
set_bit(STATUS_SCAN_ABORTING, &priv->status);
iwl_send_scan_abort(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 83a26361a9b5..c27c13fbb1ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+ sta->addr);
ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
if (ret)
IWL_ERR(priv, "Error removing station %pM\n",
sta->addr);
+ mutex_unlock(&priv->mutex);
return ret;
}
EXPORT_SYMBOL(iwl_mac_sta_remove);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index c2a453a1a991..dc43ebd1f1fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -97,6 +97,17 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
spin_lock_irqsave(&priv->sta_lock, flags);
memset(priv->stations, 0, sizeof(priv->stations));
priv->num_stations = 0;
+
+ /*
+ * Remove all key information that is not stored as part of station
+ * information since mac80211 may not have had a
+ * chance to remove all the keys. When device is reconfigured by
+ * mac80211 after an error all keys will be reconfigured.
+ */
+ priv->ucode_key_table = 0;
+ priv->key_mapping_key = 0;
+ memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
+
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 6c353cacc8d6..a27872de4106 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3437,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
u8 sta_id;
- sta_priv->common.sta_id = IWL_INVALID_STATION;
-
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+ sta->addr);
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
+
ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
&sta_id);
@@ -3448,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -3457,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl3945_rs_rate_init(priv, sta, sta_id);
+ mutex_unlock(&priv->mutex);
return 0;
}
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 6a04c2157f73..817fffc0de4b 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
prxpd = (struct rxpd *) skb->data;
- stats.flag = 0;
+ memset(&stats, 0, sizeof(stats));
if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
stats.freq = priv->cur_freq;
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 07c4528f6e6b..a5ea89cde8c4 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
{ PCI_DEVICE(0x1260, 0x3877) },
/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
{ PCI_DEVICE(0x1260, 0x3886) },
+ /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+ { PCI_DEVICE(0x1260, 0xffff) },
{ },
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 3ae468c4d760..f20d3eeeea7f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -854,6 +854,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
BIT(NL80211_IFTYPE_WDS);
/*
+ * Initialize configuration work.
+ */
+ INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
+
+ /*
* Let the driver probe the device to detect the capabilities.
*/
retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);
@@ -863,11 +868,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
}
/*
- * Initialize configuration work.
- */
- INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
-
- /*
* Allocate queue array.
*/
retval = rt2x00queue_allocate(rt2x00dev);
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 188bc8496a26..d02be78a4138 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -176,16 +176,18 @@ static ssize_t led_proc_write(struct file *file, const char *buf,
size_t count, loff_t *pos)
{
void *data = PDE(file->f_path.dentry->d_inode)->data;
- char *cur, lbuf[count + 1];
+ char *cur, lbuf[32];
int d;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- memset(lbuf, 0, count + 1);
+ if (count >= sizeof(lbuf))
+ count = sizeof(lbuf)-1;
if (copy_from_user(lbuf, buf, count))
return -EFAULT;
+ lbuf[count] = 0;
cur = lbuf;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 796828fce34c..c9171be74564 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -340,7 +340,7 @@ int dmar_disabled = 0;
int dmar_disabled = 1;
#endif /*CONFIG_DMAR_DEFAULT_ON*/
-static int __initdata dmar_map_gfx = 1;
+static int dmar_map_gfx = 1;
static int dmar_forcedac;
static int intel_iommu_strict;
@@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
}
}
if (found) {
+ spin_unlock_irqrestore(&device_domain_lock, flags);
free_devinfo_mem(info);
domain_exit(domain);
domain = found;
} else {
list_add(&info->link, &domain->devices);
list_add(&info->global, &device_domain_list);
+ spin_unlock_irqrestore(&device_domain_lock, flags);
}
- spin_unlock_irqrestore(&device_domain_lock, flags);
}
found_domain:
@@ -3603,7 +3604,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
pte = dmar_domain->pgd;
if (dma_pte_present(pte)) {
free_pgtable_page(dmar_domain->pgd);
- dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte);
+ dmar_domain->pgd = (struct dma_pte *)
+ phys_to_virt(dma_pte_addr(pte));
}
dmar_domain->agaw--;
}
@@ -3719,6 +3721,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
*/
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
rwbf_quirk = 1;
+
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
+ if (dev->revision == 0x07) {
+ printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+ dmar_map_gfx = 0;
+ }
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 60f30e7f1c8c..740fb4ea9669 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2292,6 +2292,7 @@ void pci_msi_off(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
}
}
+EXPORT_SYMBOL_GPL(pci_msi_off);
#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c
index aac285a16b62..d672a0a63816 100644
--- a/drivers/pci/pcie/pme/pcie_pme.c
+++ b/drivers/pci/pcie/pme/pcie_pme.c
@@ -34,7 +34,7 @@
* being registered. Consequently, the interrupt-based PCIe PME signaling will
* not be used by any PCIe root ports in that case.
*/
-static bool pcie_pme_disabled;
+static bool pcie_pme_disabled = true;
/*
* The PCI Express Base Specification 2.0, Section 6.1.8, states the following:
@@ -64,12 +64,19 @@ bool pcie_pme_msi_disabled;
static int __init pcie_pme_setup(char *str)
{
- if (!strcmp(str, "off"))
- pcie_pme_disabled = true;
- else if (!strcmp(str, "force"))
+ if (!strncmp(str, "auto", 4))
+ pcie_pme_disabled = false;
+ else if (!strncmp(str, "force", 5))
pcie_pme_force_enable = true;
- else if (!strcmp(str, "nomsi"))
- pcie_pme_msi_disabled = true;
+
+ str = strchr(str, ',');
+ if (str) {
+ str++;
+ str += strspn(str, " \t");
+ if (*str && !strcmp(str, "nomsi"))
+ pcie_pme_msi_disabled = true;
+ }
+
return 1;
}
__setup("pcie_pme=", pcie_pme_setup);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 92379e2d37e7..2aaa13150de3 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -156,6 +156,38 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
pcibios_align_resource, dev);
}
+ if (ret < 0 && dev->fw_addr[resno]) {
+ struct resource *root, *conflict;
+ resource_size_t start, end;
+
+ /*
+ * If we failed to assign anything, let's try the address
+ * where firmware left it. That at least has a chance of
+ * working, which is better than just leaving it disabled.
+ */
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ else
+ root = &iomem_resource;
+
+ start = res->start;
+ end = res->end;
+ res->start = dev->fw_addr[resno];
+ res->end = res->start + size - 1;
+ dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
+ resno, res);
+ conflict = request_resource_conflict(root, res);
+ if (conflict) {
+ dev_info(&dev->dev,
+ "BAR %d: %pR conflicts with %s %pR\n", resno,
+ res, conflict->name, conflict);
+ res->start = start;
+ res->end = end;
+ } else
+ ret = 0;
+ }
+
if (!ret) {
res->flags &= ~IORESOURCE_STARTALIGN;
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 9fc339845538..eac961463be2 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1356,6 +1356,7 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
INIT_LIST_HEAD(&socket->devices_list);
memset(&socket->pcmcia_state, 0, sizeof(u8));
socket->device_count = 0;
+ atomic_set(&socket->present, 0);
ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
if (ret) {
@@ -1364,8 +1365,6 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
return ret;
}
- atomic_set(&socket->present, 0);
-
return 0;
}
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 29f91fac1dff..a4cd9adfcbc0 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -857,8 +857,10 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev)
{
pcmcia_release_configuration(p_dev);
pcmcia_release_io(p_dev, &p_dev->io);
- if (p_dev->_irq)
+ if (p_dev->_irq) {
free_irq(p_dev->irq, p_dev->priv);
+ p_dev->_irq = 0;
+ }
if (p_dev->win)
pcmcia_release_window(p_dev, p_dev->win);
}
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index df4532e91b1a..f370476d5417 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -178,7 +178,6 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
unsigned long val,
struct cpufreq_freqs *freqs)
{
-#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock"
switch (val) {
case CPUFREQ_PRECHANGE:
if (freqs->new > freqs->old) {
@@ -186,7 +185,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
"pre-updating\n",
freqs->new / 1000, (freqs->new / 100) % 10,
freqs->old / 1000, (freqs->old / 100) % 10);
- pxa2xx_pcmcia_set_mcxx(skt, freqs->new);
+ pxa2xx_pcmcia_set_timing(skt);
}
break;
@@ -196,7 +195,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
"post-updating\n",
freqs->new / 1000, (freqs->new / 100) % 10,
freqs->old / 1000, (freqs->old / 100) % 10);
- pxa2xx_pcmcia_set_mcxx(skt, freqs->new);
+ pxa2xx_pcmcia_set_timing(skt);
}
break;
}
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 40658e3385b4..bb2f1fba637b 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -489,7 +489,7 @@ int intel_scu_ipc_simple_command(int cmd, int sub)
mutex_unlock(&ipclock);
return -ENODEV;
}
- ipc_command(cmd << 12 | sub);
+ ipc_command(sub << 12 | cmd);
err = busy_loop();
mutex_unlock(&ipclock);
return err;
@@ -501,9 +501,9 @@ EXPORT_SYMBOL(intel_scu_ipc_simple_command);
* @cmd: command
* @sub: sub type
* @in: input data
- * @inlen: input length
+ * @inlen: input length in dwords
* @out: output data
- * @outlein: output length
+ * @outlein: output length in dwords
*
* Issue a command to the SCU which involves data transfers. Do the
* data copies under the lock but leave it for the caller to interpret
@@ -524,7 +524,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
for (i = 0; i < inlen; i++)
ipc_data_writel(*in++, 4 * i);
- ipc_command((cmd << 12) | sub | (inlen << 18));
+ ipc_command((sub << 12) | cmd | (inlen << 18));
err = busy_loop();
for (i = 0; i < outlen; i++)
@@ -556,6 +556,10 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
u32 cmd = 0;
mutex_lock(&ipclock);
+ if (ipcdev.pdev == NULL) {
+ mutex_unlock(&ipclock);
+ return -ENODEV;
+ }
cmd = (addr >> 24) & 0xFF;
if (cmd == IPC_I2C_READ) {
writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index d762a0cbc6af..84d3c43cf2bc 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -43,10 +43,9 @@
struct ds278x_info;
struct ds278x_battery_ops {
- int (*get_current)(struct ds278x_info *info, int *current_uA);
- int (*get_voltage)(struct ds278x_info *info, int *voltage_uA);
- int (*get_capacity)(struct ds278x_info *info, int *capacity_uA);
-
+ int (*get_battery_current)(struct ds278x_info *info, int *current_uA);
+ int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uA);
+ int (*get_battery_capacity)(struct ds278x_info *info, int *capacity_uA);
};
#define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)
@@ -163,7 +162,7 @@ static int ds2782_get_capacity(struct ds278x_info *info, int *capacity)
if (err)
return err;
*capacity = raw;
- return raw;
+ return 0;
}
static int ds2786_get_current(struct ds278x_info *info, int *current_uA)
@@ -213,11 +212,11 @@ static int ds278x_get_status(struct ds278x_info *info, int *status)
int current_uA;
int capacity;
- err = info->ops->get_current(info, &current_uA);
+ err = info->ops->get_battery_current(info, &current_uA);
if (err)
return err;
- err = info->ops->get_capacity(info, &capacity);
+ err = info->ops->get_battery_capacity(info, &capacity);
if (err)
return err;
@@ -246,15 +245,15 @@ static int ds278x_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CAPACITY:
- ret = info->ops->get_capacity(info, &val->intval);
+ ret = info->ops->get_battery_capacity(info, &val->intval);
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- ret = info->ops->get_voltage(info, &val->intval);
+ ret = info->ops->get_battery_voltage(info, &val->intval);
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
- ret = info->ops->get_current(info, &val->intval);
+ ret = info->ops->get_battery_current(info, &val->intval);
break;
case POWER_SUPPLY_PROP_TEMP:
@@ -307,14 +306,14 @@ enum ds278x_num_id {
static struct ds278x_battery_ops ds278x_ops[] = {
[DS2782] = {
- .get_current = ds2782_get_current,
- .get_voltage = ds2782_get_voltage,
- .get_capacity = ds2782_get_capacity,
+ .get_battery_current = ds2782_get_current,
+ .get_battery_voltage = ds2782_get_voltage,
+ .get_battery_capacity = ds2782_get_capacity,
},
[DS2786] = {
- .get_current = ds2786_get_current,
- .get_voltage = ds2786_get_voltage,
- .get_capacity = ds2786_get_capacity,
+ .get_battery_current = ds2786_get_current,
+ .get_battery_voltage = ds2786_get_voltage,
+ .get_battery_capacity = ds2786_get_capacity,
}
};
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index 9cca465436e3..85064a9f649e 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -9,19 +9,13 @@
*
*/
-#include <linux/init.h>
-#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/i2c.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
#include <linux/gpio.h>
+#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
#include <linux/z2_battery.h>
#define Z2_DEFAULT_NAME "Z2"
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 7b14a67bdca2..11790990277a 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -286,7 +286,7 @@ static int ab3100_list_voltage_regulator(struct regulator_dev *reg,
{
struct ab3100_regulator *abreg = reg->reg_data;
- if (selector > abreg->voltages_len)
+ if (selector >= abreg->voltages_len)
return -EINVAL;
return abreg->typ_voltages[selector];
}
@@ -318,7 +318,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
regval &= 0xE0;
regval >>= 5;
- if (regval > abreg->voltages_len) {
+ if (regval >= abreg->voltages_len) {
dev_err(&reg->dev,
"regulator register %02x contains an illegal voltage setting\n",
abreg->regreg);
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 14b4576281c5..8152d65220f5 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/tps6507x.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/mfd/tps6507x.h>
@@ -101,9 +102,12 @@ struct tps_info {
unsigned max_uV;
u8 table_len;
const u16 *table;
+
+ /* Does DCDC high or the low register defines output voltage? */
+ bool defdcdc_default;
};
-static const struct tps_info tps6507x_pmic_regs[] = {
+static struct tps_info tps6507x_pmic_regs[] = {
{
.name = "VDCDC1",
.min_uV = 725000,
@@ -145,7 +149,7 @@ struct tps6507x_pmic {
struct regulator_desc desc[TPS6507X_NUM_REGULATOR];
struct tps6507x_dev *mfd;
struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR];
- const struct tps_info *info[TPS6507X_NUM_REGULATOR];
+ struct tps_info *info[TPS6507X_NUM_REGULATOR];
struct mutex io_lock;
};
static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg)
@@ -341,10 +345,16 @@ static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev)
reg = TPS6507X_REG_DEFDCDC1;
break;
case TPS6507X_DCDC_2:
- reg = TPS6507X_REG_DEFDCDC2_LOW;
+ if (tps->info[dcdc]->defdcdc_default)
+ reg = TPS6507X_REG_DEFDCDC2_HIGH;
+ else
+ reg = TPS6507X_REG_DEFDCDC2_LOW;
break;
case TPS6507X_DCDC_3:
- reg = TPS6507X_REG_DEFDCDC3_LOW;
+ if (tps->info[dcdc]->defdcdc_default)
+ reg = TPS6507X_REG_DEFDCDC3_HIGH;
+ else
+ reg = TPS6507X_REG_DEFDCDC3_LOW;
break;
default:
return -EINVAL;
@@ -370,10 +380,16 @@ static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,
reg = TPS6507X_REG_DEFDCDC1;
break;
case TPS6507X_DCDC_2:
- reg = TPS6507X_REG_DEFDCDC2_LOW;
+ if (tps->info[dcdc]->defdcdc_default)
+ reg = TPS6507X_REG_DEFDCDC2_HIGH;
+ else
+ reg = TPS6507X_REG_DEFDCDC2_LOW;
break;
case TPS6507X_DCDC_3:
- reg = TPS6507X_REG_DEFDCDC3_LOW;
+ if (tps->info[dcdc]->defdcdc_default)
+ reg = TPS6507X_REG_DEFDCDC3_HIGH;
+ else
+ reg = TPS6507X_REG_DEFDCDC3_LOW;
break;
default:
return -EINVAL;
@@ -532,7 +548,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
{
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
static int desc_id;
- const struct tps_info *info = &tps6507x_pmic_regs[0];
+ struct tps_info *info = &tps6507x_pmic_regs[0];
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
struct tps6507x_pmic *tps;
@@ -569,6 +585,12 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) {
/* Register the regulators */
tps->info[i] = info;
+ if (init_data->driver_data) {
+ struct tps6507x_reg_platform_data *data =
+ init_data->driver_data;
+ tps->info[i]->defdcdc_default = data->defdcdc_default;
+ }
+
tps->desc[i].name = info->name;
tps->desc[i].id = desc_id++;
tps->desc[i].n_voltages = num_voltages[i];
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 723cd1fb4867..0e6ed7db9364 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1495,7 +1495,7 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
if (ret != 0) {
dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
reg, ret);
- platform_device_del(pdev);
+ platform_device_put(pdev);
wm8350->pmic.pdev[reg] = NULL;
}
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 92a8f6cacda9..34647fc1ee98 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -29,6 +29,7 @@
#include <linux/bcd.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/slab.h>
/*
* The DaVinci RTC is a simple RTC with the following
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index de033b7ac21f..d827ce570a8c 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -777,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
read_rtc:
/* read RTC registers */
- tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf);
+ tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
if (tmp != 8) {
pr_debug("read error %d\n", tmp);
err = -EIO;
@@ -862,7 +862,7 @@ read_rtc:
if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
tmp += 12;
i2c_smbus_write_byte_data(client,
- DS1307_REG_HOUR,
+ ds1307->offset + DS1307_REG_HOUR,
bin2bcd(tmp));
}
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 3587d9922f28..71bbefc3544e 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -456,7 +456,7 @@ static struct rtc_class_ops stv2_pl031_ops = {
.irq_set_freq = pl031_irq_set_freq,
};
-static struct amba_id pl031_ids[] __initdata = {
+static struct amba_id pl031_ids[] = {
{
.id = 0x00041031,
.mask = 0x000fffff,
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index 9718aaaa8215..600b890a3c15 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -168,7 +168,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
- err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG,
+ err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL,
(data | RX8581_CTRL_STOP));
if (err < 0) {
dev_err(&client->dev, "Unable to write control register\n");
@@ -182,6 +182,20 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
+ /* get VLF and clear it */
+ data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG);
+ if (data < 0) {
+ dev_err(&client->dev, "Unable to read flag register\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG,
+ (data & ~(RX8581_FLAG_VLF)));
+ if (err != 0) {
+ dev_err(&client->dev, "Unable to write flag register\n");
+ return -EIO;
+ }
+
/* Restart the clock */
data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL);
if (data < 0) {
@@ -189,8 +203,8 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
- err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG,
- (data | ~(RX8581_CTRL_STOP)));
+ err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL,
+ (data & ~(RX8581_CTRL_STOP)));
if (err != 0) {
dev_err(&client->dev, "Unable to write control register\n");
return -EIO;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 34d51dd4c539..bed7b4634ccd 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -948,8 +948,10 @@ static ssize_t dasd_alias_show(struct device *dev,
if (device->discipline && device->discipline->get_uid &&
!device->discipline->get_uid(device, &uid)) {
if (uid.type == UA_BASE_PAV_ALIAS ||
- uid.type == UA_HYPER_PAV_ALIAS)
+ uid.type == UA_HYPER_PAV_ALIAS) {
+ dasd_put_device(device);
return sprintf(buf, "1\n");
+ }
}
dasd_put_device(device);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index ce7cb87479fe..407d0e9adfaf 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -713,7 +713,7 @@ int chsc_determine_base_channel_path_desc(struct chp_id chpid,
ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, chsc_resp);
if (ret)
goto out_free;
- memcpy(desc, &chsc_resp->data, chsc_resp->length);
+ memcpy(desc, &chsc_resp->data, sizeof(*desc));
out_free:
kfree(chsc_resp);
return ret;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index e3dbeda97179..fd068bc1bd0a 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -714,6 +714,14 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
return ZFCP_ERP_FAILED;
+ if (mempool_resize(act->adapter->pool.status_read_data,
+ act->adapter->stat_read_buf_num, GFP_KERNEL))
+ return ZFCP_ERP_FAILED;
+
+ if (mempool_resize(act->adapter->pool.status_read_req,
+ act->adapter->stat_read_buf_num, GFP_KERNEL))
+ return ZFCP_ERP_FAILED;
+
atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
if (zfcp_status_read_refill(act->adapter))
return ZFCP_ERP_FAILED;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9ac6a6e4a604..71663fb77310 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -496,7 +496,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
adapter->hydra_version = bottom->adapter_type;
adapter->timer_ticks = bottom->timer_interval;
- adapter->stat_read_buf_num = max(bottom->status_read_buf_num, (u16)16);
+ adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
+ (u16)FSF_STATUS_READS_RECOM);
if (fc_host_permanent_port_name(shost) == -1)
fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
@@ -719,11 +720,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
req->qtcb, sizeof(struct fsf_qtcb));
- if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) {
- zfcp_fsf_req_free(req);
- return ERR_PTR(-EIO);
- }
-
return req;
}
@@ -981,7 +977,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
}
/* use single, unchained SBAL if it can hold the request */
- if (zfcp_qdio_sg_one_sbale(sg_req) || zfcp_qdio_sg_one_sbale(sg_resp)) {
+ if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
sg_req, sg_resp);
return 0;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 28117e130e2c..6fa5e0453176 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -251,7 +251,8 @@ static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
struct zfcp_qdio_queue *req_q = &qdio->req_q;
spin_lock_bh(&qdio->req_q_lock);
- if (atomic_read(&req_q->count))
+ if (atomic_read(&req_q->count) ||
+ !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return 1;
spin_unlock_bh(&qdio->req_q_lock);
return 0;
@@ -274,8 +275,13 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
spin_unlock_bh(&qdio->req_q_lock);
ret = wait_event_interruptible_timeout(qdio->req_q_wq,
zfcp_qdio_sbal_check(qdio), 5 * HZ);
+
+ if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
+ return -EIO;
+
if (ret > 0)
return 0;
+
if (!ret) {
atomic_inc(&qdio->req_q_full);
/* assume hanging outbound queue, try queue recovery */
@@ -375,6 +381,8 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
spin_unlock_bh(&qdio->req_q_lock);
+ wake_up(&qdio->req_q_wq);
+
qdio_shutdown(qdio->adapter->ccw_device,
QDIO_FLAG_CLEANUP_USING_CLEAR);
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index d53e62ab09da..aacbe14e2e7a 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -554,7 +554,7 @@ static int opiocgetnext(unsigned int cmd, void __user *argp)
static int openprom_bsd_ioctl(struct file * file,
unsigned int cmd, unsigned long arg)
{
- DATA *data = (DATA *) file->private_data;
+ DATA *data = file->private_data;
void __user *argp = (void __user *)arg;
int err;
@@ -601,7 +601,7 @@ static int openprom_bsd_ioctl(struct file * file,
static long openprom_ioctl(struct file * file,
unsigned int cmd, unsigned long arg)
{
- DATA *data = (DATA *) file->private_data;
+ DATA *data = file->private_data;
switch (cmd) {
case OPROMGETOPT:
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index a864ccc0a342..989b9a8ba72d 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -277,6 +277,12 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue,
goto reg_crq_failed;
}
+ queue->cur = 0;
+ spin_lock_init(&queue->lock);
+
+ tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
+ (unsigned long)hostdata);
+
if (request_irq(vdev->irq,
rpavscsi_handle_event,
0, "ibmvscsi", (void *)hostdata) != 0) {
@@ -291,15 +297,10 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue,
goto req_irq_failed;
}
- queue->cur = 0;
- spin_lock_init(&queue->lock);
-
- tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
- (unsigned long)hostdata);
-
return retrc;
req_irq_failed:
+ tasklet_kill(&hostdata->srp_task);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 82ea4a8226b0..f820cffb7f00 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1129,20 +1129,22 @@ static int ipr_is_same_device(struct ipr_resource_entry *res,
}
/**
- * ipr_format_resource_path - Format the resource path for printing.
+ * ipr_format_res_path - Format the resource path for printing.
* @res_path: resource path
* @buf: buffer
*
* Return value:
* pointer to buffer
**/
-static char *ipr_format_resource_path(u8 *res_path, char *buffer)
+static char *ipr_format_res_path(u8 *res_path, char *buffer, int len)
{
int i;
+ char *p = buffer;
- sprintf(buffer, "%02X", res_path[0]);
- for (i=1; res_path[i] != 0xff; i++)
- sprintf(buffer, "%s-%02X", buffer, res_path[i]);
+ res_path[0] = '\0';
+ p += snprintf(p, buffer + len - p, "%02X", res_path[0]);
+ for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++)
+ p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);
return buffer;
}
@@ -1187,7 +1189,8 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res,
if (res->sdev && new_path)
sdev_printk(KERN_INFO, res->sdev, "Resource path: %s\n",
- ipr_format_resource_path(&res->res_path[0], &buffer[0]));
+ ipr_format_res_path(res->res_path, buffer,
+ sizeof(buffer)));
} else {
res->flags = cfgtew->u.cfgte->flags;
if (res->flags & IPR_IS_IOA_RESOURCE)
@@ -1573,7 +1576,8 @@ static void ipr_log_sis64_config_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err_separator;
ipr_err("Device %d : %s", i + 1,
- ipr_format_resource_path(&dev_entry->res_path[0], &buffer[0]));
+ ipr_format_res_path(dev_entry->res_path, buffer,
+ sizeof(buffer)));
ipr_log_ext_vpd(&dev_entry->vpd);
ipr_err("-----New Device Information-----\n");
@@ -1919,13 +1923,14 @@ static void ipr_log64_fabric_path(struct ipr_hostrcb *hostrcb,
ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s\n",
path_active_desc[i].desc, path_state_desc[j].desc,
- ipr_format_resource_path(&fabric->res_path[0], &buffer[0]));
+ ipr_format_res_path(fabric->res_path, buffer,
+ sizeof(buffer)));
return;
}
}
ipr_err("Path state=%02X Resource Path=%s\n", path_state,
- ipr_format_resource_path(&fabric->res_path[0], &buffer[0]));
+ ipr_format_res_path(fabric->res_path, buffer, sizeof(buffer)));
}
static const struct {
@@ -2066,7 +2071,8 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,
ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s, Link rate=%s, WWN=%08X%08X\n",
path_status_desc[j].desc, path_type_desc[i].desc,
- ipr_format_resource_path(&cfg->res_path[0], &buffer[0]),
+ ipr_format_res_path(cfg->res_path, buffer,
+ sizeof(buffer)),
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
return;
@@ -2074,7 +2080,7 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,
}
ipr_hcam_err(hostrcb, "Path element=%02X: Resource Path=%s, Link rate=%s "
"WWN=%08X%08X\n", cfg->type_status,
- ipr_format_resource_path(&cfg->res_path[0], &buffer[0]),
+ ipr_format_res_path(cfg->res_path, buffer, sizeof(buffer)),
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
}
@@ -2139,7 +2145,7 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("RAID %s Array Configuration: %s\n",
error->protection_level,
- ipr_format_resource_path(&error->last_res_path[0], &buffer[0]));
+ ipr_format_res_path(error->last_res_path, buffer, sizeof(buffer)));
ipr_err_separator;
@@ -2160,9 +2166,11 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("Array Member %d:\n", i);
ipr_log_ext_vpd(&array_entry->vpd);
ipr_err("Current Location: %s",
- ipr_format_resource_path(&array_entry->res_path[0], &buffer[0]));
+ ipr_format_res_path(array_entry->res_path, buffer,
+ sizeof(buffer)));
ipr_err("Expected Location: %s",
- ipr_format_resource_path(&array_entry->expected_res_path[0], &buffer[0]));
+ ipr_format_res_path(array_entry->expected_res_path,
+ buffer, sizeof(buffer)));
ipr_err_separator;
}
@@ -4079,7 +4087,8 @@ static struct device_attribute ipr_adapter_handle_attr = {
};
/**
- * ipr_show_resource_path - Show the resource path for this device.
+ * ipr_show_resource_path - Show the resource path or the resource address for
+ * this device.
* @dev: device struct
* @buf: buffer
*
@@ -4097,9 +4106,14 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
res = (struct ipr_resource_entry *)sdev->hostdata;
- if (res)
+ if (res && ioa_cfg->sis64)
len = snprintf(buf, PAGE_SIZE, "%s\n",
- ipr_format_resource_path(&res->res_path[0], &buffer[0]));
+ ipr_format_res_path(res->res_path, buffer,
+ sizeof(buffer)));
+ else if (res)
+ len = snprintf(buf, PAGE_SIZE, "%d:%d:%d:%d\n", ioa_cfg->host->host_no,
+ res->bus, res->target, res->lun);
+
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return len;
}
@@ -4351,7 +4365,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
if (ioa_cfg->sis64)
sdev_printk(KERN_INFO, sdev, "Resource path: %s\n",
- ipr_format_resource_path(&res->res_path[0], &buffer[0]));
+ ipr_format_res_path(res->res_path, buffer,
+ sizeof(buffer)));
return 0;
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 9ecd2259eb39..b965f3587c9d 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1684,8 +1684,9 @@ struct ipr_ucode_image_header {
if (ipr_is_device(hostrcb)) { \
if ((hostrcb)->ioa_cfg->sis64) { \
printk(KERN_ERR IPR_NAME ": %s: " fmt, \
- ipr_format_resource_path(&hostrcb->hcam.u.error64.fd_res_path[0], \
- &hostrcb->rp_buffer[0]), \
+ ipr_format_res_path(hostrcb->hcam.u.error64.fd_res_path, \
+ hostrcb->rp_buffer, \
+ sizeof(hostrcb->rp_buffer)), \
__VA_ARGS__); \
} else { \
ipr_ra_err((hostrcb)->ioa_cfg, \
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index b09a638d051f..50441ffe8e38 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -782,7 +782,7 @@ static int pl010_resume(struct amba_device *dev)
return 0;
}
-static struct amba_id pl010_ids[] __initdata = {
+static struct amba_id pl010_ids[] = {
{
.id = 0x00041010,
.mask = 0x000fffff,
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index eb4cb480b93e..6ca7a44f29c2 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -69,9 +69,12 @@
struct uart_amba_port {
struct uart_port port;
struct clk *clk;
- unsigned int im; /* interrupt mask */
+ unsigned int im; /* interrupt mask */
unsigned int old_status;
- unsigned int ifls; /* vendor-specific */
+ unsigned int ifls; /* vendor-specific */
+ unsigned int lcrh_tx; /* vendor-specific */
+ unsigned int lcrh_rx; /* vendor-specific */
+ bool oversampling; /* vendor-specific */
bool autorts;
};
@@ -79,16 +82,25 @@ struct uart_amba_port {
struct vendor_data {
unsigned int ifls;
unsigned int fifosize;
+ unsigned int lcrh_tx;
+ unsigned int lcrh_rx;
+ bool oversampling;
};
static struct vendor_data vendor_arm = {
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.fifosize = 16,
+ .lcrh_tx = UART011_LCRH,
+ .lcrh_rx = UART011_LCRH,
+ .oversampling = false,
};
static struct vendor_data vendor_st = {
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
.fifosize = 64,
+ .lcrh_tx = ST_UART011_LCRH_TX,
+ .lcrh_rx = ST_UART011_LCRH_RX,
+ .oversampling = true,
};
static void pl011_stop_tx(struct uart_port *port)
@@ -327,12 +339,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
unsigned int lcr_h;
spin_lock_irqsave(&uap->port.lock, flags);
- lcr_h = readw(uap->port.membase + UART011_LCRH);
+ lcr_h = readw(uap->port.membase + uap->lcrh_tx);
if (break_state == -1)
lcr_h |= UART01x_LCRH_BRK;
else
lcr_h &= ~UART01x_LCRH_BRK;
- writew(lcr_h, uap->port.membase + UART011_LCRH);
+ writew(lcr_h, uap->port.membase + uap->lcrh_tx);
spin_unlock_irqrestore(&uap->port.lock, flags);
}
@@ -393,7 +405,17 @@ static int pl011_startup(struct uart_port *port)
writew(cr, uap->port.membase + UART011_CR);
writew(0, uap->port.membase + UART011_FBRD);
writew(1, uap->port.membase + UART011_IBRD);
- writew(0, uap->port.membase + UART011_LCRH);
+ writew(0, uap->port.membase + uap->lcrh_rx);
+ if (uap->lcrh_tx != uap->lcrh_rx) {
+ int i;
+ /*
+ * Wait 10 PCLKs before writing LCRH_TX register,
+ * to get this delay write read only register 10 times
+ */
+ for (i = 0; i < 10; ++i)
+ writew(0xff, uap->port.membase + UART011_MIS);
+ writew(0, uap->port.membase + uap->lcrh_tx);
+ }
writew(0, uap->port.membase + UART01x_DR);
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
barrier();
@@ -422,10 +444,19 @@ static int pl011_startup(struct uart_port *port)
return retval;
}
+static void pl011_shutdown_channel(struct uart_amba_port *uap,
+ unsigned int lcrh)
+{
+ unsigned long val;
+
+ val = readw(uap->port.membase + lcrh);
+ val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
+ writew(val, uap->port.membase + lcrh);
+}
+
static void pl011_shutdown(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned long val;
/*
* disable all interrupts
@@ -450,9 +481,9 @@ static void pl011_shutdown(struct uart_port *port)
/*
* disable break condition and fifos
*/
- val = readw(uap->port.membase + UART011_LCRH);
- val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
- writew(val, uap->port.membase + UART011_LCRH);
+ pl011_shutdown_channel(uap, uap->lcrh_rx);
+ if (uap->lcrh_rx != uap->lcrh_tx)
+ pl011_shutdown_channel(uap, uap->lcrh_tx);
/*
* Shut down the clock producer
@@ -472,8 +503,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = port->uartclk * 4 / baud;
+ baud = uart_get_baud_rate(port, termios, old, 0,
+ port->uartclk/(uap->oversampling ? 8 : 16));
+
+ if (baud > port->uartclk/16)
+ quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
+ else
+ quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud);
switch (termios->c_cflag & CSIZE) {
case CS5:
@@ -552,6 +588,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
uap->autorts = false;
}
+ if (uap->oversampling) {
+ if (baud > port->uartclk/16)
+ old_cr |= ST_UART011_CR_OVSFACT;
+ else
+ old_cr &= ~ST_UART011_CR_OVSFACT;
+ }
+
/* Set baud rate */
writew(quot & 0x3f, port->membase + UART011_FBRD);
writew(quot >> 6, port->membase + UART011_IBRD);
@@ -561,7 +604,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
* ----------^----------^----------^----------^-----
*/
- writew(lcr_h, port->membase + UART011_LCRH);
+ writew(lcr_h, port->membase + uap->lcrh_rx);
+ if (uap->lcrh_rx != uap->lcrh_tx) {
+ int i;
+ /*
+ * Wait 10 PCLKs before writing LCRH_TX register,
+ * to get this delay write read only register 10 times
+ */
+ for (i = 0; i < 10; ++i)
+ writew(0xff, uap->port.membase + UART011_MIS);
+ writew(lcr_h, port->membase + uap->lcrh_tx);
+ }
writew(old_cr, port->membase + UART011_CR);
spin_unlock_irqrestore(&port->lock, flags);
@@ -688,7 +741,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
unsigned int lcr_h, ibrd, fbrd;
- lcr_h = readw(uap->port.membase + UART011_LCRH);
+ lcr_h = readw(uap->port.membase + uap->lcrh_tx);
*parity = 'n';
if (lcr_h & UART01x_LCRH_PEN) {
@@ -707,6 +760,12 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
fbrd = readw(uap->port.membase + UART011_FBRD);
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
+
+ if (uap->oversampling) {
+ if (readw(uap->port.membase + UART011_CR)
+ & ST_UART011_CR_OVSFACT)
+ *baud *= 2;
+ }
}
}
@@ -800,6 +859,9 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id)
}
uap->ifls = vendor->ifls;
+ uap->lcrh_rx = vendor->lcrh_rx;
+ uap->lcrh_tx = vendor->lcrh_tx;
+ uap->oversampling = vendor->oversampling;
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;
@@ -868,7 +930,7 @@ static int pl011_resume(struct amba_device *dev)
}
#endif
-static struct amba_id pl011_ids[] __initdata = {
+static struct amba_id pl011_ids[] = {
{
.id = 0x00041011,
.mask = 0x000fffff,
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index eed3c2d8dd1c..a182def7007d 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -41,6 +41,7 @@
#include <linux/uaccess.h>
#include <asm/io.h>
+#include <asm/ioctls.h>
#include <asm/mach/serial_at91.h>
#include <mach/board.h>
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 9259e849f463..6016179db533 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
}
}
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
+/*
+ * Write a string to the serial port
+ * Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
+ const char *string, u_int count)
+{
+ unsigned int i;
+ cbd_t __iomem *bdp, *bdbase;
+ unsigned char *cpm_outp_addr;
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = pinfo->tx_cur;
+ bdbase = pinfo->tx_bd_base;
+
+ /*
+ * Now, do each character. This is not as bad as it looks
+ * since this is a holding FIFO and not a transmitting FIFO.
+ * We could add the complexity of filling the entire transmit
+ * buffer, but we would just wait longer between accesses......
+ */
+ for (i = 0; i < count; i++, string++) {
+ /* Wait for transmitter fifo to empty.
+ * Ready indicates output is ready, and xmt is doing
+ * that, not that it is ready for us to send.
+ */
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ /* Send the character out.
+ * If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+ pinfo);
+ *cpm_outp_addr = *string;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+
+ /* if a LF, also do CR... */
+ if (*string == 10) {
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+ pinfo);
+ *cpm_outp_addr = 13;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+ }
+ }
+
+ /*
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
+ */
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ pinfo->tx_cur = bdp;
+}
+#endif
+
#ifdef CONFIG_CONSOLE_POLL
/* Serial polling routines for writing and reading from the uart while
* in an interrupt or debug context.
@@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port,
static char ch[2];
ch[0] = (char)c;
- cpm_uart_early_write(pinfo->port.line, ch, 1);
+ cpm_uart_early_write(pinfo, ch, 1);
}
#endif /* CONFIG_CONSOLE_POLL */
@@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s,
u_int count)
{
struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
- unsigned int i;
- cbd_t __iomem *bdp, *bdbase;
- unsigned char *cp;
unsigned long flags;
int nolock = oops_in_progress;
@@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
spin_lock_irqsave(&pinfo->port.lock, flags);
}
- /* Get the address of the host memory buffer.
- */
- bdp = pinfo->tx_cur;
- bdbase = pinfo->tx_bd_base;
-
- /*
- * Now, do each character. This is not as bad as it looks
- * since this is a holding FIFO and not a transmitting FIFO.
- * We could add the complexity of filling the entire transmit
- * buffer, but we would just wait longer between accesses......
- */
- for (i = 0; i < count; i++, s++) {
- /* Wait for transmitter fifo to empty.
- * Ready indicates output is ready, and xmt is doing
- * that, not that it is ready for us to send.
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- /* Send the character out.
- * If the buffer address is in the CPM DPRAM, don't
- * convert it.
- */
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- *cp = *s;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
-
- /* if a LF, also do CR... */
- if (*s == 10) {
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- *cp = 13;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- pinfo->tx_cur = bdp;
+ cpm_uart_early_write(pinfo, s, count);
if (unlikely(nolock)) {
local_irq_restore(flags);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 526307368f8b..ab17c08ddc03 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -821,6 +821,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index ed7d958b0a01..544f2e25d0e5 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -71,7 +71,9 @@ int sunserial_console_match(struct console *con, struct device_node *dp,
con->index = line;
drv->cons = con;
- add_preferred_console(con->name, line, NULL);
+
+ if (!console_set_on_cmdline)
+ add_preferred_console(con->name, line, NULL);
return 1;
}
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 234459c2f012..ffbf4553f665 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1500,20 +1500,25 @@ out_unmap:
static int __devexit su_remove(struct of_device *op)
{
struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
+ bool kbdms = false;
if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD) {
+ up->su_type == SU_PORT_KBD)
+ kbdms = true;
+
+ if (kbdms) {
#ifdef CONFIG_SERIO
serio_unregister_port(&up->serio);
#endif
- kfree(up);
- } else if (up->port.type != PORT_UNKNOWN) {
+ } else if (up->port.type != PORT_UNKNOWN)
uart_remove_one_port(&sunsu_reg, &up->port);
- }
if (up->port.membase)
of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
+ if (kbdms)
+ kfree(up);
+
dev_set_drvdata(&op->dev, NULL);
return 0;
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index ffa111a7e9d4..97ab0a81338a 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -66,28 +66,6 @@ struct mpc8xxx_spi_reg {
__be32 receive;
};
-/* SPI Parameter RAM */
-struct spi_pram {
- __be16 rbase; /* Rx Buffer descriptor base address */
- __be16 tbase; /* Tx Buffer descriptor base address */
- u8 rfcr; /* Rx function code */
- u8 tfcr; /* Tx function code */
- __be16 mrblr; /* Max receive buffer length */
- __be32 rstate; /* Internal */
- __be32 rdp; /* Internal */
- __be16 rbptr; /* Internal */
- __be16 rbc; /* Internal */
- __be32 rxtmp; /* Internal */
- __be32 tstate; /* Internal */
- __be32 tdp; /* Internal */
- __be16 tbptr; /* Internal */
- __be16 tbc; /* Internal */
- __be32 txtmp; /* Internal */
- __be32 res; /* Tx temp. */
- __be16 rpbase; /* Relocation pointer (CPM1 only) */
- __be16 res1; /* Reserved */
-};
-
/* SPI Controller mode register definitions */
#define SPMODE_LOOP (1 << 30)
#define SPMODE_CI_INACTIVEHIGH (1 << 29)
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c
index e2c000b80ca0..212bc21e6d68 100644
--- a/drivers/staging/batman-adv/bat_sysfs.c
+++ b/drivers/staging/batman-adv/bat_sysfs.c
@@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = {
NULL,
};
-static ssize_t transtable_local_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj,
return hna_local_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t transtable_global_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj,
return hna_global_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t originators_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t originators_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj,
return orig_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t vis_data_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
index 7eb6559e0315..32204b5572d0 100644
--- a/drivers/staging/batman-adv/device.c
+++ b/drivers/staging/batman-adv/device.c
@@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
kfree(device_packet);
if (error)
- return error;
+ return -EFAULT;
return sizeof(struct icmp_packet);
}
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 36a254cd4413..39d112b708e3 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
false, true, true);
- dev_private->scan_delay =
- (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
- async_cmd->chanlist_len)) - 1;
+ if (async_cmd->scan_begin_src == TRIG_TIMER) {
+ dev_private->scan_delay =
+ (async_cmd->scan_begin_arg /
+ (async_cmd->convert_arg *
+ async_cmd->chanlist_len)) - 1;
+ }
break;
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 81829d6fd287..c374bee25068 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -52,7 +52,6 @@ Please report success/failure with other different cards to
#include "8255.h"
#define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */
-#define N_BOARDS 10 /* Number of boards in cb_pcidda_boards */
#define EEPROM_SIZE 128 /* number of entries in eeprom */
#define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */
@@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
continue;
}
}
- for (index = 0; index < N_BOARDS; index++) {
+ for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {
if (cb_pcidda_boards[index].device_id ==
pcidev->device) {
goto found;
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 3f53b4d1e4cf..12db555a3a5d 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/completion.h>
#include "osd.h"
#include "logging.h"
#include "vmbus_private.h"
@@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)
Channel);
}
+
+DECLARE_COMPLETION(hv_channel_ready);
+
+/*
+ * Count initialized channels, and ensure all channels are ready when hv_vmbus
+ * module loading completes.
+ */
+static void count_hv_channel(void)
+{
+ static int counter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+ if (++counter == MAX_MSG_TYPES)
+ complete(&hv_channel_ready);
+ spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+}
+
+
/*
* VmbusChannelProcessOffer - Process the offer by creating a channel/device
* associated with this offer
@@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context)
* can cleanup properly
*/
newChannel->State = CHANNEL_OPEN_STATE;
- cnt = 0;
- while (cnt != MAX_MSG_TYPES) {
+ /* Open IC channels */
+ for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
&hv_cb_utils[cnt].data,
- sizeof(struct hv_guid)) == 0) {
+ sizeof(struct hv_guid)) == 0 &&
+ VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
+ 2 * PAGE_SIZE, NULL, 0,
+ hv_cb_utils[cnt].callback,
+ newChannel) == 0) {
+ hv_cb_utils[cnt].channel = newChannel;
DPRINT_INFO(VMBUS, "%s",
- hv_cb_utils[cnt].log_msg);
-
- if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
- 2 * PAGE_SIZE, NULL, 0,
- hv_cb_utils[cnt].callback,
- newChannel) == 0)
- hv_cb_utils[cnt].channel = newChannel;
+ hv_cb_utils[cnt].log_msg);
+ count_hv_channel();
}
- cnt++;
}
}
DPRINT_EXIT(VMBUS);
diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
index 8a49aafea37a..2adc9b48ca9c 100644
--- a/drivers/staging/hv/hv_utils.c
+++ b/drivers/staging/hv/hv_utils.c
@@ -24,6 +24,8 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
#include "logging.h"
#include "osd.h"
@@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context)
DPRINT_EXIT(VMBUS);
}
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+ { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused = {
+ {
+ .ident = "Hyper-V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+ },
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
static int __init init_hyperv_utils(void)
{
printk(KERN_INFO "Registering HyperV Utility Driver\n");
+ if (!dmi_check_system(hv_utils_dmi_table))
+ return -ENODEV;
+
hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
&shutdown_onchannelcallback;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
index 0c6ee0f487f3..3c14b2926e00 100644
--- a/drivers/staging/hv/vmbus.h
+++ b/drivers/staging/hv/vmbus.h
@@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx);
void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
void vmbus_get_interface(struct vmbus_channel_interface *interface);
+extern struct completion hv_channel_ready;
+
#endif /* _VMBUS_H_ */
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index c21731a12ca7..22c80ece6388 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <linux/completion.h>
#include "version_info.h"
#include "osd.h"
#include "logging.h"
@@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
vmbus_drv_obj->GetChannelOffers();
+ wait_for_completion(&hv_channel_ready);
+
cleanup:
DPRINT_EXIT(VMBUS_DRV);
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
index 1db00975a594..abba22f921be 100644
--- a/drivers/staging/mrst-touchscreen/intel-mid-touch.c
+++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
@@ -817,9 +817,9 @@ static int mrstouch_remove(struct spi_device *spi)
free_irq(mrstouchdevp->irq, mrstouchdevp);
input_unregister_device(mrstouchdevp->input);
input_free_device(mrstouchdevp->input);
- kfree(mrstouchdevp);
if (mrstouchdevp->pendet_thrd)
kthread_stop(mrstouchdevp->pendet_thrd);
+ kfree(mrstouchdevp);
return 0;
}
diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c
index b740662d095a..674769d2b59b 100644
--- a/drivers/staging/rt2860/usb_main_dev.c
+++ b/drivers/staging/rt2860/usb_main_dev.c
@@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = {
{USB_DEVICE(0x083A, 0x7522)}, /* Arcadyan */
{USB_DEVICE(0x0CDE, 0x0022)}, /* ZCOM */
{USB_DEVICE(0x0586, 0x3416)}, /* Zyxel */
+ {USB_DEVICE(0x0586, 0x341a)}, /* Zyxel NWD-270N */
{USB_DEVICE(0x0CDE, 0x0025)}, /* Zyxel */
{USB_DEVICE(0x1740, 0x9701)}, /* EnGenius */
{USB_DEVICE(0x1740, 0x9702)}, /* EnGenius */
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index dacefea78113..49ab9fa9ffa7 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -66,8 +66,6 @@ static int hwseqnum = 0;
static int hwwep = 0;
static int channels = 0x3fff;
-#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c
index 447d6474a70c..1b6890611fb6 100644
--- a/drivers/staging/rtl8192su/r8192U_core.c
+++ b/drivers/staging/rtl8192su/r8192U_core.c
@@ -112,28 +112,29 @@ u32 rt_global_debug_component = \
#define CAM_CONTENT_COUNT 8
static const struct usb_device_id rtl8192_usb_id_tbl[] = {
- /* Realtek */
- {USB_DEVICE(0x0bda, 0x8171)},
- {USB_DEVICE(0x0bda, 0x8192)},
- {USB_DEVICE(0x0bda, 0x8709)},
- /* Corega */
- {USB_DEVICE(0x07aa, 0x0043)},
- /* Belkin */
- {USB_DEVICE(0x050d, 0x805E)},
- {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */
- /* Sitecom */
- {USB_DEVICE(0x0df6, 0x0031)},
- {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9201)},
- /* Dlink */
- {USB_DEVICE(0x2001, 0x3301)},
- /* Zinwell */
- {USB_DEVICE(0x5a57, 0x0290)},
- /* Guillemot */
- {USB_DEVICE(0x06f8, 0xe031)},
- //92SU
+ {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */
{USB_DEVICE(0x0bda, 0x8172)},
+ {USB_DEVICE(0x0bda, 0x8173)},
+ {USB_DEVICE(0x0bda, 0x8174)},
+ {USB_DEVICE(0x0bda, 0x8712)},
+ {USB_DEVICE(0x0bda, 0x8713)},
+ {USB_DEVICE(0x07aa, 0x0047)},
+ {USB_DEVICE(0x07d1, 0x3303)},
+ {USB_DEVICE(0x07d1, 0x3302)},
+ {USB_DEVICE(0x07d1, 0x3300)},
+ {USB_DEVICE(0x1740, 0x9603)},
+ {USB_DEVICE(0x1740, 0x9605)},
+ {USB_DEVICE(0x050d, 0x815F)},
+ {USB_DEVICE(0x06f8, 0xe031)},
+ {USB_DEVICE(0x7392, 0x7611)},
+ {USB_DEVICE(0x7392, 0x7612)},
+ {USB_DEVICE(0x7392, 0x7622)},
+ {USB_DEVICE(0x0DF6, 0x0045)},
+ {USB_DEVICE(0x0E66, 0x0015)},
+ {USB_DEVICE(0x0E66, 0x0016)},
+ {USB_DEVICE(0x0b05, 0x1786)},
+ /* these are not in the official list */
+ {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
{}
};
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 2bede271a2f0..f38472c2e75c 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = {
{USB_DEVICE(0x2001, 0x3301)},
/* Zinwell */
{USB_DEVICE(0x5a57, 0x0290)},
+ /* LG */
+ {USB_DEVICE(0x043e, 0x7a01)},
{}
};
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
index ce081cd44ad4..273e26ede650 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/staging/tm6000/tm6000-alsa.c
@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
+#include <linux/slab.h>
#include <asm/delay.h>
#include <sound/core.h>
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index cedd9044022f..6a9ae40c7c6d 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -24,6 +24,7 @@
#include <linux/i2c.h>
#include <linux/usb.h>
#include <linux/version.h>
+#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include <media/tvaudio.h>
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index 27f3f551b545..c3690e3580da 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/i2c.h>
#include "tm6000.h"
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
index 261e66acbe46..86c1c8b5f25a 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -18,6 +18,7 @@
*/
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include "tm6000.h"
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 52408164036f..6a499f0eb594 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -378,47 +378,67 @@ int usbip_thread(void *param)
complete_and_exit(&ut->thread_done, 0);
}
+static void stop_rx_thread(struct usbip_device *ud)
+{
+ if (ud->tcp_rx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+ wait_for_completion(&ud->tcp_rx.thread_done);
+ usbip_udbg("rx_thread for ud %p has finished\n", ud);
+ }
+}
+
+static void stop_tx_thread(struct usbip_device *ud)
+{
+ if (ud->tcp_tx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+ wait_for_completion(&ud->tcp_tx.thread_done);
+ usbip_udbg("tx_thread for ud %p has finished\n", ud);
+ }
+}
+
int usbip_start_threads(struct usbip_device *ud)
{
/*
* threads are invoked per one device (per one connection).
*/
struct task_struct *th;
+ int err = 0;
th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
if (IS_ERR(th)) {
printk(KERN_WARNING
"Unable to start control thread\n");
- return PTR_ERR(th);
+ err = PTR_ERR(th);
+ goto ust_exit;
}
+
th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
if (IS_ERR(th)) {
printk(KERN_WARNING
"Unable to start control thread\n");
- return PTR_ERR(th);
+ err = PTR_ERR(th);
+ goto tx_thread_err;
}
/* confirm threads are starting */
wait_for_completion(&ud->tcp_rx.thread_done);
wait_for_completion(&ud->tcp_tx.thread_done);
+
return 0;
+
+tx_thread_err:
+ stop_rx_thread(ud);
+
+ust_exit:
+ return err;
}
EXPORT_SYMBOL_GPL(usbip_start_threads);
void usbip_stop_threads(struct usbip_device *ud)
{
/* kill threads related to this sdev, if v.c. exists */
- if (ud->tcp_rx.thread != NULL) {
- send_sig(SIGKILL, ud->tcp_rx.thread, 1);
- wait_for_completion(&ud->tcp_rx.thread_done);
- usbip_udbg("rx_thread for ud %p has finished\n", ud);
- }
-
- if (ud->tcp_tx.thread != NULL) {
- send_sig(SIGKILL, ud->tcp_tx.thread, 1);
- wait_for_completion(&ud->tcp_tx.thread_done);
- usbip_udbg("tx_thread for ud %p has finished\n", ud);
- }
+ stop_rx_thread(ud);
+ stop_tx_thread(ud);
}
EXPORT_SYMBOL_GPL(usbip_stop_threads);
diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c
index 48c44c8fdb28..26cf5486edd6 100644
--- a/drivers/staging/wlags49_h2/wl_enc.c
+++ b/drivers/staging/wlags49_h2/wl_enc.c
@@ -62,6 +62,7 @@
/*******************************************************************************
* include files
******************************************************************************/
+#include <linux/string.h>
#include <wl_version.h>
#include <debug.h>
diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h
index 6d96d03cf490..fa658c38001e 100644
--- a/drivers/staging/wlags49_h2/wl_sysfs.h
+++ b/drivers/staging/wlags49_h2/wl_sysfs.h
@@ -2,6 +2,6 @@
extern void register_wlags_sysfs(struct net_device *);
extern void unregister_wlags_sysfs(struct net_device *);
#else
-static void register_wlags_sysfs(struct net_device *) { return; };
-static void unregister_wlags_sysfs(struct net_device *) { return; };
+static inline void register_wlags_sysfs(struct net_device *net) { }
+static inline void unregister_wlags_sysfs(struct net_device *net) { }
#endif
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8413a567c12d..89d260d6b031 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1596,6 +1596,7 @@ static const struct usb_device_id acm_ids[] = {
{ NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */
{ NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */
{ NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */
+ { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */
/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index de98a94d1853..a6bd53ace035 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
{
- int w, i;
- struct usb_interface *intf;
+ int w;
/* Remote wakeup is needed only when we actually go to sleep.
* For things like FREEZE and QUIESCE, if the device is already
@@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
return;
}
- /* If remote wakeup is permitted, see whether any interface drivers
+ /* Enable remote wakeup if it is allowed, even if no interface drivers
* actually want it.
*/
- w = 0;
- if (device_may_wakeup(&udev->dev) && udev->actconfig) {
- for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
- intf = udev->actconfig->interface[i];
- w |= intf->needs_remote_wakeup;
- }
- }
+ w = device_may_wakeup(&udev->dev);
/* If the device is autosuspended with the wrong wakeup setting,
* autoresume now so the setting can be changed.
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 83e7bbbe97fa..70cccc75a362 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1982,6 +1982,8 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
(portstatus & USB_PORT_STAT_ENABLE)) {
if (hub_is_wusb(hub))
udev->speed = USB_SPEED_WIRELESS;
+ else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
+ udev->speed = USB_SPEED_SUPER;
else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
udev->speed = USB_SPEED_HIGH;
else if (portstatus & USB_PORT_STAT_LOW_SPEED)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index a73e08fdab36..fd4c36ea5e46 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
/* A length of zero means transfer the whole sg list */
len = length;
if (len == 0) {
- for_each_sg(sg, sg, nents, i)
- len += sg->length;
+ struct scatterlist *sg2;
+ int j;
+
+ for_each_sg(sg, sg2, nents, j)
+ len += sg2->length;
}
} else {
/*
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index f22d03df8b17..db99c084df92 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -41,6 +41,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Philips PSC805 audio device */
{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Artisman Watchdog Dongle */
+ { USB_DEVICE(0x04b4, 0x0526), .driver_info =
+ USB_QUIRK_CONFIG_INTF_STRINGS },
+
/* Roland SC-8820 */
{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
@@ -64,6 +68,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
+ /* Broadcom BCM92035DGROM BT dongle */
+ { USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* Action Semiconductor flash disk */
{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
USB_QUIRK_STRING_FETCH_255 },
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index eaa79c8a9b8c..93ead19507b6 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -76,11 +76,12 @@
static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0";
+#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
-#define at91_udp_read(dev, reg) \
- __raw_readl((dev)->udp_baseaddr + (reg))
-#define at91_udp_write(dev, reg, val) \
- __raw_writel((val), (dev)->udp_baseaddr + (reg))
+#define at91_udp_read(udc, reg) \
+ __raw_readl((udc)->udp_baseaddr + (reg))
+#define at91_udp_write(udc, reg, val) \
+ __raw_writel((val), (udc)->udp_baseaddr + (reg))
/*-------------------------------------------------------------------------*/
@@ -102,8 +103,9 @@ static void proc_ep_show(struct seq_file *s, struct at91_ep *ep)
u32 csr;
struct at91_request *req;
unsigned long flags;
+ struct at91_udc *udc = ep->udc;
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
csr = __raw_readl(ep->creg);
@@ -147,7 +149,7 @@ static void proc_ep_show(struct seq_file *s, struct at91_ep *ep)
&req->req, length,
req->req.length, req->req.buf);
}
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
}
static void proc_irq_show(struct seq_file *s, const char *label, u32 mask)
@@ -272,7 +274,9 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)
VDBG("%s done %p, status %d\n", ep->ep.name, req, status);
ep->stopped = 1;
+ spin_unlock(&udc->lock);
req->req.complete(&ep->ep, &req->req);
+ spin_lock(&udc->lock);
ep->stopped = stopped;
/* ep0 is always ready; other endpoints need a non-empty queue */
@@ -472,7 +476,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
const struct usb_endpoint_descriptor *desc)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
- struct at91_udc *dev = ep->udc;
+ struct at91_udc *udc = ep->udc;
u16 maxpacket;
u32 tmp;
unsigned long flags;
@@ -487,7 +491,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
return -EINVAL;
}
- if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
DBG("bogus device state\n");
return -ESHUTDOWN;
}
@@ -521,7 +525,7 @@ bogus_max:
}
ok:
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
/* initialize endpoint to match this descriptor */
ep->is_in = usb_endpoint_dir_in(desc);
@@ -540,10 +544,10 @@ ok:
* reset/init endpoint fifo. NOTE: leaves fifo_bank alone,
* since endpoint resets don't reset hw pingpong state.
*/
- at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(dev, AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -556,7 +560,7 @@ static int at91_ep_disable (struct usb_ep * _ep)
if (ep == &ep->udc->ep[0])
return -EINVAL;
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
nuke(ep, -ESHUTDOWN);
@@ -571,7 +575,7 @@ static int at91_ep_disable (struct usb_ep * _ep)
__raw_writel(0, ep->creg);
}
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -607,7 +611,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
{
struct at91_request *req;
struct at91_ep *ep;
- struct at91_udc *dev;
+ struct at91_udc *udc;
int status;
unsigned long flags;
@@ -625,9 +629,9 @@ static int at91_ep_queue(struct usb_ep *_ep,
return -EINVAL;
}
- dev = ep->udc;
+ udc = ep->udc;
- if (!dev || !dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+ if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
DBG("invalid device\n");
return -EINVAL;
}
@@ -635,7 +639,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
_req->status = -EINPROGRESS;
_req->actual = 0;
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
/* try to kickstart any empty and idle queue */
if (list_empty(&ep->queue) && !ep->stopped) {
@@ -653,7 +657,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
if (is_ep0) {
u32 tmp;
- if (!dev->req_pending) {
+ if (!udc->req_pending) {
status = -EINVAL;
goto done;
}
@@ -662,11 +666,11 @@ static int at91_ep_queue(struct usb_ep *_ep,
* defer changing CONFG until after the gadget driver
* reconfigures the endpoints.
*/
- if (dev->wait_for_config_ack) {
- tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT);
+ if (udc->wait_for_config_ack) {
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp ^= AT91_UDP_CONFG;
VDBG("toggle config\n");
- at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
}
if (req->req.length == 0) {
ep0_in_status:
@@ -676,7 +680,7 @@ ep0_in_status:
tmp &= ~SET_FX;
tmp |= CLR_FX | AT91_UDP_TXPKTRDY;
__raw_writel(tmp, ep->creg);
- dev->req_pending = 0;
+ udc->req_pending = 0;
goto done;
}
}
@@ -695,31 +699,40 @@ ep0_in_status:
if (req && !status) {
list_add_tail (&req->queue, &ep->queue);
- at91_udp_write(dev, AT91_UDP_IER, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_IER, ep->int_mask);
}
done:
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return (status < 0) ? status : 0;
}
static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
{
- struct at91_ep *ep;
+ struct at91_ep *ep;
struct at91_request *req;
+ unsigned long flags;
+ struct at91_udc *udc;
ep = container_of(_ep, struct at91_ep, ep);
if (!_ep || ep->ep.name == ep0name)
return -EINVAL;
+ udc = ep->udc;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
/* make sure it's actually queued on this endpoint */
list_for_each_entry (req, &ep->queue, queue) {
if (&req->req == _req)
break;
}
- if (&req->req != _req)
+ if (&req->req != _req) {
+ spin_unlock_irqrestore(&udc->lock, flags);
return -EINVAL;
+ }
done(ep, req, -ECONNRESET);
+ spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -736,7 +749,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
return -EINVAL;
creg = ep->creg;
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
csr = __raw_readl(creg);
@@ -761,7 +774,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
__raw_writel(csr, creg);
}
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return status;
}
@@ -795,7 +808,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
unsigned long flags;
DBG("%s\n", __func__ );
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
if (!udc->clocked || !udc->suspended)
goto done;
@@ -809,7 +822,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
done:
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return status;
}
@@ -851,8 +864,11 @@ static void stop_activity(struct at91_udc *udc)
ep->stopped = 1;
nuke(ep, -ESHUTDOWN);
}
- if (driver)
+ if (driver) {
+ spin_unlock(&udc->lock);
driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+ }
udc_reinit(udc);
}
@@ -935,13 +951,13 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
unsigned long flags;
// VDBG("vbus %s\n", is_active ? "on" : "off");
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
udc->vbus = (is_active != 0);
if (udc->driver)
pullup(udc, is_active);
else
pullup(udc, 0);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -950,10 +966,10 @@ static int at91_pullup(struct usb_gadget *gadget, int is_on)
struct at91_udc *udc = to_udc(gadget);
unsigned long flags;
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
udc->enabled = is_on = !!is_on;
pullup(udc, is_on);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -962,9 +978,9 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
struct at91_udc *udc = to_udc(gadget);
unsigned long flags;
- local_irq_save(flags);
+ spin_lock_irqsave(&udc->lock, flags);
udc->selfpowered = (is_on != 0);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -1226,8 +1242,11 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
#undef w_length
/* pass request up to the gadget driver */
- if (udc->driver)
+ if (udc->driver) {
+ spin_unlock(&udc->lock);
status = udc->driver->setup(&udc->gadget, &pkt.r);
+ spin_lock(&udc->lock);
+ }
else
status = -ENODEV;
if (status < 0) {
@@ -1378,6 +1397,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
struct at91_udc *udc = _udc;
u32 rescans = 5;
int disable_clock = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&udc->lock, flags);
if (!udc->clocked) {
clk_on(udc);
@@ -1433,8 +1455,11 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
* and then into standby to avoid drawing more than
* 500uA power (2500uA for some high-power configs).
*/
- if (udc->driver && udc->driver->suspend)
+ if (udc->driver && udc->driver->suspend) {
+ spin_unlock(&udc->lock);
udc->driver->suspend(&udc->gadget);
+ spin_lock(&udc->lock);
+ }
/* host initiated resume */
} else if (status & AT91_UDP_RXRSM) {
@@ -1451,8 +1476,11 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
* would normally want to switch out of slow clock
* mode into normal mode.
*/
- if (udc->driver && udc->driver->resume)
+ if (udc->driver && udc->driver->resume) {
+ spin_unlock(&udc->lock);
udc->driver->resume(&udc->gadget);
+ spin_lock(&udc->lock);
+ }
/* endpoint IRQs are cleared by handling them */
} else {
@@ -1474,6 +1502,8 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
if (disable_clock)
clk_off(udc);
+ spin_unlock_irqrestore(&udc->lock, flags);
+
return IRQ_HANDLED;
}
@@ -1556,24 +1586,53 @@ static struct at91_udc controller = {
/* ep6 and ep7 are also reserved (custom silicon might use them) */
};
+static void at91_vbus_update(struct at91_udc *udc, unsigned value)
+{
+ value ^= udc->board.vbus_active_low;
+ if (value != udc->vbus)
+ at91_vbus_session(&udc->gadget, value);
+}
+
static irqreturn_t at91_vbus_irq(int irq, void *_udc)
{
struct at91_udc *udc = _udc;
- unsigned value;
/* vbus needs at least brief debouncing */
udelay(10);
- value = gpio_get_value(udc->board.vbus_pin);
- if (value != udc->vbus)
- at91_vbus_session(&udc->gadget, value);
+ at91_vbus_update(udc, gpio_get_value(udc->board.vbus_pin));
return IRQ_HANDLED;
}
+static void at91_vbus_timer_work(struct work_struct *work)
+{
+ struct at91_udc *udc = container_of(work, struct at91_udc,
+ vbus_timer_work);
+
+ at91_vbus_update(udc, gpio_get_value_cansleep(udc->board.vbus_pin));
+
+ if (!timer_pending(&udc->vbus_timer))
+ mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT);
+}
+
+static void at91_vbus_timer(unsigned long data)
+{
+ struct at91_udc *udc = (struct at91_udc *)data;
+
+ /*
+ * If we are polling vbus it is likely that the gpio is on an
+ * bus such as i2c or spi which may sleep, so schedule some work
+ * to read the vbus gpio
+ */
+ if (!work_pending(&udc->vbus_timer_work))
+ schedule_work(&udc->vbus_timer_work);
+}
+
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
int retval;
+ unsigned long flags;
if (!driver
|| driver->speed < USB_SPEED_FULL
@@ -1605,9 +1664,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
return retval;
}
- local_irq_disable();
+ spin_lock_irqsave(&udc->lock, flags);
pullup(udc, 1);
- local_irq_enable();
+ spin_unlock_irqrestore(&udc->lock, flags);
DBG("bound to %s\n", driver->driver.name);
return 0;
@@ -1617,15 +1676,16 @@ EXPORT_SYMBOL (usb_gadget_register_driver);
int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
+ unsigned long flags;
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
- local_irq_disable();
+ spin_lock_irqsave(&udc->lock, flags);
udc->enabled = 0;
at91_udp_write(udc, AT91_UDP_IDR, ~0);
pullup(udc, 0);
- local_irq_enable();
+ spin_unlock_irqrestore(&udc->lock, flags);
driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
@@ -1641,8 +1701,13 @@ EXPORT_SYMBOL (usb_gadget_unregister_driver);
static void at91udc_shutdown(struct platform_device *dev)
{
+ struct at91_udc *udc = platform_get_drvdata(dev);
+ unsigned long flags;
+
/* force disconnect on reboot */
+ spin_lock_irqsave(&udc->lock, flags);
pullup(platform_get_drvdata(dev), 0);
+ spin_unlock_irqrestore(&udc->lock, flags);
}
static int __init at91udc_probe(struct platform_device *pdev)
@@ -1683,6 +1748,7 @@ static int __init at91udc_probe(struct platform_device *pdev)
udc->board = *(struct at91_udc_data *) dev->platform_data;
udc->pdev = pdev;
udc->enabled = 0;
+ spin_lock_init(&udc->lock);
/* rm9200 needs manual D+ pullup; off by default */
if (cpu_is_at91rm9200()) {
@@ -1763,13 +1829,23 @@ static int __init at91udc_probe(struct platform_device *pdev)
* Get the initial state of VBUS - we cannot expect
* a pending interrupt.
*/
- udc->vbus = gpio_get_value(udc->board.vbus_pin);
- if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
- IRQF_DISABLED, driver_name, udc)) {
- DBG("request vbus irq %d failed\n",
- udc->board.vbus_pin);
- retval = -EBUSY;
- goto fail3;
+ udc->vbus = gpio_get_value_cansleep(udc->board.vbus_pin) ^
+ udc->board.vbus_active_low;
+
+ if (udc->board.vbus_polled) {
+ INIT_WORK(&udc->vbus_timer_work, at91_vbus_timer_work);
+ setup_timer(&udc->vbus_timer, at91_vbus_timer,
+ (unsigned long)udc);
+ mod_timer(&udc->vbus_timer,
+ jiffies + VBUS_POLL_TIMEOUT);
+ } else {
+ if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
+ IRQF_DISABLED, driver_name, udc)) {
+ DBG("request vbus irq %d failed\n",
+ udc->board.vbus_pin);
+ retval = -EBUSY;
+ goto fail3;
+ }
}
} else {
DBG("no VBUS detection, assuming always-on\n");
@@ -1804,13 +1880,16 @@ static int __exit at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
struct resource *res;
+ unsigned long flags;
DBG("remove\n");
if (udc->driver)
return -EBUSY;
+ spin_lock_irqsave(&udc->lock, flags);
pullup(udc, 0);
+ spin_unlock_irqrestore(&udc->lock, flags);
device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc);
@@ -1840,6 +1919,7 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
int wake = udc->driver && device_may_wakeup(&pdev->dev);
+ unsigned long flags;
/* Unless we can act normally to the host (letting it wake us up
* whenever it has work for us) force disconnect. Wakeup requires
@@ -1849,13 +1929,15 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
if ((!udc->suspended && udc->addr)
|| !wake
|| at91_suspend_entering_slow_clock()) {
+ spin_lock_irqsave(&udc->lock, flags);
pullup(udc, 0);
wake = 0;
+ spin_unlock_irqrestore(&udc->lock, flags);
} else
enable_irq_wake(udc->udp_irq);
udc->active_suspend = wake;
- if (udc->board.vbus_pin > 0 && wake)
+ if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled && wake)
enable_irq_wake(udc->board.vbus_pin);
return 0;
}
@@ -1863,15 +1945,20 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
static int at91udc_resume(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
+ unsigned long flags;
- if (udc->board.vbus_pin > 0 && udc->active_suspend)
+ if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled &&
+ udc->active_suspend)
disable_irq_wake(udc->board.vbus_pin);
/* maybe reconnect to host; if so, clocks on */
if (udc->active_suspend)
disable_irq_wake(udc->udp_irq);
- else
+ else {
+ spin_lock_irqsave(&udc->lock, flags);
pullup(udc, 1);
+ spin_unlock_irqrestore(&udc->lock, flags);
+ }
return 0;
}
#else
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index c65d62295890..108ca54f9092 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -144,6 +144,9 @@ struct at91_udc {
struct proc_dir_entry *pde;
void __iomem *udp_baseaddr;
int udp_irq;
+ spinlock_t lock;
+ struct timer_list vbus_timer;
+ struct work_struct vbus_timer_work;
};
static inline struct at91_udc *to_udc(struct usb_gadget *g)
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 38226e9a371d..95dd4662d6a8 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,
crc = get_unaligned_le32(skb->data + len
- ETH_FCS_LEN);
crc2 = ~crc32_le(~0,
- skb->data,
- skb->len - ETH_FCS_LEN);
+ skb->data, len - ETH_FCS_LEN);
} else {
crc = get_unaligned_be32(skb->data + len
- ETH_FCS_LEN);
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index d69eccf5f197..2aaa0f75c6cf 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -136,7 +136,7 @@ struct ffs_data {
* handling setup requests immidiatelly user space may be so
* slow that another setup will be sent to the gadget but this
* time not to us but another function and then there could be
- * a race. Is taht the case? Or maybe we can use cdev->req
+ * a race. Is that the case? Or maybe we can use cdev->req
* after all, maybe we just need some spinlock for that? */
struct usb_request *ep0req; /* P: mutex */
struct completion ep0req_completion; /* P: mutex */
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 7d05a0be5c60..4ce899c9b165 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -321,8 +321,8 @@ struct fsg_dev;
/* Data shared by all the FSG instances. */
struct fsg_common {
struct usb_gadget *gadget;
- struct fsg_dev *fsg;
- struct fsg_dev *prev_fsg;
+ struct fsg_dev *fsg, *new_fsg;
+ wait_queue_head_t fsg_wait;
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
@@ -351,7 +351,6 @@ struct fsg_common {
enum fsg_state state; /* For exception handling */
unsigned int exception_req_tag;
- u8 config, new_config;
enum data_direction data_dir;
u32 data_size;
u32 data_size_from_cmnd;
@@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
- if (!fsg->common->config)
+ if (!fsg_is_set(fsg->common))
return -EOPNOTSUPP;
switch (ctrl->bRequest) {
@@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
return -ENOMEM;
}
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface. The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_common *common, int altsetting)
+/* Reset interface setting and re-init endpoint state (toggle etc). */
+static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
{
- int rc = 0;
- int i;
- const struct usb_endpoint_descriptor *d;
+ const struct usb_endpoint_descriptor *d;
+ struct fsg_dev *fsg;
+ int i, rc = 0;
if (common->running)
DBG(common, "reset interface\n");
reset:
/* Deallocate the requests */
- if (common->prev_fsg) {
- struct fsg_dev *fsg = common->prev_fsg;
+ if (common->fsg) {
+ fsg = common->fsg;
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &common->buffhds[i];
@@ -2345,88 +2340,53 @@ reset:
fsg->bulk_out_enabled = 0;
}
- common->prev_fsg = 0;
+ common->fsg = NULL;
+ wake_up(&common->fsg_wait);
}
common->running = 0;
- if (altsetting < 0 || rc != 0)
+ if (!new_fsg || rc)
return rc;
- DBG(common, "set interface %d\n", altsetting);
+ common->fsg = new_fsg;
+ fsg = common->fsg;
- if (fsg_is_set(common)) {
- struct fsg_dev *fsg = common->fsg;
- common->prev_fsg = common->fsg;
+ /* Enable the endpoints */
+ d = fsg_ep_desc(common->gadget,
+ &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
+ rc = enable_endpoint(common, fsg->bulk_in, d);
+ if (rc)
+ goto reset;
+ fsg->bulk_in_enabled = 1;
+
+ d = fsg_ep_desc(common->gadget,
+ &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
+ rc = enable_endpoint(common, fsg->bulk_out, d);
+ if (rc)
+ goto reset;
+ fsg->bulk_out_enabled = 1;
+ common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+ clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
- /* Enable the endpoints */
- d = fsg_ep_desc(common->gadget,
- &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
- rc = enable_endpoint(common, fsg->bulk_in, d);
+ /* Allocate the requests */
+ for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+ struct fsg_buffhd *bh = &common->buffhds[i];
+
+ rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
if (rc)
goto reset;
- fsg->bulk_in_enabled = 1;
-
- d = fsg_ep_desc(common->gadget,
- &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
- rc = enable_endpoint(common, fsg->bulk_out, d);
+ rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
if (rc)
goto reset;
- fsg->bulk_out_enabled = 1;
- common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
- clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
- /* Allocate the requests */
- for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
- struct fsg_buffhd *bh = &common->buffhds[i];
-
- rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
- if (rc)
- goto reset;
- rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
- if (rc)
- goto reset;
- bh->inreq->buf = bh->outreq->buf = bh->buf;
- bh->inreq->context = bh->outreq->context = bh;
- bh->inreq->complete = bulk_in_complete;
- bh->outreq->complete = bulk_out_complete;
- }
-
- common->running = 1;
- for (i = 0; i < common->nluns; ++i)
- common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
- return rc;
- } else {
- return -EIO;
- }
-}
-
-
-/*
- * Change our operational configuration. This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions. Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_common *common, u8 new_config)
-{
- int rc = 0;
-
- /* Disable the single interface */
- if (common->config != 0) {
- DBG(common, "reset config\n");
- common->config = 0;
- rc = do_set_interface(common, -1);
+ bh->inreq->buf = bh->outreq->buf = bh->buf;
+ bh->inreq->context = bh->outreq->context = bh;
+ bh->inreq->complete = bulk_in_complete;
+ bh->outreq->complete = bulk_out_complete;
}
- /* Enable the interface */
- if (new_config != 0) {
- common->config = new_config;
- rc = do_set_interface(common, 0);
- if (rc != 0)
- common->config = 0; /* Reset on errors */
- }
+ common->running = 1;
+ for (i = 0; i < common->nluns; ++i)
+ common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
return rc;
}
@@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->prev_fsg = fsg->common->fsg;
- fsg->common->fsg = fsg;
- fsg->common->new_config = 1;
+ fsg->common->new_fsg = fsg;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
return 0;
}
@@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
static void fsg_disable(struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->prev_fsg = fsg->common->fsg;
- fsg->common->fsg = fsg;
- fsg->common->new_config = 0;
+ fsg->common->new_fsg = NULL;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
}
@@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)
static void handle_exception(struct fsg_common *common)
{
siginfo_t info;
- int sig;
int i;
struct fsg_buffhd *bh;
enum fsg_state old_state;
- u8 new_config;
struct fsg_lun *curlun;
unsigned int exception_req_tag;
- int rc;
/* Clear the existing signals. Anything but SIGUSR1 is converted
* into a high-priority EXIT exception. */
for (;;) {
- sig = dequeue_signal_lock(current, &current->blocked, &info);
+ int sig =
+ dequeue_signal_lock(current, &current->blocked, &info);
if (!sig)
break;
if (sig != SIGUSR1) {
@@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)
}
/* Cancel all the pending transfers */
- if (fsg_is_set(common)) {
+ if (likely(common->fsg)) {
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
bh = &common->buffhds[i];
if (bh->inreq_busy)
@@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)
common->next_buffhd_to_fill = &common->buffhds[0];
common->next_buffhd_to_drain = &common->buffhds[0];
exception_req_tag = common->exception_req_tag;
- new_config = common->new_config;
old_state = common->state;
if (old_state == FSG_STATE_ABORT_BULK_OUT)
@@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)
break;
case FSG_STATE_CONFIG_CHANGE:
- rc = do_set_config(common, new_config);
+ do_set_interface(common, common->new_fsg);
break;
case FSG_STATE_EXIT:
case FSG_STATE_TERMINATED:
- do_set_config(common, 0); /* Free resources */
+ do_set_interface(common, NULL); /* Free resources */
spin_lock_irq(&common->lock);
common->state = FSG_STATE_TERMINATED; /* Stop the thread */
spin_unlock_irq(&common->lock);
@@ -2863,6 +2816,7 @@ buffhds_first_it:
goto error_release;
}
init_completion(&common->thread_notifier);
+ init_waitqueue_head(&common->fsg_wait);
#undef OR
@@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)
static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
+ struct fsg_common *common = fsg->common;
DBG(fsg, "unbind\n");
- fsg_common_put(fsg->common);
+ if (fsg->common->fsg == fsg) {
+ fsg->common->new_fsg = NULL;
+ raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+ /* FIXME: make interruptible or killable somehow? */
+ wait_event(common->fsg_wait, common->fsg != fsg);
+ }
+
+ fsg_common_put(common);
usb_free_descriptors(fsg->function.descriptors);
usb_free_descriptors(fsg->function.hs_descriptors);
kfree(fsg);
@@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
- int rc;
int i;
struct usb_ep *ep;
@@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
+ /* Copy descriptors */
+ f->descriptors = usb_copy_descriptors(fsg_fs_function);
+ if (unlikely(!f->descriptors))
+ return -ENOMEM;
+
if (gadget_is_dualspeed(gadget)) {
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
- if (unlikely(!f->hs_descriptors))
+ if (unlikely(!f->hs_descriptors)) {
+ usb_free_descriptors(f->descriptors);
return -ENOMEM;
+ }
}
return 0;
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
- rc = -ENOTSUPP;
- return rc;
+ return -ENOTSUPP;
}
@@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,
fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
- fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
- if (unlikely(!fsg->function.descriptors)) {
- rc = -ENOMEM;
- goto error_free_fsg;
- }
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
fsg->function.setup = fsg_setup;
@@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,
rc = usb_add_function(c, &fsg->function);
if (unlikely(rc))
- goto error_free_all;
-
- fsg_common_get(fsg->common);
- return 0;
-
-error_free_all:
- usb_free_descriptors(fsg->function.descriptors);
- /* fsg_bind() might have copied those; or maybe not? who cares
- * -- free it just in case. */
- usb_free_descriptors(fsg->function.hs_descriptors);
-error_free_fsg:
- kfree(fsg);
-
+ kfree(fsg);
+ else
+ fsg_common_get(fsg->common);
return rc;
}
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index fc2611f8b326..dbe6db0184fd 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -28,7 +28,7 @@
#include "uvc.h"
-unsigned int uvc_trace_param;
+unsigned int uvc_gadget_trace_param;
/* --------------------------------------------------------------------------
* Function descriptors
@@ -656,6 +656,6 @@ error:
return ret;
}
-module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
+module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask");
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index d0b8bde59e59..eafa6d2c5ed7 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -30,7 +30,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
- if (!cpu_is_mx35()) {
+ if (!cpu_is_mx35() && !cpu_is_mx25()) {
mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
if (IS_ERR(mxc_ahb_clk))
return PTR_ERR(mxc_ahb_clk);
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 4b0e4a040d6f..d1af253a9105 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,
if (unlikely(ret < 0))
return ret;
+ /* After previous do_configs there may be some invalid
+ * pointers in c->interface array. This happens every time
+ * a user space function with fewer interfaces than a user
+ * space function that was run before the new one is run. The
+ * compasit's set_config() assumes that if there is no more
+ * then MAX_CONFIG_INTERFACES interfaces in a configuration
+ * then there is a NULL pointer after the last interface in
+ * c->interface array. We need to make sure this is true. */
+ if (c->next_interface_id < ARRAY_SIZE(c->interface))
+ c->interface[c->next_interface_id] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 43abf55d8c60..4c3ac5c42237 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
struct printer_dev {
spinlock_t lock; /* lock this structure */
/* lock buffer lists during read/write calls */
- spinlock_t lock_printer_io;
+ struct mutex lock_printer_io;
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
u8 config;
@@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
/* We will use this flag later to check if a printer reset happened
@@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
* call or not.
*/
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
if (dev->reset_printer) {
list_add(&current_rx_req->list, &dev->rx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
dev->current_rx_buf = current_rx_buf;
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
@@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (len == 0)
return -EINVAL;
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
/* Check if a printer reset happens while we have interrupts on */
@@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
* a NON-Blocking call or not.
*/
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (copy_from_user(req->buf, buf, size)) {
list_add(&req->list, &dev->tx_reqs);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return bytes_copied;
}
@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (dev->reset_printer) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
}
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
unsigned long flags;
int status = 0;
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
setup_rx_reqs(dev);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
poll_wait(fd, &dev->rx_wait, wait);
poll_wait(fd, &dev->tx_wait, wait);
@@ -1461,7 +1461,7 @@ autoconf_fail:
}
spin_lock_init(&dev->lock);
- spin_lock_init(&dev->lock_printer_io);
+ mutex_init(&dev->lock_printer_io);
INIT_LIST_HEAD(&dev->tx_reqs);
INIT_LIST_HEAD(&dev->tx_reqs_active);
INIT_LIST_HEAD(&dev->rx_reqs);
@@ -1594,7 +1594,7 @@ cleanup(void)
{
int status;
- spin_lock(&usb_printer_gadget.lock_printer_io);
+ mutex_lock(&usb_printer_gadget.lock_printer_io);
class_destroy(usb_gadget_class);
unregister_chrdev_region(g_printer_devno, 2);
@@ -1602,6 +1602,6 @@ cleanup(void)
if (status)
ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
- spin_unlock(&usb_printer_gadget.lock_printer_io);
+ mutex_unlock(&usb_printer_gadget.lock_printer_io);
}
module_exit(cleanup);
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 85b0d8921eae..980762453a9c 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -2561,7 +2561,7 @@ static void pxa_udc_shutdown(struct platform_device *_dev)
udc_disable(udc);
}
-#ifdef CONFIG_CPU_PXA27x
+#ifdef CONFIG_PXA27x
extern void pxa27x_clear_otgph(void);
#else
#define pxa27x_clear_otgph() do {} while (0)
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index d5f4c1d45c97..ea2b3c7ebee5 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -735,6 +735,10 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
else
dev->ep0state = EP0_OUT_DATA_PHASE;
+ if (!dev->driver)
+ return;
+
+ /* deliver the request to the gadget driver */
ret = dev->driver->setup(&dev->gadget, crq);
if (ret < 0) {
if (dev->req_config) {
@@ -1700,9 +1704,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
- dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+ dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
driver->driver.name);
+ /* report disconnect */
+ if (driver->disconnect)
+ driver->disconnect(&udc->gadget);
+
driver->unbind(&udc->gadget);
device_del(&udc->gadget.dev);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 16bdf77f582a..3e8dcb5455e3 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -536,17 +536,11 @@ recycle:
list_move(&req->list, &port->read_pool);
}
- /* Push from tty to ldisc; this is immediate with low_latency, and
- * may trigger callbacks to this driver ... so drop the spinlock.
+ /* Push from tty to ldisc; without low_latency set this is handled by
+ * a workqueue, so we won't get callbacks and can hold port_lock
*/
if (tty && do_push) {
- spin_unlock_irq(&port->port_lock);
tty_flip_buffer_push(tty);
- wake_up_interruptible(&tty->read_wait);
- spin_lock_irq(&port->port_lock);
-
- /* tty may have been closed */
- tty = port->port_tty;
}
@@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file)
port->open_count = 1;
port->openclose = false;
- /* low_latency means ldiscs work in tasklet context, without
- * needing a workqueue schedule ... easier to keep up.
- */
- tty->low_latency = 1;
-
/* if connected, start the I/O stream */
if (port->port_usb) {
struct gserial *gser = port->port_usb;
@@ -1195,6 +1184,7 @@ void gserial_cleanup(void)
n_ports = 0;
tty_unregister_driver(gs_tty_driver);
+ put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
pr_debug("%s: cleaned up ttyGS* support\n", __func__);
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h
index 0a705e63c936..e92454cddd7d 100644
--- a/drivers/usb/gadget/uvc.h
+++ b/drivers/usb/gadget/uvc.h
@@ -107,11 +107,11 @@ struct uvc_streaming_control {
#define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1
-extern unsigned int uvc_trace_param;
+extern unsigned int uvc_gadget_trace_param;
#define uvc_trace(flag, msg...) \
do { \
- if (uvc_trace_param & flag) \
+ if (uvc_gadget_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
@@ -220,16 +220,10 @@ struct uvc_file_handle
#define to_uvc_file_handle(handle) \
container_of(handle, struct uvc_file_handle, vfh)
-extern struct v4l2_file_operations uvc_v4l2_fops;
-
/* ------------------------------------------------------------------------
* Functions
*/
-extern int uvc_video_enable(struct uvc_video *video, int enable);
-extern int uvc_video_init(struct uvc_video *video);
-extern int uvc_video_pump(struct uvc_video *video);
-
extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c
index 43891991bf21..f7395ac5dc17 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/uvc_queue.c
@@ -78,7 +78,8 @@
*
*/
-void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
+static void
+uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
{
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
@@ -88,6 +89,28 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
}
/*
+ * Free the video buffers.
+ *
+ * This function must be called with the queue lock held.
+ */
+static int uvc_free_buffers(struct uvc_video_queue *queue)
+{
+ unsigned int i;
+
+ for (i = 0; i < queue->count; ++i) {
+ if (queue->buffer[i].vma_use_count != 0)
+ return -EBUSY;
+ }
+
+ if (queue->count) {
+ vfree(queue->mem);
+ queue->count = 0;
+ }
+
+ return 0;
+}
+
+/*
* Allocate the video buffers.
*
* Pages are reserved to make sure they will not be swapped, as they will be
@@ -95,8 +118,9 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
*
* Buffers will be individually mapped, so they must all be page aligned.
*/
-int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
- unsigned int buflength)
+static int
+uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
+ unsigned int buflength)
{
unsigned int bufsize = PAGE_ALIGN(buflength);
unsigned int i;
@@ -150,28 +174,6 @@ done:
return ret;
}
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
- */
-int uvc_free_buffers(struct uvc_video_queue *queue)
-{
- unsigned int i;
-
- for (i = 0; i < queue->count; ++i) {
- if (queue->buffer[i].vma_use_count != 0)
- return -EBUSY;
- }
-
- if (queue->count) {
- vfree(queue->mem);
- queue->count = 0;
- }
-
- return 0;
-}
-
static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf)
{
@@ -195,8 +197,8 @@ static void __uvc_query_buffer(struct uvc_buffer *buf,
}
}
-int uvc_query_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf)
+static int
+uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{
int ret = 0;
@@ -217,8 +219,8 @@ done:
* Queue a video buffer. Attempting to queue a buffer that has already been
* queued will return -EINVAL.
*/
-int uvc_queue_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf)
+static int
+uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{
struct uvc_buffer *buf;
unsigned long flags;
@@ -298,8 +300,9 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available.
*/
-int uvc_dequeue_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf, int nonblocking)
+static int
+uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
+ int nonblocking)
{
struct uvc_buffer *buf;
int ret = 0;
@@ -359,8 +362,9 @@ done:
* This function implements video queue polling and is intended to be used by
* the device poll handler.
*/
-unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
- poll_table *wait)
+static unsigned int
+uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
+ poll_table *wait)
{
struct uvc_buffer *buf;
unsigned int mask = 0;
@@ -407,7 +411,8 @@ static struct vm_operations_struct uvc_vm_ops = {
* This function implements video buffer memory mapping and is intended to be
* used by the device mmap handler.
*/
-int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+static int
+uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
@@ -458,6 +463,42 @@ done:
}
/*
+ * Cancel the video buffers queue.
+ *
+ * Cancelling the queue marks all buffers on the irq queue as erroneous,
+ * wakes them up and removes them from the queue.
+ *
+ * If the disconnect parameter is set, further calls to uvc_queue_buffer will
+ * fail with -ENODEV.
+ *
+ * This function acquires the irq spinlock and can be called from interrupt
+ * context.
+ */
+static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
+{
+ struct uvc_buffer *buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->irqlock, flags);
+ while (!list_empty(&queue->irqqueue)) {
+ buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+ queue);
+ list_del(&buf->queue);
+ buf->state = UVC_BUF_STATE_ERROR;
+ wake_up(&buf->wait);
+ }
+ /* This must be protected by the irqlock spinlock to avoid race
+ * conditions between uvc_queue_buffer and the disconnection event that
+ * could result in an interruptible wait in uvc_dequeue_buffer. Do not
+ * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
+ * state outside the queue code.
+ */
+ if (disconnect)
+ queue->flags |= UVC_QUEUE_DISCONNECTED;
+ spin_unlock_irqrestore(&queue->irqlock, flags);
+}
+
+/*
* Enable or disable the video buffers queue.
*
* The queue must be enabled before starting video acquisition and must be
@@ -474,7 +515,7 @@ done:
* This function can't be called from interrupt context. Use
* uvc_queue_cancel() instead.
*/
-int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
+static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
unsigned int i;
int ret = 0;
@@ -503,44 +544,8 @@ done:
return ret;
}
-/*
- * Cancel the video buffers queue.
- *
- * Cancelling the queue marks all buffers on the irq queue as erroneous,
- * wakes them up and removes them from the queue.
- *
- * If the disconnect parameter is set, further calls to uvc_queue_buffer will
- * fail with -ENODEV.
- *
- * This function acquires the irq spinlock and can be called from interrupt
- * context.
- */
-void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
-{
- struct uvc_buffer *buf;
- unsigned long flags;
-
- spin_lock_irqsave(&queue->irqlock, flags);
- while (!list_empty(&queue->irqqueue)) {
- buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
- queue);
- list_del(&buf->queue);
- buf->state = UVC_BUF_STATE_ERROR;
- wake_up(&buf->wait);
- }
- /* This must be protected by the irqlock spinlock to avoid race
- * conditions between uvc_queue_buffer and the disconnection event that
- * could result in an interruptible wait in uvc_dequeue_buffer. Do not
- * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
- * state outside the queue code.
- */
- if (disconnect)
- queue->flags |= UVC_QUEUE_DISCONNECTED;
- spin_unlock_irqrestore(&queue->irqlock, flags);
-}
-
-struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
- struct uvc_buffer *buf)
+static struct uvc_buffer *
+uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
unsigned long flags;
@@ -568,7 +573,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
return nextbuf;
}
-struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
+static struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
{
struct uvc_buffer *buf = NULL;
diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h
index 7f5a33fe7ae2..1812a8ecc5d0 100644
--- a/drivers/usb/gadget/uvc_queue.h
+++ b/drivers/usb/gadget/uvc_queue.h
@@ -58,30 +58,10 @@ struct uvc_video_queue {
struct list_head irqqueue;
};
-extern void uvc_queue_init(struct uvc_video_queue *queue,
- enum v4l2_buf_type type);
-extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
- unsigned int nbuffers, unsigned int buflength);
-extern int uvc_free_buffers(struct uvc_video_queue *queue);
-extern int uvc_query_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf);
-extern int uvc_queue_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf);
-extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf, int nonblocking);
-extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
-extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
-extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
- struct uvc_buffer *buf);
-extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
- struct file *file, poll_table *wait);
-extern int uvc_queue_mmap(struct uvc_video_queue *queue,
- struct vm_area_struct *vma);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
return queue->flags & UVC_QUEUE_STREAMING;
}
-extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue);
#endif /* __KERNEL__ */
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index a7989f29837e..2dcffdac86d2 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/uvc_v4l2.c
@@ -363,7 +363,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
return mask;
}
-struct v4l2_file_operations uvc_v4l2_fops = {
+static struct v4l2_file_operations uvc_v4l2_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c
index de8cbc46518d..b08f35438d70 100644
--- a/drivers/usb/gadget/uvc_video.c
+++ b/drivers/usb/gadget/uvc_video.c
@@ -271,7 +271,7 @@ error:
* This function fills the available USB requests (listed in req_free) with
* video data from the queued buffers.
*/
-int
+static int
uvc_video_pump(struct uvc_video *video)
{
struct usb_request *req;
@@ -328,7 +328,7 @@ uvc_video_pump(struct uvc_video *video)
/*
* Enable or disable the video stream.
*/
-int
+static int
uvc_video_enable(struct uvc_video *video, int enable)
{
unsigned int i;
@@ -367,7 +367,7 @@ uvc_video_enable(struct uvc_video *video, int enable)
/*
* Initialize the UVC video stream.
*/
-int
+static int
uvc_video_init(struct uvc_video *video)
{
INIT_LIST_HEAD(&video->req_free);
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index 417fd6887698..f5f3030cc416 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -28,10 +28,10 @@
#include "config.c"
#include "epautoconf.c"
-#include "f_uvc.c"
#include "uvc_queue.c"
-#include "uvc_v4l2.c"
#include "uvc_video.c"
+#include "uvc_v4l2.c"
+#include "f_uvc.c"
/* --------------------------------------------------------------------------
* Device descriptor
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 544ccfd7056e..a8ad8ac120a2 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -182,7 +182,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
}
clk_enable(priv->usbclk);
- if (!cpu_is_mx35()) {
+ if (!cpu_is_mx35() && !cpu_is_mx25()) {
priv->ahbclk = clk_get(dev, "usb_ahb");
if (IS_ERR(priv->ahbclk)) {
ret = PTR_ERR(priv->ahbclk);
@@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
/* Initialize the transceiver */
if (pdata->otg) {
pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
- if (otg_init(pdata->otg) != 0)
- dev_err(dev, "unable to init transceiver\n");
- else if (otg_set_vbus(pdata->otg, 1) != 0)
+ ret = otg_init(pdata->otg);
+ if (ret) {
+ dev_err(dev, "unable to init transceiver, probably missing\n");
+ ret = -ENODEV;
+ goto err_add;
+ }
+ ret = otg_set_vbus(pdata->otg, 1);
+ if (ret) {
dev_err(dev, "unable to enable vbus on transceiver\n");
+ goto err_add;
+ }
}
priv->hcd = hcd;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 20a0dfe0fe36..0587ad4ce5c2 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
/*-------------------------------------------------------------------------*/
-static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
{
int tmp = 20;
- unsigned long flags;
-
- spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
@@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
}
if (!tmp)
pr_err("Software reset timeout\n");
+}
+
+static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&isp1362_hcd->lock, flags);
+ __isp1362_sw_reset(isp1362_hcd);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
}
@@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd)
if (isp1362_hcd->board && isp1362_hcd->board->reset)
isp1362_hcd->board->reset(hcd->self.controller, 1);
else
- isp1362_sw_reset(isp1362_hcd);
+ __isp1362_sw_reset(isp1362_hcd);
if (isp1362_hcd->board && isp1362_hcd->board->clock)
isp1362_hcd->board->clock(hcd->self.controller, 0);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index a18debdd79b8..418163894775 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -203,7 +203,7 @@ static inline void pxa27x_reset_hc(struct pxa27x_ohci *ohci)
__raw_writel(uhchr & ~UHCHR_FHR, ohci->mmio_base + UHCHR);
}
-#ifdef CONFIG_CPU_PXA27x
+#ifdef CONFIG_PXA27x
extern void pxa27x_clear_otgph(void);
#else
#define pxa27x_clear_otgph() do {} while (0)
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 1a2bb4ce638f..77be3c24a427 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
else if (speed == LSMODE)
rh->port |= USB_PORT_STAT_LOW_SPEED;
- rh->port &= USB_PORT_STAT_RESET;
+ rh->port &= ~USB_PORT_STAT_RESET;
rh->port |= USB_PORT_STAT_ENABLE;
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index fd9e03afd91c..2eb658d26394 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -835,6 +835,27 @@ fail:
return 0;
}
+void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
+ struct usb_device *udev)
+{
+ struct xhci_virt_device *virt_dev;
+ struct xhci_ep_ctx *ep0_ctx;
+ struct xhci_ring *ep_ring;
+
+ virt_dev = xhci->devs[udev->slot_id];
+ ep0_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, 0);
+ ep_ring = virt_dev->eps[0].ring;
+ /*
+ * FIXME we don't keep track of the dequeue pointer very well after a
+ * Set TR dequeue pointer, so we're setting the dequeue pointer of the
+ * host to our enqueue pointer. This should only be called after a
+ * configured device has reset, so all control transfers should have
+ * been completed or cancelled before the reset.
+ */
+ ep0_ctx->deq = xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue);
+ ep0_ctx->deq |= ep_ring->cycle_state;
+}
+
/* Setup an xHCI virtual device for a Set Address command */
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev)
{
@@ -1002,7 +1023,7 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
return EP_INTERVAL(interval);
}
-/* The "Mult" field in the endpoint context is only set for SuperSpeed devices.
+/* The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
* High speed endpoint descriptors can define "the number of additional
* transaction opportunities per microframe", but that goes in the Max Burst
* endpoint context field.
@@ -1010,7 +1031,8 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
static inline u32 xhci_get_endpoint_mult(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
- if (udev->speed != USB_SPEED_SUPER)
+ if (udev->speed != USB_SPEED_SUPER ||
+ !usb_endpoint_xfer_isoc(&ep->desc))
return 0;
return ep->ss_ep_comp.bmAttributes;
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 9012098add6b..bfc99a939455 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
* 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.
+ *
+ * @more_trbs_coming: Will you enqueue more TRBs before calling
+ * prepare_transfer()?
*/
-static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
+ bool consumer, bool more_trbs_coming)
{
u32 chain;
union xhci_trb *next;
@@ -199,15 +203,28 @@ 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) {
- if (chain) {
- next->link.control |= TRB_CHAIN;
-
- /* Give this link TRB to the hardware */
- wmb();
- next->link.control ^= TRB_CYCLE;
- } else {
+ /*
+ * If the caller doesn't plan on enqueueing more
+ * TDs before ringing the doorbell, then we
+ * don't want to give the link TRB to the
+ * hardware just yet. We'll give the link TRB
+ * back in prepare_ring() just before we enqueue
+ * the TD at the top of the ring.
+ */
+ if (!chain && !more_trbs_coming)
break;
+
+ /* 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();
+ next->link.control ^= TRB_CYCLE;
}
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -1707,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci)
/*
* Generic function for queueing a TRB on a ring.
* The caller must have checked to make sure there's room on the ring.
+ *
+ * @more_trbs_coming: Will you enqueue more TRBs before calling
+ * prepare_transfer()?
*/
static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
- bool consumer,
+ bool consumer, bool more_trbs_coming,
u32 field1, u32 field2, u32 field3, u32 field4)
{
struct xhci_generic_trb *trb;
@@ -1719,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
trb->field[1] = field2;
trb->field[2] = field3;
trb->field[3] = field4;
- inc_enq(xhci, ring, consumer);
+ inc_enq(xhci, ring, consumer, more_trbs_coming);
}
/*
@@ -1988,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
int trb_buff_len, this_sg_len, running_total;
bool first_trb;
u64 addr;
+ bool more_trbs_coming;
struct xhci_generic_trb *start_trb;
int start_cycle;
@@ -2073,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
length_field = TRB_LEN(trb_buff_len) |
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false,
+ if (num_trbs > 1)
+ more_trbs_coming = true;
+ else
+ more_trbs_coming = false;
+ queue_trb(xhci, ep_ring, false, more_trbs_coming,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
@@ -2124,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
int num_trbs;
struct xhci_generic_trb *start_trb;
bool first_trb;
+ bool more_trbs_coming;
int start_cycle;
u32 field, length_field;
@@ -2212,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
length_field = TRB_LEN(trb_buff_len) |
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false,
+ if (num_trbs > 1)
+ more_trbs_coming = true;
+ else
+ more_trbs_coming = false;
+ queue_trb(xhci, ep_ring, false, more_trbs_coming,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
@@ -2291,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
/* Queue setup TRB - see section 6.4.1.2.1 */
/* FIXME better way to translate setup_packet into two u32 fields? */
setup = (struct usb_ctrlrequest *) urb->setup_packet;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, true,
/* FIXME endianness is probably going to bite my ass here. */
setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
setup->wIndex | setup->wLength << 16,
@@ -2307,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_buffer_length > 0) {
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, true,
lower_32_bits(urb->transfer_dma),
upper_32_bits(urb->transfer_dma),
length_field,
@@ -2324,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field = 0;
else
field = TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, false,
0,
0,
TRB_INTR_TARGET(0),
@@ -2350,18 +2380,21 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
u32 field3, u32 field4, bool command_must_succeed)
{
int reserved_trbs = xhci->cmd_ring_reserved_trbs;
+ int ret;
+
if (!command_must_succeed)
reserved_trbs++;
- if (!room_on_ring(xhci, xhci->cmd_ring, reserved_trbs)) {
- if (!in_interrupt())
- xhci_err(xhci, "ERR: No room for command on command ring\n");
+ ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING,
+ reserved_trbs, GFP_ATOMIC);
+ if (ret < 0) {
+ xhci_err(xhci, "ERR: No room for command on command ring\n");
if (command_must_succeed)
xhci_err(xhci, "ERR: Reserved TRB counting for "
"unfailable commands failed.\n");
- return -ENOMEM;
+ return ret;
}
- queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
+ queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
field4 | xhci->cmd_ring->cycle_state);
return 0;
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 27345cd04da0..3998f72cd0c4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2134,6 +2134,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
/* If this is a Set Address to an unconfigured device, setup ep 0 */
if (!udev->config)
xhci_setup_addressable_virt_dev(xhci, udev);
+ else
+ xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
/* Otherwise, assume the core has the device configured how it wants */
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8b4b7d39f79c..6c7e3430ec93 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1292,6 +1292,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags);
void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags);
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
+void xhci_copy_ep0_dequeue_into_input_ctx(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);
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 30d930386b65..d25814c172b2 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2436,7 +2436,8 @@ sisusb_open(struct inode *inode, struct file *file)
}
if (!sisusb->devinit) {
- if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
+ if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
+ sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {
if (sisusb_init_gfxdevice(sisusb, 0)) {
mutex_unlock(&sisusb->lock);
dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
@@ -3166,7 +3167,7 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->present = 1;
- if (dev->speed == USB_SPEED_HIGH) {
+ if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
int initscreen = 1;
#ifdef INCL_SISUSB_CON
if (sisusb_first_vc > 0 &&
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index fad70bc83555..3b795c56221f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg,
return 0;
}
#else
-#define musb_ulpi_read(a, b) NULL
-#define musb_ulpi_write(a, b, c) NULL
+#define musb_ulpi_read NULL
+#define musb_ulpi_write NULL
#endif
static struct otg_io_access_ops musb_ulpi_access = {
@@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb)
* @param power
*/
-#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
- | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
- | MUSB_INTR_RESET)
-
static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
u8 devctl, u8 power)
{
@@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
handled = IRQ_HANDLED;
}
-
+#endif
if (int_usb & MUSB_INTR_SUSPEND) {
DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
otg_state_string(musb), devctl, power);
@@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
}
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (int_usb & MUSB_INTR_CONNECT) {
struct usb_hcd *hcd = musb_to_hcd(musb);
void __iomem *mbase = musb->mregs;
@@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
/* the core can interrupt us for multiple reasons; docs have
* a generic interrupt flowchart to follow
*/
- if (musb->int_usb & STAGE0_MASK)
+ if (musb->int_usb)
retval |= musb_stage0_irq(musb, musb->int_usb,
devctl, power);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index b22d02dea7d3..91d67794e350 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -470,7 +470,8 @@ struct musb_csr_regs {
struct musb_context_registers {
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_ARCH_OMAP4)
u32 otg_sysconfig, otg_forcestandby;
#endif
u8 power;
@@ -484,7 +485,8 @@ struct musb_context_registers {
struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
};
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_ARCH_OMAP4)
extern void musb_platform_save_context(struct musb *musb,
struct musb_context_registers *musb_context);
extern void musb_platform_restore_context(struct musb *musb,
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 1008044a3bbc..dc66e4376d49 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel,
if (mode) {
csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
BUG_ON(len < packet_sz);
-
- if (packet_sz >= 64) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR16
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- } else if (packet_sz >= 32) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR8
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- } else if (packet_sz >= 16) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR4
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- }
}
+ csr |= MUSB_HSDMA_BURSTMODE_INCR16
+ << MUSB_HSDMA_BURSTMODE_SHIFT;
csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
| (1 << MUSB_HSDMA_ENABLE_SHIFT)
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 05c077f8f9ac..3c48e77a0aa2 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -29,19 +29,6 @@ static void tusb_source_power(struct musb *musb, int is_on);
#define TUSB_REV_MAJOR(reg_val) ((reg_val >> 4) & 0xf)
#define TUSB_REV_MINOR(reg_val) (reg_val & 0xf)
-#ifdef CONFIG_PM
-/* REVISIT: These should be only needed if somebody implements off idle */
-void musb_platform_save_context(struct musb *musb,
- struct musb_context_registers *musb_context)
-{
-}
-
-void musb_platform_restore_context(struct musb *musb,
- struct musb_context_registers *musb_context)
-{
-}
-#endif
-
/*
* Checks the revision. We need to use the DMA register as 3.0 does not
* have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV.
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index b1b346932946..d331b222ad21 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
static int ulpi_init(struct otg_transceiver *otg)
{
- int i, vid, pid;
-
- vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) |
- otg_io_read(otg, ULPI_VENDOR_ID_LOW);
- pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) |
- otg_io_read(otg, ULPI_PRODUCT_ID_LOW);
+ int i, vid, pid, ret;
+ u32 ulpi_id = 0;
+
+ for (i = 0; i < 4; i++) {
+ ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
+ if (ret < 0)
+ return ret;
+ ulpi_id = (ulpi_id << 8) | ret;
+ }
+ vid = ulpi_id & 0xffff;
+ pid = ulpi_id >> 16;
pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 79dd1ae195e5..e298dc4baed7 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
- { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
@@ -692,6 +691,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
@@ -738,6 +738,14 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
{ USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) },
{ USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) },
+ { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 94d86c3febcb..d01946db8fac 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -501,13 +501,6 @@
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
- * Contec products (http://www.contec.com)
- * Submitted by Daniel Sangorrin
- */
-#define CONTEC_VID 0x06CE /* Vendor ID */
-#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
-
-/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
@@ -703,6 +696,12 @@
#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */
/*
+ * RT Systems programming cables for various ham radios
+ */
+#define RTSYSTEMS_VID 0x2100 /* Vendor ID */
+#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */
+
+/*
* Bayer Ascensia Contour blood glucose meter USB-converter cable.
* http://winglucofacts.com/cables/
*/
@@ -1024,3 +1023,12 @@
#define MJSG_SR_RADIO_PID 0x9379
#define MJSG_XM_RADIO_PID 0x937A
#define MJSG_HD_RADIO_PID 0x937C
+
+/*
+ * Xverve Signalyzer tools (http://www.signalyzer.com/)
+ */
+#define XVERVE_SIGNALYZER_ST_PID 0xBCA0
+#define XVERVE_SIGNALYZER_SLITE_PID 0xBCA1
+#define XVERVE_SIGNALYZER_SH2_PID 0xBCA2
+#define XVERVE_SIGNALYZER_SH4_PID 0xBCA4
+
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index e280ad8e12f7..5cd30e4345c6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -206,6 +206,7 @@ static void option_instat_callback(struct urb *urb);
#define AMOI_PRODUCT_H01 0x0800
#define AMOI_PRODUCT_H01A 0x7002
#define AMOI_PRODUCT_H02 0x0802
+#define AMOI_PRODUCT_SKYPEPHONE_S2 0x0407
#define DELL_VENDOR_ID 0x413C
@@ -302,6 +303,7 @@ static void option_instat_callback(struct urb *urb);
#define QISDA_PRODUCT_H21_4512 0x4512
#define QISDA_PRODUCT_H21_4523 0x4523
#define QISDA_PRODUCT_H20_4515 0x4515
+#define QISDA_PRODUCT_H20_4518 0x4518
#define QISDA_PRODUCT_H20_4519 0x4519
/* TLAYTECH PRODUCTS */
@@ -516,6 +518,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) },
+ { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_SKYPEPHONE_S2) },
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_MINICARD) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5500_MINICARD) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
@@ -852,6 +855,7 @@ static const struct usb_device_id option_ids[] = {
{ 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_4518) },
{ 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 */
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 04bb759536bb..cde67cacb2c3 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -51,6 +51,8 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
{USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */
{USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
+ {USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */
+ {USB_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */
{USB_DEVICE(0x05c6, 0x9224)}, /* Sony Gobi 2000 QDL device (N0279, VU730) */
{USB_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */
{USB_DEVICE(0x05c6, 0x9244)}, /* Samsung Gobi 2000 QDL device (VL176) */
@@ -139,6 +141,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
+ kfree(data);
}
return retval;
}
@@ -155,6 +158,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
+ kfree(data);
}
return retval;
}
@@ -163,6 +167,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
default:
dev_err(&serial->dev->dev,
"unknown number of interfaces: %d\n", nintf);
+ kfree(data);
return -ENODEV;
}
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index ef0bdb08d788..d47b56e9e8ce 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -245,6 +245,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
{ USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
+ { USB_DEVICE(0x1199, 0x0301) }, /* Sierra Wireless USB Dongle 250U */
/* Sierra Wireless C597 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
/* Sierra Wireless T598 */
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 44716427c51c..64ec073e89de 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -139,9 +139,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
/* fill the common fields in the URB */
us->current_urb->context = &urb_done;
- us->current_urb->actual_length = 0;
- us->current_urb->error_count = 0;
- us->current_urb->status = 0;
+ us->current_urb->transfer_flags = 0;
/* we assume that if transfer_buffer isn't us->iobuf then it
* hasn't been mapped for DMA. Yes, this is clunky, but it's
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index df5b6b971f26..d219070fed3d 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
static void handle_tx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
- unsigned head, out, in, s;
+ unsigned out, in, s;
+ int head;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
@@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net)
ARRAY_SIZE(vq->iov),
&out, &in,
NULL, NULL);
+ /* On error, stop handling until the next kick. */
+ if (unlikely(head < 0))
+ break;
/* Nothing new? Wait for eventfd to tell us they refilled. */
if (head == vq->num) {
wmem = atomic_read(&sock->sk->sk_wmem_alloc);
@@ -173,8 +177,8 @@ static void handle_tx(struct vhost_net *net)
break;
}
if (err != len)
- pr_err("Truncated TX packet: "
- " len %d != %zd\n", err, len);
+ pr_debug("Truncated TX packet: "
+ " len %d != %zd\n", err, len);
vhost_add_used_and_signal(&net->dev, vq, head, 0);
total_len += len;
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
@@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net)
static void handle_rx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
- unsigned head, out, in, log, s;
+ unsigned out, in, log, s;
+ int head;
struct vhost_log *vq_log;
struct msghdr msg = {
.msg_name = NULL,
@@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net)
ARRAY_SIZE(vq->iov),
&out, &in,
vq_log, &log);
+ /* On error, stop handling until the next kick. */
+ if (unlikely(head < 0))
+ break;
/* OK, now we need to know about added descriptors. */
if (head == vq->num) {
if (unlikely(vhost_enable_notify(vq))) {
@@ -267,8 +275,8 @@ static void handle_rx(struct vhost_net *net)
}
/* TODO: Should check and handle checksum. */
if (err > len) {
- pr_err("Discarded truncated rx packet: "
- " len %d > %zd\n", err, len);
+ pr_debug("Discarded truncated rx packet: "
+ " len %d > %zd\n", err, len);
vhost_discard_vq_desc(vq);
continue;
}
@@ -526,11 +534,16 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
rcu_assign_pointer(vq->private_data, sock);
vhost_net_enable_vq(n, vq);
done:
+ mutex_unlock(&vq->mutex);
+
if (oldsock) {
vhost_net_flush_vq(n, index);
fput(oldsock->file);
}
+ mutex_unlock(&n->dev.mutex);
+ return 0;
+
err_vq:
mutex_unlock(&vq->mutex);
err:
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 3b83382e06eb..0b99783083f6 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -736,12 +736,12 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
mem = rcu_dereference(dev->memory);
while ((u64)len > s) {
u64 size;
- if (ret >= iov_size) {
+ if (unlikely(ret >= iov_size)) {
ret = -ENOBUFS;
break;
}
reg = find_region(mem, addr, len);
- if (!reg) {
+ if (unlikely(!reg)) {
ret = -EFAULT;
break;
}
@@ -780,18 +780,18 @@ static unsigned next_desc(struct vring_desc *desc)
return next;
}
-static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
- struct iovec iov[], unsigned int iov_size,
- unsigned int *out_num, unsigned int *in_num,
- struct vhost_log *log, unsigned int *log_num,
- struct vring_desc *indirect)
+static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+ struct iovec iov[], unsigned int iov_size,
+ unsigned int *out_num, unsigned int *in_num,
+ struct vhost_log *log, unsigned int *log_num,
+ struct vring_desc *indirect)
{
struct vring_desc desc;
unsigned int i = 0, count, found = 0;
int ret;
/* Sanity check */
- if (indirect->len % sizeof desc) {
+ if (unlikely(indirect->len % sizeof desc)) {
vq_err(vq, "Invalid length in indirect descriptor: "
"len 0x%llx not multiple of 0x%zx\n",
(unsigned long long)indirect->len,
@@ -801,7 +801,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
ARRAY_SIZE(vq->indirect));
- if (ret < 0) {
+ if (unlikely(ret < 0)) {
vq_err(vq, "Translation failure %d in indirect.\n", ret);
return ret;
}
@@ -813,7 +813,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
count = indirect->len / sizeof desc;
/* Buffers are chained via a 16 bit next field, so
* we can have at most 2^16 of these. */
- if (count > USHRT_MAX + 1) {
+ if (unlikely(count > USHRT_MAX + 1)) {
vq_err(vq, "Indirect buffer length too big: %d\n",
indirect->len);
return -E2BIG;
@@ -821,19 +821,19 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
do {
unsigned iov_count = *in_num + *out_num;
- if (++found > count) {
+ if (unlikely(++found > count)) {
vq_err(vq, "Loop detected: last one at %u "
"indirect size %u\n",
i, count);
return -EINVAL;
}
- if (memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
- sizeof desc)) {
+ if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
+ sizeof desc))) {
vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
i, (size_t)indirect->addr + i * sizeof desc);
return -EINVAL;
}
- if (desc.flags & VRING_DESC_F_INDIRECT) {
+ if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {
vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n",
i, (size_t)indirect->addr + i * sizeof desc);
return -EINVAL;
@@ -841,7 +841,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
iov_size - iov_count);
- if (ret < 0) {
+ if (unlikely(ret < 0)) {
vq_err(vq, "Translation failure %d indirect idx %d\n",
ret, i);
return ret;
@@ -857,7 +857,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
} else {
/* If it's an output descriptor, they're all supposed
* to come before any input descriptors. */
- if (*in_num) {
+ if (unlikely(*in_num)) {
vq_err(vq, "Indirect descriptor "
"has out after in: idx %d\n", i);
return -EINVAL;
@@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
* number of output then some number of input descriptors, it's actually two
* iovecs, but we pack them into one and note how many of each there were.
*
- * This function returns the descriptor number found, or vq->num (which
- * is never a valid descriptor number) if none was found. */
-unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
- struct iovec iov[], unsigned int iov_size,
- unsigned int *out_num, unsigned int *in_num,
- struct vhost_log *log, unsigned int *log_num)
+ * This function returns the descriptor number found, or vq->num (which is
+ * never a valid descriptor number) if none was found. A negative code is
+ * returned on error. */
+int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+ struct iovec iov[], unsigned int iov_size,
+ unsigned int *out_num, unsigned int *in_num,
+ struct vhost_log *log, unsigned int *log_num)
{
struct vring_desc desc;
unsigned int i, head, found = 0;
@@ -887,16 +888,16 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
/* Check it isn't doing very strange things with descriptor numbers. */
last_avail_idx = vq->last_avail_idx;
- if (get_user(vq->avail_idx, &vq->avail->idx)) {
+ if (unlikely(get_user(vq->avail_idx, &vq->avail->idx))) {
vq_err(vq, "Failed to access avail idx at %p\n",
&vq->avail->idx);
- return vq->num;
+ return -EFAULT;
}
- if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) {
+ if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) {
vq_err(vq, "Guest moved used index from %u to %u",
last_avail_idx, vq->avail_idx);
- return vq->num;
+ return -EFAULT;
}
/* If there's nothing new since last we looked, return invalid. */
@@ -908,18 +909,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
/* Grab the next descriptor number they're advertising, and increment
* the index we've seen. */
- if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) {
+ if (unlikely(get_user(head,
+ &vq->avail->ring[last_avail_idx % vq->num]))) {
vq_err(vq, "Failed to read head: idx %d address %p\n",
last_avail_idx,
&vq->avail->ring[last_avail_idx % vq->num]);
- return vq->num;
+ return -EFAULT;
}
/* If their number is silly, that's an error. */
- if (head >= vq->num) {
+ if (unlikely(head >= vq->num)) {
vq_err(vq, "Guest says index %u > %u is available",
head, vq->num);
- return vq->num;
+ return -EINVAL;
}
/* When we start there are none of either input nor output. */
@@ -930,41 +932,41 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
i = head;
do {
unsigned iov_count = *in_num + *out_num;
- if (i >= vq->num) {
+ if (unlikely(i >= vq->num)) {
vq_err(vq, "Desc index is %u > %u, head = %u",
i, vq->num, head);
- return vq->num;
+ return -EINVAL;
}
- if (++found > vq->num) {
+ if (unlikely(++found > vq->num)) {
vq_err(vq, "Loop detected: last one at %u "
"vq size %u head %u\n",
i, vq->num, head);
- return vq->num;
+ return -EINVAL;
}
ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
- if (ret) {
+ if (unlikely(ret)) {
vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
i, vq->desc + i);
- return vq->num;
+ return -EFAULT;
}
if (desc.flags & VRING_DESC_F_INDIRECT) {
ret = get_indirect(dev, vq, iov, iov_size,
out_num, in_num,
log, log_num, &desc);
- if (ret < 0) {
+ if (unlikely(ret < 0)) {
vq_err(vq, "Failure detected "
"in indirect descriptor at idx %d\n", i);
- return vq->num;
+ return ret;
}
continue;
}
ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
iov_size - iov_count);
- if (ret < 0) {
+ if (unlikely(ret < 0)) {
vq_err(vq, "Translation failure %d descriptor idx %d\n",
ret, i);
- return vq->num;
+ return ret;
}
if (desc.flags & VRING_DESC_F_WRITE) {
/* If this is an input descriptor,
@@ -978,10 +980,10 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
} else {
/* If it's an output descriptor, they're all supposed
* to come before any input descriptors. */
- if (*in_num) {
+ if (unlikely(*in_num)) {
vq_err(vq, "Descriptor has out after in: "
"idx %d\n", i);
- return vq->num;
+ return -EINVAL;
}
*out_num += ret;
}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 44591ba9b07a..11ee13dba0f7 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -120,10 +120,10 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
int vhost_vq_access_ok(struct vhost_virtqueue *vq);
int vhost_log_access_ok(struct vhost_dev *);
-unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
- struct iovec iov[], unsigned int iov_count,
- unsigned int *out_num, unsigned int *in_num,
- struct vhost_log *log, unsigned int *log_num);
+int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
+ struct iovec iov[], unsigned int iov_count,
+ unsigned int *out_num, unsigned int *in_num,
+ struct vhost_log *log, unsigned int *log_num);
void vhost_discard_vq_desc(struct vhost_virtqueue *);
int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 515cf1978d19..c4e17642d9c5 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2872,7 +2872,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis
}
#if 0
- /* Power down TV DAC, taht saves a significant amount of power,
+ /* Power down TV DAC, that saves a significant amount of power,
* we'll have something better once we actually have some TVOut
* support
*/
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 40f61320ce16..34b2fc472fe8 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -95,7 +95,7 @@ struct fb_bitfield rgb_bitfields[][4] =
{ { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
};
-static struct fb_fix_screeninfo au1100fb_fix __initdata = {
+static struct fb_fix_screeninfo au1100fb_fix __devinitdata = {
.id = "AU1100 FB",
.xpanstep = 1,
.ypanstep = 1,
@@ -103,7 +103,7 @@ static struct fb_fix_screeninfo au1100fb_fix __initdata = {
.accel = FB_ACCEL_NONE,
};
-static struct fb_var_screeninfo au1100fb_var __initdata = {
+static struct fb_var_screeninfo au1100fb_var __devinitdata = {
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
@@ -458,7 +458,7 @@ static struct fb_ops au1100fb_ops =
/* AU1100 LCD controller device driver */
-static int __init au1100fb_drv_probe(struct platform_device *dev)
+static int __devinit au1100fb_drv_probe(struct platform_device *dev)
{
struct au1100fb_device *fbdev = NULL;
struct resource *regs_res;
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 3a561df2e8a2..0c1afd13ddd3 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -388,6 +388,7 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
pseudo_val |= convert_bitfield(red, &var->red);
pseudo_val |= convert_bitfield(green, &var->green);
pseudo_val |= convert_bitfield(blue, &var->blue);
+ ret = 0;
break;
}
@@ -436,6 +437,8 @@ static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
cyber2000fb_writeb(i | 4, 0x3cf, cfb);
cyber2000fb_writeb(val, 0x3c6, cfb);
cyber2000fb_writeb(i, 0x3cf, cfb);
+ /* prevent card lock-up observed on x86 with CyberPro 2000 */
+ cyber2000fb_readb(0x3cf, cfb);
}
static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 7d8c55d7fd28..ca3355e430bf 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -91,10 +91,10 @@ static uint32_t pseudo_palette[16];
static uint32_t gbe_cmap[256];
static int gbe_turned_on; /* 0 turned off, 1 turned on */
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
/* default CRT mode */
-static struct fb_var_screeninfo default_var_CRT __initdata = {
+static struct fb_var_screeninfo default_var_CRT __devinitdata = {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
.xres = 640,
.yres = 480,
@@ -125,7 +125,7 @@ static struct fb_var_screeninfo default_var_CRT __initdata = {
};
/* default LCD mode */
-static struct fb_var_screeninfo default_var_LCD __initdata = {
+static struct fb_var_screeninfo default_var_LCD __devinitdata = {
/* 1600x1024, 8 bpp */
.xres = 1600,
.yres = 1024,
@@ -157,7 +157,7 @@ static struct fb_var_screeninfo default_var_LCD __initdata = {
/* default modedb mode */
/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-static struct fb_videomode default_mode_CRT __initdata = {
+static struct fb_videomode default_mode_CRT __devinitdata = {
.refresh = 60,
.xres = 640,
.yres = 480,
@@ -172,7 +172,7 @@ static struct fb_videomode default_mode_CRT __initdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
/* 1600x1024 SGI flatpanel 1600sw */
-static struct fb_videomode default_mode_LCD __initdata = {
+static struct fb_videomode default_mode_LCD __devinitdata = {
/* 1600x1024, 8 bpp */
.xres = 1600,
.yres = 1024,
@@ -186,8 +186,8 @@ static struct fb_videomode default_mode_LCD __initdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_videomode *default_mode __initdata = &default_mode_CRT;
-static struct fb_var_screeninfo *default_var __initdata = &default_var_CRT;
+static struct fb_videomode *default_mode __devinitdata = &default_mode_CRT;
+static struct fb_var_screeninfo *default_var __devinitdata = &default_var_CRT;
static int flat_panel_enabled = 0;
@@ -1098,7 +1098,7 @@ static void gbefb_create_sysfs(struct device *dev)
* Initialization
*/
-static int __init gbefb_setup(char *options)
+static int __devinit gbefb_setup(char *options)
{
char *this_opt;
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 76e7dac6f259..70b1d9d51c96 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -40,7 +40,7 @@ static int vram;
static int vt_switch;
/* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] __initdata = {
+static struct fb_videomode gx_modedb[] __devinitdata = {
/* 640x480-60 VESA */
{ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -110,14 +110,15 @@ static struct fb_videomode gx_modedb[] __initdata = {
#ifdef CONFIG_OLPC
#include <asm/olpc.h>
-static struct fb_videomode gx_dcon_modedb[] __initdata = {
+static struct fb_videomode gx_dcon_modedb[] __devinitdata = {
/* The only mode the DCON has is 1200x900 */
{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, 0 }
};
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
if (olpc_has_dcon()) {
*modedb = (struct fb_videomode *) gx_dcon_modedb;
@@ -129,7 +130,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
}
#else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
*modedb = (struct fb_videomode *) gx_modedb;
*size = ARRAY_SIZE(gx_modedb);
@@ -226,7 +228,8 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)
return gx_blank_display(info, blank_mode);
}
-static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int __devinit gxfb_map_video_memory(struct fb_info *info,
+ struct pci_dev *dev)
{
struct gxfb_par *par = info->par;
int ret;
@@ -290,7 +293,7 @@ static struct fb_ops gxfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)
{
struct gxfb_par *par;
struct fb_info *info;
@@ -371,7 +374,8 @@ static int gxfb_resume(struct pci_dev *pdev)
}
#endif
-static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit gxfb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct gxfb_par *par;
struct fb_info *info;
@@ -451,7 +455,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
return ret;
}
-static void gxfb_remove(struct pci_dev *pdev)
+static void __devexit gxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct gxfb_par *par = info->par;
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 1a18da86d3fa..39bdbedf43b4 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -35,7 +35,7 @@ static int vt_switch;
* we try to make it something sane - 640x480-60 is sane
*/
-static struct fb_videomode geode_modedb[] __initdata = {
+static struct fb_videomode geode_modedb[] __devinitdata = {
/* 640x480-60 */
{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
@@ -219,14 +219,15 @@ static struct fb_videomode geode_modedb[] __initdata = {
#ifdef CONFIG_OLPC
#include <asm/olpc.h>
-static struct fb_videomode olpc_dcon_modedb[] __initdata = {
+static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {
/* The only mode the DCON has is 1200x900 */
{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, 0 }
};
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
if (olpc_has_dcon()) {
*modedb = (struct fb_videomode *) olpc_dcon_modedb;
@@ -238,7 +239,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
}
#else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
*modedb = (struct fb_videomode *) geode_modedb;
*size = ARRAY_SIZE(geode_modedb);
@@ -334,7 +336,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info)
}
-static int __init lxfb_map_video_memory(struct fb_info *info,
+static int __devinit lxfb_map_video_memory(struct fb_info *info,
struct pci_dev *dev)
{
struct lxfb_par *par = info->par;
@@ -412,7 +414,7 @@ static struct fb_ops lxfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
+static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)
{
struct lxfb_par *par;
struct fb_info *info;
@@ -496,7 +498,7 @@ static int lxfb_resume(struct pci_dev *pdev)
#define lxfb_resume NULL
#endif
-static int __init lxfb_probe(struct pci_dev *pdev,
+static int __devinit lxfb_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct lxfb_par *par;
@@ -588,7 +590,7 @@ err:
return ret;
}
-static void lxfb_remove(struct pci_dev *pdev)
+static void __devexit lxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct lxfb_par *par = info->par;
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index b4b6deceed15..43f0639b1c10 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -175,6 +175,7 @@ struct imxfb_info {
struct imx_fb_videomode *mode;
int num_modes;
+ struct backlight_device *bl;
void (*lcd_power)(int);
void (*backlight_power)(int);
@@ -449,6 +450,73 @@ static int imxfb_set_par(struct fb_info *info)
return 0;
}
+
+
+static int imxfb_bl_get_brightness(struct backlight_device *bl)
+{
+ struct imxfb_info *fbi = bl_get_data(bl);
+
+ return readl(fbi->regs + LCDC_PWMR) & 0xFF;
+}
+
+static int imxfb_bl_update_status(struct backlight_device *bl)
+{
+ struct imxfb_info *fbi = bl_get_data(bl);
+ int brightness = bl->props.brightness;
+
+ if (bl->props.power != FB_BLANK_UNBLANK)
+ brightness = 0;
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness;
+
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ clk_enable(fbi->clk);
+ writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ clk_disable(fbi->clk);
+
+ return 0;
+}
+
+static const struct backlight_ops imxfb_lcdc_bl_ops = {
+ .update_status = imxfb_bl_update_status,
+ .get_brightness = imxfb_bl_get_brightness,
+};
+
+static void imxfb_init_backlight(struct imxfb_info *fbi)
+{
+ struct backlight_properties props;
+ struct backlight_device *bl;
+
+ if (fbi->bl)
+ return;
+
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.max_brightness = 0xff;
+ writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
+
+ bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
+ &imxfb_lcdc_bl_ops, &props);
+ if (IS_ERR(bl)) {
+ dev_err(&fbi->pdev->dev, "error %ld on backlight register\n",
+ PTR_ERR(bl));
+ return;
+ }
+
+ fbi->bl = bl;
+ bl->props.power = FB_BLANK_UNBLANK;
+ bl->props.fb_blank = FB_BLANK_UNBLANK;
+ bl->props.brightness = imxfb_bl_get_brightness(bl);
+}
+
+static void imxfb_exit_backlight(struct imxfb_info *fbi)
+{
+ if (fbi->bl)
+ backlight_device_unregister(fbi->bl);
+}
+
static void imxfb_enable_controller(struct imxfb_info *fbi)
{
pr_debug("Enabling LCD controller\n");
@@ -579,7 +647,6 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
fbi->regs + LCDC_SIZE);
writel(fbi->pcr, fbi->regs + LCDC_PCR);
- writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -779,6 +846,8 @@ static int __init imxfb_probe(struct platform_device *pdev)
}
imxfb_enable_controller(fbi);
+ fbi->pdev = pdev;
+ imxfb_init_backlight(fbi);
return 0;
@@ -816,6 +885,7 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
imxfb_disable_controller(fbi);
+ imxfb_exit_backlight(fbi);
unregister_framebuffer(info);
pdata = pdev->dev.platform_data;
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d4cde79ea15e..81687ed26ba9 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -596,8 +596,6 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
goto release_regs;
}
- nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
-
fbi->clk = clk_get(&pdev->dev, NULL);
if (!fbi->clk || IS_ERR(fbi->clk)) {
printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 43ab7d8b66b2..7767338f8b14 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -572,22 +572,12 @@ static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
/* PM code called only in internal controller mode */
static void omap_lcdc_suspend(void)
{
- if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
- disable_controller();
- omap_stop_lcd_dma();
- }
+ omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
}
static void omap_lcdc_resume(void)
{
- if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
- setup_regs();
- load_palette();
- setup_lcd_dma();
- set_load_mode(OMAP_LCDC_LOAD_FRAME);
- enable_irqs(OMAP_LCDC_IRQ_DONE);
- enable_controller();
- }
+ omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
}
static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 1162603c72e5..eada9f12efc7 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include "omapfb.h"
#include "dispc.h"
@@ -83,13 +84,13 @@ static inline u32 rfbi_read_reg(int idx)
static int rfbi_get_clocks(void)
{
- rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
+ rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");
if (IS_ERR(rfbi.dss_ick)) {
dev_err(rfbi.fbdev->dev, "can't get ick\n");
return PTR_ERR(rfbi.dss_ick);
}
- rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
+ rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck");
if (IS_ERR(rfbi.dss1_fck)) {
dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
clk_put(rfbi.dss_ick);
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index 3b1237ad85ed..f6fdc2085f3e 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -25,7 +25,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
-#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/jiffies.h>
@@ -525,10 +525,8 @@ early_param("vram", omap_vram_early_vram);
* Called from map_io. We need to call to this early enough so that we
* can reserve the fixed SDRAM regions before VM could get hold of them.
*/
-void __init omap_vram_reserve_sdram(void)
+void __init omap_vram_reserve_sdram_memblock(void)
{
- struct bootmem_data *bdata;
- unsigned long sdram_start, sdram_size;
u32 paddr;
u32 size = 0;
@@ -555,29 +553,28 @@ void __init omap_vram_reserve_sdram(void)
size = PAGE_ALIGN(size);
- bdata = NODE_DATA(0)->bdata;
- sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
- sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
-
if (paddr) {
- if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
- paddr + size > sdram_start + sdram_size) {
+ struct memblock_property res;
+
+ res.base = paddr;
+ res.size = size;
+ if ((paddr & ~PAGE_MASK) || memblock_find(&res) ||
+ res.base != paddr || res.size != size) {
pr_err("Illegal SDRAM region for VRAM\n");
return;
}
- if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
- pr_err("FB: failed to reserve VRAM\n");
+ if (memblock_is_region_reserved(paddr, size)) {
+ pr_err("FB: failed to reserve VRAM - busy\n");
return;
}
- } else {
- if (size > sdram_size) {
- pr_err("Illegal SDRAM size for VRAM\n");
+
+ if (memblock_reserve(paddr, size) < 0) {
+ pr_err("FB: failed to reserve VRAM - no memory\n");
return;
}
-
- paddr = virt_to_phys(alloc_bootmem_pages(size));
- BUG_ON(paddr & ~PAGE_MASK);
+ } else {
+ paddr = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_REAL_LIMIT);
}
omap_vram_add_region(paddr, size);
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 0f361b6100d2..0c69fa20251b 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -44,7 +44,7 @@ struct pmagbafb_par {
};
-static struct fb_var_screeninfo pmagbafb_defined __initdata = {
+static struct fb_var_screeninfo pmagbafb_defined __devinitdata = {
.xres = 1024,
.yres = 864,
.xres_virtual = 1024,
@@ -68,7 +68,7 @@ static struct fb_var_screeninfo pmagbafb_defined __initdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo pmagbafb_fix __initdata = {
+static struct fb_fix_screeninfo pmagbafb_fix __devinitdata = {
.id = "PMAG-BA",
.smem_len = (1024 * 1024),
.type = FB_TYPE_PACKED_PIXELS,
@@ -142,7 +142,7 @@ static void __init pmagbafb_erase_cursor(struct fb_info *info)
}
-static int __init pmagbafb_probe(struct device *dev)
+static int __devinit pmagbafb_probe(struct device *dev)
{
struct tc_dev *tdev = to_tc_dev(dev);
resource_size_t start, len;
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 2de0806421b4..22fcb9a3d5c0 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -45,7 +45,7 @@ struct pmagbbfb_par {
};
-static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
+static struct fb_var_screeninfo pmagbbfb_defined __devinitdata = {
.bits_per_pixel = 8,
.red.length = 8,
.green.length = 8,
@@ -58,7 +58,7 @@ static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo pmagbbfb_fix __initdata = {
+static struct fb_fix_screeninfo pmagbbfb_fix __devinitdata = {
.id = "PMAGB-BA",
.smem_len = (2048 * 1024),
.type = FB_TYPE_PACKED_PIXELS,
@@ -148,7 +148,7 @@ static void __init pmagbbfb_erase_cursor(struct fb_info *info)
/*
* Set up screen parameters.
*/
-static void __init pmagbbfb_screen_setup(struct fb_info *info)
+static void __devinit pmagbbfb_screen_setup(struct fb_info *info)
{
struct pmagbbfb_par *par = info->par;
@@ -180,9 +180,9 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info)
/*
* Determine oscillator configuration.
*/
-static void __init pmagbbfb_osc_setup(struct fb_info *info)
+static void __devinit pmagbbfb_osc_setup(struct fb_info *info)
{
- static unsigned int pmagbbfb_freqs[] __initdata = {
+ static unsigned int pmagbbfb_freqs[] __devinitdata = {
130808, 119843, 104000, 92980, 74370, 72800,
69197, 66000, 65000, 50350, 36000, 32000, 25175
};
@@ -247,7 +247,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)
};
-static int __init pmagbbfb_probe(struct device *dev)
+static int __devinit pmagbbfb_probe(struct device *dev)
{
struct tc_dev *tdev = to_tc_dev(dev);
resource_size_t start, len;
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 95896f387927..ef8d9d558fc7 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -636,6 +636,9 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
INIT_LIST_HEAD(&vp_dev->virtqueues);
spin_lock_init(&vp_dev->lock);
+ /* Disable MSI/MSIX to bring device to a known good state. */
+ pci_msi_off(pci_dev);
+
/* enable the device */
err = pci_enable_device(pci_dev);
if (err)
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1ca88908723b..1475ed6b575f 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -119,7 +119,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
if (!desc)
- return vq->vring.num;
+ return -ENOMEM;
/* Transfer entries from the sg list into the indirect page */
for (i = 0; i < out; i++) {
@@ -164,7 +164,8 @@ int virtqueue_add_buf_gfp(struct virtqueue *_vq,
gfp_t gfp)
{
struct vring_virtqueue *vq = to_vvq(_vq);
- unsigned int i, avail, head, uninitialized_var(prev);
+ unsigned int i, avail, uninitialized_var(prev);
+ int head;
START_USE(vq);
@@ -174,7 +175,7 @@ int virtqueue_add_buf_gfp(struct virtqueue *_vq,
* buffers, then go indirect. FIXME: tune this threshold */
if (vq->indirect && (out + in) > 1 && vq->num_free) {
head = vring_add_indirect(vq, sg, out, in, gfp);
- if (head != vq->vring.num)
+ if (likely(head >= 0))
goto add_head;
}
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 1cddf92cb9a6..750bc5281d79 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -346,9 +346,13 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
} else {
wdt->users = 0;
}
- wdt->miscdev.minor = WATCHDOG_MINOR;
- wdt->miscdev.name = "watchdog";
- wdt->miscdev.fops = &at32_wdt_fops;
+
+ wdt->miscdev.minor = WATCHDOG_MINOR;
+ wdt->miscdev.name = "watchdog";
+ wdt->miscdev.fops = &at32_wdt_fops;
+ wdt->miscdev.parent = &pdev->dev;
+
+ platform_set_drvdata(pdev, wdt);
if (at32_wdt_settimeout(timeout)) {
at32_wdt_settimeout(TIMEOUT_DEFAULT);
@@ -360,17 +364,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
ret = misc_register(&wdt->miscdev);
if (ret) {
dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
- goto err_iounmap;
+ goto err_register;
}
- platform_set_drvdata(pdev, wdt);
- wdt->miscdev.parent = &pdev->dev;
dev_info(&pdev->dev,
"AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
wdt->regs, wdt->timeout, nowayout);
return 0;
+err_register:
+ platform_set_drvdata(pdev, NULL);
err_iounmap:
iounmap(wdt->regs);
err_free:
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index ea25885781bb..2ee7dac55a3c 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -330,7 +330,6 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
}
static struct platform_driver imx2_wdt_driver = {
- .probe = imx2_wdt_probe,
.remove = __exit_p(imx2_wdt_remove),
.shutdown = imx2_wdt_shutdown,
.driver = {