aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/Kconfig16
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/ac.c40
-rw-r--r--drivers/acpi/battery.c32
-rw-r--r--drivers/acpi/ec.c100
-rw-r--r--drivers/acpi/osl.c25
-rw-r--r--drivers/acpi/processor_core.c33
-rw-r--r--drivers/acpi/processor_idle.c112
-rw-r--r--drivers/acpi/processor_throttling.c286
-rw-r--r--drivers/acpi/sbs.c43
-rw-r--r--drivers/acpi/tables/tbutils.c2
-rw-r--r--drivers/acpi/toshiba_acpi.c3
-rw-r--r--drivers/acpi/video.c155
-rw-r--r--drivers/ata/ata_piix.c128
-rw-r--r--drivers/ata/libata-acpi.c10
-rw-r--r--drivers/ata/libata-core.c194
-rw-r--r--drivers/ata/libata-eh.c137
-rw-r--r--drivers/ata/libata-scsi.c38
-rw-r--r--drivers/ata/pata_ali.c20
-rw-r--r--drivers/ata/pata_at32.c61
-rw-r--r--drivers/ata/pata_bf54x.c13
-rw-r--r--drivers/ata/pata_hpt37x.c2
-rw-r--r--drivers/ata/pata_isapnp.c11
-rw-r--r--drivers/ata/pata_jmicron.c9
-rw-r--r--drivers/ata/pata_platform.c35
-rw-r--r--drivers/ata/pata_sil680.c32
-rw-r--r--drivers/ata/pata_sis.c1
-rw-r--r--drivers/ata/sata_mv.c64
-rw-r--r--drivers/ata/sata_nv.c2
-rw-r--r--drivers/ata/sata_qstor.c114
-rw-r--r--drivers/ata/sata_sil24.c26
-rw-r--r--drivers/atm/he.c10
-rw-r--r--drivers/base/core.c4
-rw-r--r--drivers/base/power/Makefile3
-rw-r--r--drivers/base/power/main.c8
-rw-r--r--drivers/base/power/power.h28
-rw-r--r--drivers/block/nbd.c3
-rw-r--r--drivers/block/paride/pf.c25
-rw-r--r--drivers/block/pktcdvd.c9
-rw-r--r--drivers/block/rd.c13
-rw-r--r--drivers/block/virtio_blk.c10
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c2
-rw-r--r--drivers/char/random.c6
-rw-r--r--drivers/char/rtc.c52
-rw-r--r--drivers/char/sonypi.c8
-rw-r--r--drivers/char/tpm/tpm_tis.c10
-rw-r--r--drivers/char/tty_ioctl.c170
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c153
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/crypto/geode-aes.c3
-rw-r--r--drivers/dma/Kconfig8
-rw-r--r--drivers/dma/dmaengine.c17
-rw-r--r--drivers/dma/ioat.c11
-rw-r--r--drivers/dma/ioat_dca.c164
-rw-r--r--drivers/dma/ioat_dma.c578
-rw-r--r--drivers/dma/ioatdma.h32
-rw-r--r--drivers/dma/ioatdma_hw.h33
-rw-r--r--drivers/dma/ioatdma_registers.h106
-rw-r--r--drivers/edac/i5000_edac.c2
-rw-r--r--drivers/firewire/fw-sbp2.c11
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/abituguru3.c56
-rw-r--r--drivers/hwmon/applesmc.c107
-rw-r--r--drivers/hwmon/f75375s.c170
-rw-r--r--drivers/hwmon/i5k_amb.c552
-rw-r--r--drivers/hwmon/ibmpex.c48
-rw-r--r--drivers/hwmon/lm70.c11
-rw-r--r--drivers/hwmon/sis5595.c59
-rw-r--r--drivers/hwmon/w83627hf.c155
-rw-r--r--drivers/hwmon/w83781d.c3
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c7
-rw-r--r--drivers/i2c/chips/eeprom.c37
-rw-r--r--drivers/i2c/i2c-core.c3
-rw-r--r--drivers/i2c/i2c-dev.c86
-rw-r--r--drivers/ide/Kconfig51
-rw-r--r--drivers/ide/Makefile2
-rw-r--r--drivers/ide/cris/ide-cris.c10
-rw-r--r--drivers/ide/ide-dma.c1
-rw-r--r--drivers/ide/ide-io.c6
-rw-r--r--drivers/ide/ide-iops.c13
-rw-r--r--drivers/ide/ide-lib.c1
-rw-r--r--drivers/ide/ide-probe.c32
-rw-r--r--drivers/ide/legacy/ali14xx.c7
-rw-r--r--drivers/ide/legacy/macide.c2
-rw-r--r--drivers/ide/legacy/q40ide.c2
-rw-r--r--drivers/ide/pci/aec62xx.c11
-rw-r--r--drivers/ide/pci/alim15x3.c5
-rw-r--r--drivers/ide/pci/cmd64x.c5
-rw-r--r--drivers/ide/pci/cs5530.c3
-rw-r--r--drivers/ide/pci/it821x.c3
-rw-r--r--drivers/ide/pci/jmicron.c3
-rw-r--r--drivers/ide/pci/piix.c1
-rw-r--r--drivers/ide/pci/sc1200.c3
-rw-r--r--drivers/ide/pci/siimage.c45
-rw-r--r--drivers/ide/pci/sis5513.c2
-rw-r--r--drivers/ide/pci/trm290.c3
-rw-r--r--drivers/ide/ppc/pmac.c3
-rw-r--r--drivers/ide/setup-pci.c5
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_av.c52
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c20
-rw-r--r--drivers/infiniband/hw/ehca/ehca_iverbs.h3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c29
-rw-r--r--drivers/infiniband/hw/ehca/hipz_hw.h6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_cq.c30
-rw-r--r--drivers/infiniband/hw/ipath/ipath_qp.c15
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c5
-rw-r--r--drivers/infiniband/hw/ipath/ipath_srq.c44
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c3
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c6
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/gpio_keys.c38
-rw-r--r--drivers/input/serio/Kconfig2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h8
-rw-r--r--drivers/isdn/hisax/hfcscard.c3
-rw-r--r--drivers/isdn/i4l/isdn_common.c5
-rw-r--r--drivers/isdn/i4l/isdn_net.c8
-rw-r--r--drivers/isdn/sc/card.h2
-rw-r--r--drivers/isdn/sc/packet.c2
-rw-r--r--drivers/isdn/sc/shmem.c2
-rw-r--r--drivers/kvm/kvm_main.c3
-rw-r--r--drivers/kvm/svm.c19
-rw-r--r--drivers/kvm/x86_emulate.c32
-rw-r--r--drivers/lguest/lguest_device.c5
-rw-r--r--drivers/lguest/lguest_user.c2
-rw-r--r--drivers/macintosh/windfarm_core.c10
-rw-r--r--drivers/md/bitmap.c3
-rw-r--r--drivers/md/dm-table.c3
-rw-r--r--drivers/md/linear.c3
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/multipath.c3
-rw-r--r--drivers/md/raid0.c3
-rw-r--r--drivers/md/raid1.c3
-rw-r--r--drivers/md/raid10.c3
-rw-r--r--drivers/md/raid5.c19
-rw-r--r--drivers/mfd/sm501.c2
-rw-r--r--drivers/misc/ioc4.c10
-rw-r--r--drivers/misc/sony-laptop.c10
-rw-r--r--drivers/misc/thinkpad_acpi.c231
-rw-r--r--drivers/misc/thinkpad_acpi.h4
-rw-r--r--drivers/mmc/card/block.c22
-rw-r--r--drivers/mmc/card/queue.c5
-rw-r--r--drivers/mmc/card/sdio_uart.c2
-rw-r--r--drivers/mmc/host/sdhci.c2
-rw-r--r--drivers/mmc/host/tifm_sd.c18
-rw-r--r--drivers/net/Kconfig212
-rw-r--r--drivers/net/amd8111e.c6
-rw-r--r--drivers/net/arcnet/Kconfig15
-rw-r--r--drivers/net/arm/ep93xx_eth.c2
-rw-r--r--drivers/net/bfin_mac.c4
-rw-r--r--drivers/net/bfin_mac.h2
-rw-r--r--drivers/net/bonding/bond_main.c5
-rw-r--r--drivers/net/bonding/bond_sysfs.c4
-rwxr-xr-x[-rw-r--r--]drivers/net/chelsio/cxgb2.c70
-rwxr-xr-x[-rw-r--r--]drivers/net/chelsio/pm3393.c112
-rwxr-xr-x[-rw-r--r--]drivers/net/chelsio/sge.c46
-rwxr-xr-x[-rw-r--r--]drivers/net/chelsio/sge.h3
-rw-r--r--drivers/net/cris/eth_v10.c440
-rw-r--r--drivers/net/e1000/e1000_main.c15
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c20
-rw-r--r--drivers/net/ehea/ehea_qmr.h4
-rw-r--r--drivers/net/fec_mpc52xx.c2
-rw-r--r--drivers/net/forcedeth.c38
-rw-r--r--drivers/net/fs_enet/Kconfig11
-rw-r--r--drivers/net/fs_enet/Makefile15
-rw-r--r--drivers/net/hamradio/6pack.c26
-rw-r--r--drivers/net/ibm_newemac/core.c31
-rw-r--r--drivers/net/ibm_newemac/core.h1
-rw-r--r--drivers/net/irda/irtty-sir.c7
-rw-r--r--drivers/net/lib82596.c50
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/mlx4/alloc.c7
-rw-r--r--drivers/net/mlx4/qp.c4
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/netx-eth.c6
-rw-r--r--drivers/net/pasemi_mac.c18
-rw-r--r--drivers/net/phy/marvell.c26
-rw-r--r--drivers/net/phy/phy.c3
-rw-r--r--drivers/net/plip.c4
-rw-r--r--drivers/net/ppp_async.c44
-rw-r--r--drivers/net/ppp_generic.c126
-rw-r--r--drivers/net/ppp_synctty.c37
-rw-r--r--drivers/net/pppol2tp.c25
-rw-r--r--drivers/net/qla3xxx.c42
-rw-r--r--drivers/net/qla3xxx.h1
-rw-r--r--drivers/net/r8169.c26
-rw-r--r--drivers/net/rrunner.c18
-rw-r--r--drivers/net/s2io.c142
-rw-r--r--drivers/net/skge.c157
-rw-r--r--drivers/net/sky2.c183
-rw-r--r--drivers/net/sky2.h24
-rw-r--r--drivers/net/slip.c8
-rw-r--r--drivers/net/smc911x.c19
-rw-r--r--drivers/net/smc911x.h2
-rw-r--r--drivers/net/smc91x.h17
-rw-r--r--drivers/net/sungem.c22
-rw-r--r--drivers/net/sunhme.c17
-rw-r--r--drivers/net/tehuti.c8
-rw-r--r--drivers/net/tg3.c186
-rw-r--r--drivers/net/tg3.h44
-rw-r--r--drivers/net/tulip/Kconfig21
-rw-r--r--drivers/net/tulip/dmfe.c4
-rw-r--r--drivers/net/ucc_geth.c10
-rw-r--r--drivers/net/usb/Kconfig9
-rw-r--r--drivers/net/usb/dm9601.c2
-rw-r--r--drivers/net/usb/usbnet.c7
-rw-r--r--drivers/net/via-velocity.c16
-rw-r--r--drivers/net/virtio_net.c15
-rw-r--r--drivers/net/wan/x25_asy.c6
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/b43/Kconfig10
-rw-r--r--drivers/net/wireless/b43/debugfs.c2
-rw-r--r--drivers/net/wireless/b43/main.c21
-rw-r--r--drivers/net/wireless/b43/pcmcia.c52
-rw-r--r--drivers/net/wireless/b43/phy.c2
-rw-r--r--drivers/net/wireless/b43/rfkill.c115
-rw-r--r--drivers/net/wireless/b43/rfkill.h14
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/dma.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c23
-rw-r--r--drivers/net/wireless/b43legacy/phy.c2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c6
-rw-r--r--drivers/net/wireless/ipw2100.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c56
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c126
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c23
-rw-r--r--drivers/net/wireless/libertas/cmd.c10
-rw-r--r--drivers/net/wireless/libertas/if_cs.c10
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c4
-rw-r--r--drivers/net/wireless/libertas/main.c4
-rw-r--r--drivers/net/wireless/libertas/wext.c2
-rw-r--r--drivers/net/wireless/netwave_cs.c2
-rw-r--r--drivers/net/wireless/p54usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h15
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c6
-rw-r--r--drivers/net/wireless/strip.c10
-rw-r--r--drivers/oprofile/cpu_buffer.c7
-rw-r--r--drivers/oprofile/cpu_buffer.h1
-rw-r--r--drivers/oprofile/oprofile_stats.c4
-rw-r--r--drivers/pci/hotplug/acpiphp.h8
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c29
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c36
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c47
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c41
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c96
-rw-r--r--drivers/pci/hotplug/fakephp.c14
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c16
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c19
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c15
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c1
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c16
-rw-r--r--drivers/pci/pci-sysfs.c4
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c29
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c39
-rw-r--r--drivers/pnp/resource.c4
-rw-r--r--drivers/ps3/Makefile4
-rw-r--r--drivers/ps3/ps3-sys-manager.c (renamed from drivers/ps3/sys-manager.c)0
-rw-r--r--drivers/ps3/ps3-vuart.c (renamed from drivers/ps3/vuart.c)0
-rw-r--r--drivers/rtc/Kconfig10
-rw-r--r--drivers/rtc/hctosys.c4
-rw-r--r--drivers/rtc/interface.c4
-rw-r--r--drivers/rtc/rtc-dev.c12
-rw-r--r--drivers/rtc/rtc-ds1307.c93
-rw-r--r--drivers/rtc/rtc-ds1553.c2
-rw-r--r--drivers/rtc/rtc-ds1742.c5
-rw-r--r--drivers/rtc/rtc-m48t59.c3
-rw-r--r--drivers/rtc/rtc-sh.c6
-rw-r--r--drivers/rtc/rtc-stk17ta8.c2
-rw-r--r--drivers/s390/cio/css.c2
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/device_id.c45
-rw-r--r--drivers/s390/net/ctcmain.c45
-rw-r--r--drivers/scsi/aic94xx/aic94xx_sds.c4
-rw-r--r--drivers/scsi/ide-scsi.c22
-rw-r--r--drivers/scsi/zorro7xx.c3
-rw-r--r--drivers/serial/8250_pnp.c10
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/atmel_serial.c9
-rw-r--r--drivers/serial/crisv10.c1293
-rw-r--r--drivers/serial/crisv10.h146
-rw-r--r--drivers/serial/ip22zilog.c247
-rw-r--r--drivers/serial/pxa.c4
-rw-r--r--drivers/serial/sh-sci.h19
-rw-r--r--drivers/serial/uartlite.c10
-rw-r--r--drivers/sh/superhyway/superhyway.c7
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/atmel_spi.c2
-rw-r--r--drivers/spi/spi.c8
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c21
-rw-r--r--drivers/spi/spi_txx9.c40
-rw-r--r--drivers/spi/tle62x0.c5
-rw-r--r--drivers/ssb/main.c6
-rw-r--r--drivers/ssb/pcmcia.c56
-rw-r--r--drivers/usb/README6
-rw-r--r--drivers/usb/core/driver.c11
-rw-r--r--drivers/usb/core/hcd.c3
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/message.c36
-rw-r--r--drivers/usb/core/sysfs.c6
-rw-r--r--drivers/usb/core/usb.c25
-rw-r--r--drivers/usb/gadget/omap_udc.c6
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c16
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-hcd.c5
-rw-r--r--drivers/usb/image/microtek.c2
-rw-r--r--drivers/usb/misc/adutux.c262
-rw-r--r--drivers/usb/misc/usbled.c4
-rw-r--r--drivers/usb/serial/generic.c5
-rw-r--r--drivers/usb/serial/keyspan.c10
-rw-r--r--drivers/usb/serial/mos7840.c2
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h3
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/storage/scsiglue.c4
-rw-r--r--drivers/usb/storage/unusual_devs.h17
-rw-r--r--drivers/video/Kconfig13
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/atmel_lcdfb.c4
-rw-r--r--drivers/video/aty/radeon_base.c1
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/cyber2000fb.c2
-rw-r--r--drivers/video/efifb.c232
-rw-r--r--drivers/video/fb_ddc.c8
-rw-r--r--drivers/video/gbefb.c4
-rw-r--r--drivers/video/geode/lxfb.h2
-rw-r--r--drivers/video/imacfb.c4
-rw-r--r--drivers/video/ps3fb.c13
-rw-r--r--drivers/video/s1d13xxxfb.c5
-rw-r--r--drivers/video/sis/sis_main.c3
-rw-r--r--drivers/video/uvesafb.c6
-rw-r--r--drivers/virtio/virtio.c13
-rw-r--r--drivers/virtio/virtio_ring.c10
-rw-r--r--drivers/w1/masters/ds2490.c2
-rw-r--r--drivers/zorro/zorro-driver.c15
349 files changed, 7318 insertions, 4577 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index da3a08fa9e4..b9f923ef173 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -67,7 +67,21 @@ config ACPI_PROCFS
and functions which do not yet exist in /sys.
Say N to delete /proc/acpi/ files that have moved to /sys/
-
+config ACPI_PROCFS_POWER
+ bool "Deprecated power /proc/acpi folders"
+ depends on PROC_FS
+ default y
+ ---help---
+ For backwards compatibility, this option allows
+ deprecated power /proc/acpi/ folders to exist, even when
+ they have been replaced by functions in /sys.
+ The deprecated folders (and their replacements) include:
+ /proc/acpi/battery/* (/sys/class/power_supply/*)
+ /proc/acpi/ac_adapter/* (sys/class/power_supply/*)
+ This option has no effect on /proc/acpi/ folders
+ and functions, which do not yet exist in /sys
+
+ Say N to delete power /proc/acpi/ folders that have moved to /sys/
config ACPI_PROC_EVENT
bool "Deprecated /proc/acpi/event support"
depends on PROC_FS
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 54e3ab0e5fc..456446f9007 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -58,6 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
-obj-y += cm_sbs.o
+obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_SBS) += sbshc.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index e03de37a750..76ed4f52beb 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -27,8 +27,10 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
+#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#endif
#include <linux/power_supply.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -49,12 +51,15 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
+#ifdef CONFIG_ACPI_PROCFS_POWER
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+static int acpi_ac_open_fs(struct inode *inode, struct file *file);
+#endif
static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device, int type);
-static int acpi_ac_open_fs(struct inode *inode, struct file *file);
+static int acpi_ac_resume(struct acpi_device *device);
const static struct acpi_device_id ac_device_ids[] = {
{"ACPI0003", 0},
@@ -69,6 +74,7 @@ static struct acpi_driver acpi_ac_driver = {
.ops = {
.add = acpi_ac_add,
.remove = acpi_ac_remove,
+ .resume = acpi_ac_resume,
},
};
@@ -80,12 +86,15 @@ struct acpi_ac {
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
+#ifdef CONFIG_ACPI_PROCFS_POWER
static const struct file_operations acpi_ac_fops = {
.open = acpi_ac_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
+#endif
+
static int get_ac_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -127,6 +136,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
return 0;
}
+#ifdef CONFIG_ACPI_PROCFS_POWER
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
@@ -206,6 +216,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device)
return 0;
}
+#endif
/* --------------------------------------------------------------------------
Driver Model
@@ -264,7 +275,9 @@ static int acpi_ac_add(struct acpi_device *device)
if (result)
goto end;
+#ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_ac_add_fs(device);
+#endif
if (result)
goto end;
ac->charger.name = acpi_device_bid(device);
@@ -287,13 +300,30 @@ static int acpi_ac_add(struct acpi_device *device)
end:
if (result) {
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device);
+#endif
kfree(ac);
}
return result;
}
+static int acpi_ac_resume(struct acpi_device *device)
+{
+ struct acpi_ac *ac;
+ unsigned old_state;
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+ ac = acpi_driver_data(device);
+ old_state = ac->state;
+ if (acpi_ac_get_state(ac))
+ return 0;
+ if (old_state != ac->state)
+ kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
+ return 0;
+}
+
static int acpi_ac_remove(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
@@ -309,7 +339,9 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
ACPI_ALL_NOTIFY, acpi_ac_notify);
if (ac->charger.dev)
power_supply_unregister(&ac->charger);
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device);
+#endif
kfree(ac);
@@ -323,13 +355,17 @@ static int __init acpi_ac_init(void)
if (acpi_disabled)
return -ENODEV;
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir)
return -ENODEV;
+#endif
result = acpi_bus_register_driver(&acpi_ac_driver);
if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_ac_dir(acpi_ac_dir);
+#endif
return -ENODEV;
}
@@ -341,7 +377,9 @@ static void __exit acpi_ac_exit(void)
acpi_bus_unregister_driver(&acpi_ac_driver);
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_ac_dir(acpi_ac_dir);
+#endif
return;
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index c2ce0ad2169..7d6be23eff8 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -31,7 +31,7 @@
#include <linux/types.h>
#include <linux/jiffies.h>
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
@@ -63,7 +63,7 @@ static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
@@ -132,7 +132,7 @@ static int acpi_battery_technology(struct acpi_battery *battery)
return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}
-static int acpi_battery_update(struct acpi_battery *battery);
+static int acpi_battery_get_state(struct acpi_battery *battery);
static int acpi_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
@@ -140,10 +140,11 @@ static int acpi_battery_get_property(struct power_supply *psy,
{
struct acpi_battery *battery = to_acpi_battery(psy);
- if ((!acpi_battery_present(battery)) &&
- psp != POWER_SUPPLY_PROP_PRESENT)
+ if (acpi_battery_present(battery)) {
+ /* run battery update only if it is present */
+ acpi_battery_get_state(battery);
+ } else if (psp != POWER_SUPPLY_PROP_PRESENT)
return -ENODEV;
- acpi_battery_update(battery);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
if (battery->state & 0x01)
@@ -152,6 +153,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (battery->state == 0)
val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = acpi_battery_present(battery);
@@ -220,7 +223,7 @@ static enum power_supply_property energy_battery_props[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
};
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
inline char *acpi_battery_units(struct acpi_battery *battery)
{
return (battery->power_unit)?"mA":"mW";
@@ -457,6 +460,7 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
return;
device_remove_file(battery->bat.dev, &alarm_attr);
power_supply_unregister(&battery->bat);
+ battery->bat.dev = NULL;
}
static int acpi_battery_update(struct acpi_battery *battery)
@@ -477,7 +481,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
FS Interface (/proc)
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_print_info(struct seq_file *seq, int result)
@@ -784,7 +788,7 @@ static int acpi_battery_add(struct acpi_device *device)
acpi_driver_data(device) = battery;
mutex_init(&battery->lock);
acpi_battery_update(battery);
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_battery_add_fs(device);
if (result)
goto end;
@@ -802,7 +806,7 @@ static int acpi_battery_add(struct acpi_device *device)
device->status.battery_present ? "present" : "absent");
end:
if (result) {
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device);
#endif
kfree(battery);
@@ -821,7 +825,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
acpi_battery_notify);
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device);
#endif
sysfs_remove_battery(battery);
@@ -857,13 +861,13 @@ static int __init acpi_battery_init(void)
{
if (acpi_disabled)
return -ENODEV;
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_dir = acpi_lock_battery_dir();
if (!acpi_battery_dir)
return -ENODEV;
#endif
if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir);
#endif
return -ENODEV;
@@ -874,7 +878,7 @@ static int __init acpi_battery_init(void)
static void __exit acpi_battery_exit(void)
{
acpi_bus_unregister_driver(&acpi_battery_driver);
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir);
#endif
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 06b78e5e33a..d411017f8c0 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -47,6 +47,9 @@
#undef PREFIX
#define PREFIX "ACPI: EC: "
+/* Uncomment next line to get verbose print outs*/
+/* #define DEBUG */
+
/* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
@@ -75,7 +78,10 @@ enum {
EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
- EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */
+ EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */
+ EC_FLAGS_ADDRESS, /* Address is being written */
+ EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */
+ EC_FLAGS_WDATA, /* Data is being written */
};
static int acpi_ec_remove(struct acpi_device *device, int type);
@@ -131,21 +137,27 @@ static struct acpi_ec {
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{
- return inb(ec->command_addr);
+ u8 x = inb(ec->command_addr);
+ pr_debug(PREFIX "---> status = 0x%2x\n", x);
+ return x;
}
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{
+ u8 x = inb(ec->data_addr);
+ pr_debug(PREFIX "---> data = 0x%2x\n", x);
return inb(ec->data_addr);
}
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{
+ pr_debug(PREFIX "<--- command = 0x%2x\n", command);
outb(command, ec->command_addr);
}
static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{
+ pr_debug(PREFIX "<--- data = 0x%2x\n", data);
outb(data, ec->data_addr);
}
@@ -166,38 +178,54 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
{
+ int ret = 0;
+ if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) &&
+ test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags)))
+ force_poll = 1;
+ if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) &&
+ test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags)))
+ force_poll = 1;
if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
likely(!force_poll)) {
if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
msecs_to_jiffies(ACPI_EC_DELAY)))
- return 0;
+ goto end;
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (acpi_ec_check_status(ec, event)) {
- if (event == ACPI_EC_EVENT_OBF_1) {
- /* miss OBF = 1 GPE, don't expect it anymore */
- printk(KERN_INFO PREFIX "missing OBF_1 confirmation,"
- "switching to degraded mode.\n");
- set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags);
+ if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
+ /* miss address GPE, don't expect it anymore */
+ pr_info(PREFIX "missing address confirmation, "
+ "don't expect it any longer.\n");
+ set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags);
+ } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) {
+ /* miss write data GPE, don't expect it */
+ pr_info(PREFIX "missing write data confirmation, "
+ "don't expect it any longer.\n");
+ set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags);
} else {
/* missing GPEs, switch back to poll mode */
- printk(KERN_INFO PREFIX "missing IBF_1 confirmations,"
- "switch off interrupt mode.\n");
+ if (printk_ratelimit())
+ pr_info(PREFIX "missing confirmations, "
+ "switch off interrupt mode.\n");
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
- return 0;
+ goto end;
}
} else {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
while (time_before(jiffies, delay)) {
if (acpi_ec_check_status(ec, event))
- return 0;
+ goto end;
}
}
- printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
+ pr_err(PREFIX "acpi_ec_wait timeout,"
" status = %d, expect_event = %d\n",
acpi_ec_read_status(ec), event);
- return -ETIME;
+ ret = -ETIME;
+ end:
+ clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
+ return ret;
}
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
@@ -208,22 +236,26 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
int result = 0;
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_cmd(ec, command);
-
+ pr_debug(PREFIX "transaction start\n");
for (; wdata_len > 0; --wdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
- printk(KERN_ERR PREFIX
+ pr_err(PREFIX
"write_cmd timeout, command = %d\n", command);
goto end;
}
+ /* mark the address byte written to EC */
+ if (rdata_len + wdata_len > 1)
+ set_bit(EC_FLAGS_ADDRESS, &ec->flags);
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_data(ec, *(wdata++));
}
if (!rdata_len) {
+ set_bit(EC_FLAGS_WDATA, &ec->flags);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
- printk(KERN_ERR PREFIX
+ pr_err(PREFIX
"finish-write timeout, command = %d\n", command);
goto end;
}
@@ -231,12 +263,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
for (; rdata_len > 0; --rdata_len) {
- if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
- force_poll = 1;
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
if (result) {
- printk(KERN_ERR PREFIX "read timeout, command = %d\n",
- command);
+ pr_err(PREFIX "read timeout, command = %d\n", command);
goto end;
}
/* Don't expect GPE after last read */
@@ -245,6 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
*(rdata++) = acpi_ec_read_data(ec);
}
end:
+ pr_debug(PREFIX "transaction end\n");
return result;
}
@@ -273,8 +303,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) {
- printk(KERN_ERR PREFIX
- "input buffer is not empty, aborting transaction\n");
+ pr_err(PREFIX "input buffer is not empty, "
+ "aborting transaction\n");
goto end;
}
@@ -488,6 +518,7 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_status status = AE_OK;
struct acpi_ec *ec = data;
+ pr_debug(PREFIX "~~~> interrupt\n");
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
wake_up(&ec->wait);
@@ -498,8 +529,9 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_ec_gpe_query, ec);
} else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) {
/* this is non-query, must be confirmation */
- printk(KERN_INFO PREFIX "non-query interrupt received,"
- " switching to interrupt mode\n");
+ if (printk_ratelimit())
+ pr_info(PREFIX "non-query interrupt received,"
+ " switching to interrupt mode\n");
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
@@ -701,10 +733,10 @@ static void ec_remove_handlers(struct acpi_ec *ec)
{
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
- printk(KERN_ERR PREFIX "failed to remove space handler\n");
+ pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
- printk(KERN_ERR PREFIX "failed to remove gpe handler\n");
+ pr_err(PREFIX "failed to remove gpe handler\n");
ec->handlers_installed = 0;
}
@@ -747,9 +779,9 @@ static int acpi_ec_add(struct acpi_device *device)
first_ec = ec;
acpi_driver_data(device) = ec;
acpi_ec_add_fs(device);
- printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
+ pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
- printk(KERN_INFO PREFIX "driver started in %s mode\n",
+ pr_info(PREFIX "driver started in %s mode\n",
(test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");
return 0;
}
@@ -875,18 +907,26 @@ int __init acpi_ec_ecdt_probe(void)
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) {
- printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
+ pr_info(PREFIX "EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
} else {
+ /* This workaround is needed only on some broken machines,
+ * which require early EC, but fail to provide ECDT */
+ acpi_handle x;
printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
boot_ec, NULL);
/* Check that acpi_get_devices actually find something */
if (ACPI_FAILURE(status) || !boot_ec->handle)
goto error;
+ /* We really need to limit this workaround, the only ASUS,
+ * which needs it, has fake EC._INI method, so use it as flag.
+ */
+ if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x)))
+ goto error;
}
ret = ec_install_handlers(boot_ec);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index aabc6ca4a81..e3a673a0084 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -387,17 +387,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
if (!value)
value = &dummy;
- switch (width) {
- case 8:
+ *value = 0;
+ if (width <= 8) {
*(u8 *) value = inb(port);
- break;
- case 16:
+ } else if (width <= 16) {
*(u16 *) value = inw(port);
- break;
- case 32:
+ } else if (width <= 32) {
*(u32 *) value = inl(port);
- break;
- default:
+ } else {
BUG();
}
@@ -408,17 +405,13 @@ EXPORT_SYMBOL(acpi_os_read_port);
acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
{
- switch (width) {
- case 8:
+ if (width <= 8) {
outb(value, port);
- break;
- case 16:
+ } else if (width <= 16) {
outw(value, port);
- break;
- case 32:
+ } else if (width <= 32) {
outl(value, port);
- break;
- default:
+ } else {
BUG();
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 235a51e328c..e48ee4f8749 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -494,7 +494,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id)
if (apic_id == -1)
return apic_id;
- for (i = 0; i < NR_CPUS; ++i) {
+ for_each_possible_cpu(i) {
if (cpu_physical_id(i) == apic_id)
return i;
}
@@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
}
-#ifdef CONFIG_CPU_FREQ
- acpi_processor_ppc_has_changed(pr);
-#endif
- acpi_processor_get_throttling_info(pr);
- acpi_processor_get_limit_info(pr);
-
return 0;
}
@@ -638,7 +632,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
return 0;
}
- BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0));
+ BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
* Buggy BIOS check
@@ -647,7 +641,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
*/
if (processor_device_array[pr->id] != NULL &&
processor_device_array[pr->id] != device) {
- printk(KERN_WARNING "BIOS reported wrong ACPI id"
+ printk(KERN_WARNING "BIOS reported wrong ACPI id "
"for the processor\n");
return -ENODEV;
}
@@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
/* _PDC call should be done before doing anything else (if reqd.). */
arch_acpi_processor_init_pdc(pr);
acpi_processor_set_pdc(pr);
+#ifdef CONFIG_CPU_FREQ
+ acpi_processor_ppc_has_changed(pr);
+#endif
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
acpi_processor_power_init(pr, device);
@@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_processor *pr = data;
struct acpi_device *device = NULL;
-
+ int saved;
if (!pr)
return;
@@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
switch (event) {
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
+ saved = pr->performance_platform_limit;
acpi_processor_ppc_has_changed(pr);
+ if (saved == pr->performance_platform_limit)
+ break;
acpi_bus_generate_proc_event(device, event,
pr->performance_platform_limit);
acpi_bus_generate_netlink_event(device->pnp.device_class,
@@ -771,7 +774,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
pr = acpi_driver_data(device);
- if (pr->id >= NR_CPUS) {
+ if (pr->id >= nr_cpu_ids) {
kfree(pr);
return 0;
}
@@ -842,7 +845,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
if (!pr)
return -ENODEV;
- if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
+ if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) {
kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE);
}
return 0;
@@ -880,13 +883,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
break;
}
- if (pr->id >= 0 && (pr->id < NR_CPUS)) {
+ if (pr->id >= 0 && (pr->id < nr_cpu_ids)) {
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
}
result = acpi_processor_start(device);
- if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
+ if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) {
kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
} else {
printk(KERN_ERR PREFIX "Device [%s] failed to start\n",
@@ -909,7 +912,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
return;
}
- if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
+ if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id)))
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
break;
default:
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f996d0e3768..b1fbee3f7fe 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
}
+static void acpi_safe_halt(void)
+{
+ current_thread_info()->status &= ~TS_POLLING;
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
+ if (!need_resched())
+ safe_halt();
+ current_thread_info()->status |= TS_POLLING;
+}
+
#ifndef CONFIG_CPU_IDLE
static void
@@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr,
return;
}
-static void acpi_safe_halt(void)
-{
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we
- * test NEED_RESCHED:
- */
- smp_mb();
- if (!need_resched())
- safe_halt();
- current_thread_info()->status |= TS_POLLING;
-}
-
static atomic_t c3_cpu_count;
/* Common C-state entry for C2, C3, .. */
@@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx);
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
- if (!need_resched())
- safe_halt();
- current_thread_info()->status |= TS_POLLING;
+ acpi_safe_halt();
cx->usage++;
@@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
u32 t1, t2;
+ int sleep_ticks = 0;
+
pr = processors[smp_processor_id()];
if (unlikely(!pr))
@@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
ACPI_FLUSH_CPU_CACHE();
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ /* Tell the scheduler that we are going deep-idle: */
+ sched_clock_idle_sleep_event();
acpi_state_timer_broadcast(pr, cx, 1);
acpi_idle_do_entry(cx);
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
/* TSC could halt in idle, so notify users */
mark_tsc_unstable("TSC halts in idle");;
#endif
+ sleep_ticks = ticks_elapsed(t1, t2);
+
+ /* Tell the scheduler how much we idled: */
+ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
local_irq_enable();
current_thread_info()->status |= TS_POLLING;
@@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0);
- cx->time += ticks_elapsed(t1, t2);
+ cx->time += sleep_ticks;
return ticks_elapsed_in_us(t1, t2);
}
@@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
u32 t1, t2;
+ int sleep_ticks = 0;
+
pr = processors[smp_processor_id()];
if (unlikely(!pr))
@@ -1471,6 +1473,15 @@ 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 (dev->safe_state) {
+ return dev->safe_state->enter(dev, dev->safe_state);
+ } else {
+ acpi_safe_halt();
+ return 0;
+ }
+ }
+
local_irq_disable();
current_thread_info()->status &= ~TS_POLLING;
/*
@@ -1485,38 +1496,45 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
return 0;
}
+ /* Tell the scheduler that we are going deep-idle: */
+ sched_clock_idle_sleep_event();
/*
* Must be done before busmaster disable as we might need to
* access HPET !
*/
acpi_state_timer_broadcast(pr, cx, 1);
- if (acpi_idle_bm_check()) {
- cx = pr->power.bm_state;
-
- acpi_idle_update_bm_rld(pr, cx);
-
- t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
- acpi_idle_do_entry(cx);
- t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
- } else {
- acpi_idle_update_bm_rld(pr, cx);
+ acpi_idle_update_bm_rld(pr, cx);
+ /*
+ * disable bus master
+ * bm_check implies we need ARB_DIS
+ * !bm_check implies we need cache flush
+ * bm_control implies whether we can do ARB_DIS
+ *
+ * That leaves a case where bm_check is set and bm_control is
+ * not set. In that case we cannot do much, we enter C3
+ * without doing anything.
+ */
+ if (pr->flags.bm_check && pr->flags.bm_control) {
spin_lock(&c3_lock);
c3_cpu_count++;
/* Disable bus master arbitration when all CPUs are in C3 */
if (c3_cpu_count == num_online_cpus())
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
spin_unlock(&c3_lock);
+ } else if (!pr->flags.bm_check) {
+ ACPI_FLUSH_CPU_CACHE();
+ }
- t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
- acpi_idle_do_entry(cx);
- t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ acpi_idle_do_entry(cx);
+ t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+ /* Re-enable bus master arbitration */
+ if (pr->flags.bm_check && pr->flags.bm_control) {
spin_lock(&c3_lock);
- /* Re-enable bus master arbitration */
- if (c3_cpu_count == num_online_cpus())
- acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
c3_cpu_count--;
spin_unlock(&c3_lock);
}
@@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
/* TSC could halt in idle, so notify users */
mark_tsc_unstable("TSC halts in idle");
#endif
+ sleep_ticks = ticks_elapsed(t1, t2);
+ /* Tell the scheduler how much we idled: */
+ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
local_irq_enable();
current_thread_info()->status |= TS_POLLING;
@@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0);
- cx->time += ticks_elapsed(t1, t2);
+ cx->time += sleep_ticks;
return ticks_elapsed_in_us(t1, t2);
}
@@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
case ACPI_STATE_C1:
state->flags |= CPUIDLE_FLAG_SHALLOW;
state->enter = acpi_idle_enter_c1;
+ dev->safe_state = state;
break;
case ACPI_STATE_C2:
state->flags |= CPUIDLE_FLAG_BALANCED;
state->flags |= CPUIDLE_FLAG_TIME_VALID;
state->enter = acpi_idle_enter_simple;
+ dev->safe_state = state;
break;
case ACPI_STATE_C3:
@@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
if (!count)
return -EINVAL;
- /* find the deepest state that can handle active BM */
- if (pr->flags.bm_check) {
- for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++)
- if (pr->power.states[i].type == ACPI_STATE_C3)
- break;
- pr->power.bm_state = &pr->power.states[i-1];
- }
-
return 0;
}
@@ -1658,6 +1673,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
if (!first_run) {
dmi_check_system(processor_power_dmi_table);
+ max_cstate = acpi_processor_cstate_check(max_cstate);
if (max_cstate < ACPI_C_STATES_MAX)
printk(KERN_NOTICE
"ACPI: processor limited to max C-state %d\n",
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 0b8204e7082..c26c61fb36c 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -70,7 +70,55 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
{
- return acpi_processor_get_platform_limit(pr);
+ int result = 0;
+ int throttling_limit;
+ int current_state;
+ struct acpi_processor_limit *limit;
+ int target_state;
+
+ result = acpi_processor_get_platform_limit(pr);
+ if (result) {
+ /* Throttling Limit is unsupported */
+ return result;
+ }
+
+ throttling_limit = pr->throttling_platform_limit;
+ if (throttling_limit >= pr->throttling.state_count) {
+ /* Uncorrect Throttling Limit */
+ return -EINVAL;
+ }
+
+ current_state = pr->throttling.state;
+ if (current_state > throttling_limit) {
+ /*
+ * The current state can meet the requirement of
+ * _TPC limit. But it is reasonable that OSPM changes
+ * t-states from high to low for better performance.
+ * Of course the limit condition of thermal
+ * and user should be considered.
+ */
+ limit = &pr->limit;
+ target_state = throttling_limit;
+ if (limit->thermal.tx > target_state)
+ target_state = limit->thermal.tx;
+ if (limit->user.tx > target_state)
+ target_state = limit->user.tx;
+ } else if (current_state == throttling_limit) {
+ /*
+ * Unnecessary to change the throttling state
+ */
+ return 0;
+ } else {
+ /*
+ * If the current state is lower than the limit of _TPC, it
+ * will be forced to switch to the throttling state defined
+ * by throttling_platfor_limit.
+ * Because the previous state meets with the limit condition
+ * of thermal and user, it is unnecessary to check it again.
+ */
+ target_state = throttling_limit;
+ }
+ return acpi_processor_set_throttling(pr, target_state);
}
/*
@@ -83,6 +131,7 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *ptc = NULL;
union acpi_object obj = { 0 };
+ struct acpi_processor_throttling *throttling;
status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer);
if (ACPI_FAILURE(status)) {
@@ -134,6 +183,22 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
memcpy(&pr->throttling.status_register, obj.buffer.pointer,
sizeof(struct acpi_ptc_register));
+ throttling = &pr->throttling;
+
+ if ((throttling->control_register.bit_width +
+ throttling->control_register.bit_offset) > 32) {
+ printk(KERN_ERR PREFIX "Invalid _PTC control register\n");
+ result = -EFAULT;
+ goto end;
+ }
+
+ if ((throttling->status_register.bit_width +
+ throttling->status_register.bit_offset) > 32) {
+ printk(KERN_ERR PREFIX "Invalid _PTC status register\n");
+ result = -EFAULT;
+ goto end;
+ }
+
end:
kfree(buffer.pointer);
@@ -328,44 +393,132 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
return 0;
}
-static int acpi_read_throttling_status(struct acpi_processor_throttling
- *throttling)
+#ifdef CONFIG_X86
+static int acpi_throttling_rdmsr(struct acpi_processor *pr,
+ acpi_integer * value)
{
- int value = -1;
+ struct cpuinfo_x86 *c;
+ u64 msr_high, msr_low;
+ unsigned int cpu;
+ u64 msr = 0;
+ int ret = -1;
+
+ cpu = pr->id;
+ c = &cpu_data(cpu);
+
+ if ((c->x86_vendor != X86_VENDOR_INTEL) ||
+ !cpu_has(c, X86_FEATURE_ACPI)) {
+ printk(KERN_ERR PREFIX
+ "HARDWARE addr space,NOT supported yet\n");
+ } else {
+ msr_low = 0;
+ msr_high = 0;
+ rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL,
+ (u32 *)&msr_low , (u32 *) &msr_high);
+ msr = (msr_high << 32) | msr_low;
+ *value = (acpi_integer) msr;
+ ret = 0;
+ }
+ return ret;
+}
+
+static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value)
+{
+ struct cpuinfo_x86 *c;
+ unsigned int cpu;
+ int ret = -1;
+ u64 msr;
+
+ cpu = pr->id;
+ c = &cpu_data(cpu);
+
+ if ((c->x86_vendor != X86_VENDOR_INTEL) ||
+ !cpu_has(c, X86_FEATURE_ACPI)) {
+ printk(KERN_ERR PREFIX
+ "HARDWARE addr space,NOT supported yet\n");
+ } else {
+ msr = value;
+ wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL,
+ msr & 0xffffffff, msr >> 32);
+ ret = 0;
+ }
+ return ret;
+}
+#else
+static int acpi_throttling_rdmsr(struct acpi_processor *pr,
+ acpi_integer * value)
+{
+ printk(KERN_ERR PREFIX
+ "HARDWARE addr space,NOT supported yet\n");
+ return -1;
+}
+
+static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value)
+{
+ printk(KERN_ERR PREFIX
+ "HARDWARE addr space,NOT supported yet\n");
+ return -1;
+}
+#endif
+
+static int acpi_read_throttling_status(struct acpi_processor *pr,
+ acpi_integer *value)
+{
+ u32 bit_width, bit_offset;
+ u64 ptc_value;
+ u64 ptc_mask;
+ struct acpi_processor_throttling *throttling;
+ int ret = -1;
+
+ throttling = &pr->throttling;
switch (throttling->status_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
+ ptc_value = 0;
+ bit_width = throttling->status_register.bit_width;
+ bit_offset = throttling->status_register.bit_offset;
+
acpi_os_read_port((acpi_io_address) throttling->status_register.
- address, &value,
- (u32) throttling->status_register.bit_width *
- 8);
+ address, (u32 *) &ptc_value,
+ (u32) (bit_width + bit_offset));
+ ptc_mask = (1 << bit_width) - 1;
+ *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask);
+ ret = 0;
break;
case ACPI_ADR_SPACE_FIXED_HARDWARE:
- printk(KERN_ERR PREFIX
- "HARDWARE addr space,NOT supported yet\n");
+ ret = acpi_throttling_rdmsr(pr, value);
break;
default:
printk(KERN_ERR PREFIX "Unknown addr space %d\n",
(u32) (throttling->status_register.space_id));
}
- return value;
+ return ret;
}
-static int acpi_write_throttling_state(struct acpi_processor_throttling
- *throttling, int value)
+static int acpi_write_throttling_state(struct acpi_processor *pr,
+ acpi_integer value)
{
+ u32 bit_width, bit_offset;
+ u64 ptc_value;
+ u64 ptc_mask;
+ struct acpi_processor_throttling *throttling;
int ret = -1;
+ throttling = &pr->throttling;
switch (throttling->control_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
+ bit_width = throttling->control_register.bit_width;
+ bit_offset = throttling->control_register.bit_offset;
+ ptc_mask = (1 << bit_width) - 1;
+ ptc_value = value & ptc_mask;
+
acpi_os_write_port((acpi_io_address) throttling->
- control_register.address, value,
- (u32) throttling->control_register.
- bit_width * 8);
+ control_register.address,
+ (u32) (ptc_value << bit_offset),
+ (u32) (bit_width + bit_offset));
ret = 0;
break;
case ACPI_ADR_SPACE_FIXED_HARDWARE:
- printk(KERN_ERR PREFIX
- "HARDWARE addr space,NOT supported yet\n");
+ ret = acpi_throttling_wrmsr(pr, value);
break;
default:
printk(KERN_ERR PREFIX "Unknown addr space %d\n",
@@ -374,7 +527,8 @@ static int acpi_write_throttling_state(struct acpi_processor_throttling
return ret;
}
-static int acpi_get_throttling_state(struct acpi_processor *pr, int value)
+static int acpi_get_throttling_state(struct acpi_processor *pr,
+ acpi_integer value)
{
int i;
@@ -390,22 +544,26 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, int value)
return i;
}
-static int acpi_get_throttling_value(struct acpi_processor *pr, int state)
+static int acpi_get_throttling_value(struct acpi_processor *pr,
+ int state, acpi_integer *value)
{
- int value = -1;
+ int ret = -1;
+
if (state >= 0 && state <= pr->throttling.state_count) {
struct acpi_processor_tx_tss *tx =
(struct acpi_processor_tx_tss *)&(pr->throttling.
states_tss[state]);
- value = tx->control;
+ *value = tx->control;
+ ret = 0;
}
- return value;
+ return ret;
}
static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
{
int state = 0;
- u32 value = 0;
+ int ret;
+ acpi_integer value;
if (!pr)
return -EINVAL;
@@ -415,8 +573,9 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
pr->throttling.state = 0;
local_irq_disable();
- value = acpi_read_throttling_status(&pr->throttling);
- if (value >= 0) {
+ value = 0;
+ ret = acpi_read_throttling_status(pr, &value);
+ if (ret >= 0) {
state = acpi_get_throttling_state(pr, value);
pr->throttling.state = state;
}
@@ -430,6 +589,40 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
return pr->throttling.acpi_processor_get_throttling(pr);
}
+static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
+{
+ int i, step;
+
+ if (!pr->throttling.address) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
+ return -EINVAL;
+ } else if (!pr->throttling.duty_width) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
+ return -EINVAL;
+ }
+ /* TBD: Support duty_cycle values that span bit 4. */
+ else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
+ printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n");
+ return -EINVAL;
+ }
+
+ pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width;
+
+ /*
+ * Compute state values. Note that throttling displays a linear power
+ * performance relationship (at 50% performance the CPU will consume
+ * 50% power). Values are in 1/10th of a percent to preserve accuracy.
+ */
+
+ step = (1000 / pr->throttling.state_count);
+
+ for (i = 0; i < pr->throttling.state_count; i++) {
+ pr->throttling.states[i].performance = 1000 - step * i;
+ pr->throttling.states[i].power = 1000 - step * i;
+ }
+ return 0;
+}
+
static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
int state)
{
@@ -506,7 +699,8 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
int state)
{
- u32 value = 0;
+ int ret;
+ acpi_integer value;
if (!pr)
return -EINVAL;
@@ -524,10 +718,10 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
return -EPERM;
local_irq_disable();
-
- value = acpi_get_throttling_value(pr, state);
- if (value >= 0) {
- acpi_write_throttling_state(&pr->throttling, value);
+ value = 0;
+ ret = acpi_get_throttling_value(pr, state, &value);
+ if (ret >= 0) {
+ acpi_write_throttling_state(pr, value);
pr->throttling.state = state;
}
local_irq_enable();
@@ -543,8 +737,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
int acpi_processor_get_throttling_info(struct acpi_processor *pr)
{
int result = 0;
- int step = 0;
- int i = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
@@ -563,6 +755,8 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
acpi_processor_get_throttling_states(pr) ||
acpi_processor_get_platform_limit(pr))
{
+ if (acpi_processor_get_fadt_info(pr))
+ return 0;
pr->throttling.acpi_processor_get_throttling =
&acpi_processor_get_throttling_fadt;
pr->throttling.acpi_processor_set_throttling =
@@ -576,19 +770,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
acpi_processor_get_tsd(pr);
- if (!pr->throttling.address) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
- return 0;
- } else if (!pr->throttling.duty_width) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
- return 0;
- }
- /* TBD: Support duty_cycle values that span bit 4. */
- else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
- printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n");
- return 0;
- }
-
/*
* PIIX4 Errata: We don't support throttling on the original PIIX4.
* This shouldn't be an issue as few (if any) mobile systems ever
@@ -600,21 +781,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
return 0;
}
- pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width;
-
- /*
- * Compute state values. Note that throttling displays a linear power/
- * performance relationship (at 50% performance the CPU will consume
- * 50% power). Values are in 1/10th of a percent to preserve accuracy.
- */
-
- step = (1000 / pr->throttling.state_count);
-
- for (i = 0; i < pr->throttling.state_count; i++) {
- pr->throttling.states[i].performance = step * i;
- pr->throttling.states[i].power = step * i;
- }
-
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
pr->throttling.state_count));
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 90fd09c65f9..6045cdbe176 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -29,7 +29,7 @@
#include <linux/moduleparam.h>
#include <linux/kernel.h>
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
@@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
struct acpi_battery {
struct power_supply bat;
struct acpi_sbs *sbs;
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
struct proc_dir_entry *proc_entry;
#endif
unsigned long update_time;
@@ -113,6 +113,7 @@ struct acpi_battery {
u16 spec;
u8 id;
u8 present:1;
+ u8 have_sysfs_alarm:1;
};
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
@@ -122,7 +123,7 @@ struct acpi_sbs {
struct acpi_device *device;
struct acpi_smb_hc *hc;
struct mutex lock;
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
struct proc_dir_entry *charger_entry;
#endif
struct acpi_battery battery[MAX_SBS_BAT];
@@ -468,7 +469,7 @@ static struct device_attribute alarm_attr = {
FS Interface (/proc/acpi)
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
/* Generic Routines */
static int
acpi_sbs_add_fs(struct proc_dir_entry **dir,
@@ -789,7 +790,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
return result;
sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
battery->name, &acpi_battery_info_fops,
&acpi_battery_state_fops, &acpi_battery_alarm_fops,
@@ -808,7 +809,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
}
battery->bat.get_property = acpi_sbs_battery_get_property;
result = power_supply_register(&sbs->device->dev, &battery->bat);
- device_create_file(battery->bat.dev, &alarm_attr);
+ if (result)
+ goto end;
+ result = device_create_file(battery->bat.dev, &alarm_attr);
+ if (result)
+ goto end;
+ battery->have_sysfs_alarm = 1;
+ end:
printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
battery->name, sbs->battery->present ? "present" : "absent");
@@ -817,14 +824,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
{
- if (sbs->battery[id].bat.dev)
- device_remove_file(sbs->battery[id].bat.dev, &alarm_attr);
- power_supply_unregister(&sbs->battery[id].bat);
-#ifdef CONFIG_ACPI_PROCFS
- if (sbs->battery[id].proc_entry) {
- acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
- acpi_battery_dir);
+ struct acpi_battery *battery = &sbs->battery[id];
+
+ if (battery->bat.dev) {
+ if (battery->have_sysfs_alarm)
+ device_remove_file(battery->bat.dev, &alarm_attr);
+ power_supply_unregister(&battery->bat);
}
+#ifdef CONFIG_ACPI_PROCFS_POWER
+ if (battery->proc_entry)
+ acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);
#endif
}
@@ -835,7 +844,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
result = acpi_ac_get_present(sbs);
if (result)
goto end;
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
ACPI_AC_DIR_NAME, NULL,
&acpi_ac_state_fops, NULL, sbs);
@@ -859,7 +868,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs)
{
if (sbs->charger.dev)
power_supply_unregister(&sbs->charger);
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
if (sbs->charger_entry)
acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
#endif
@@ -965,7 +974,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
static void acpi_sbs_rmdirs(void)
{
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
if (acpi_ac_dir) {
acpi_unlock_ac_dir(acpi_ac_dir);
acpi_ac_dir = NULL;
@@ -1004,7 +1013,7 @@ static int __init acpi_sbs_init(void)
if (acpi_disabled)
return -ENODEV;
-#ifdef CONFIG_ACPI_PROCFS
+#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir)
return -ENODEV;
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index 5f1d85f2ffe..010f19652f8 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -449,7 +449,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
/* XSDT has NULL entry, RSDT is used */
address = rsdt_address;
table_entry_size = sizeof(u32);
- ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry,"
+ ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, "
"using RSDT"));
}
}
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index a736ef7bdee..9e8c20c6a0b 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -591,9 +591,12 @@ static int __init toshiba_acpi_init(void)
NULL,
&toshiba_backlight_data);
if (IS_ERR(toshiba_backlight_device)) {
+ int ret = PTR_ERR(toshiba_backlight_device);
+
printk(KERN_ERR "Could not register toshiba backlight device\n");
toshiba_backlight_device = NULL;
toshiba_acpi_exit();
+ return ret;
}
toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bac956b30c5..44a0d9ba9bd 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/input.h>
@@ -135,8 +136,8 @@ struct acpi_video_bus {
u8 attached_count;
struct acpi_video_bus_cap cap;
struct acpi_video_bus_flags flags;
- struct semaphore sem;
struct list_head video_device_list;
+ struct mutex device_list_lock; /* protects video_device_list */
struct proc_dir_entry *dir;
struct input_dev *input;
char phys[32]; /* for input device */
@@ -896,7 +897,7 @@ acpi_video_device_write_brightness(struct file *file,
{
struct seq_file *m = file->private_data;
struct acpi_video_device *dev = m->private;
- char str[4] = { 0 };
+ char str[5] = { 0 };
unsigned int level = 0;
int i;
@@ -1436,9 +1437,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
return -ENODEV;
}
- down(&video->sem);
+ mutex_lock(&video->device_list_lock);
list_add_tail(&data->entry, &video->video_device_list);
- up(&video->sem);
+ mutex_unlock(&video->device_list_lock);
acpi_video_device_add_fs(device);
@@ -1462,12 +1463,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
static void acpi_video_device_rebind(struct acpi_video_bus *video)
{
- struct list_head *node, *next;
- list_for_each_safe(node, next, &video->video_device_list) {
- struct acpi_video_device *dev =
- container_of(node, struct acpi_video_device, entry);
+ struct acpi_video_device *dev;
+
+ mutex_lock(&video->device_list_lock);
+
+ list_for_each_entry(dev, &video->video_device_list, entry)
acpi_video_device_bind(video, dev);
- }
+
+ mutex_unlock(&video->device_list_lock);
}
/*
@@ -1592,30 +1595,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
{
- struct list_head *node, *next;
+ struct list_head *node;
struct acpi_video_device *dev = NULL;
struct acpi_video_device *dev_next = NULL;
struct acpi_video_device *dev_prev = NULL;
unsigned long state;
int status = 0;
+ mutex_lock(&video->device_list_lock);
- list_for_each_safe(node, next, &video->video_device_list) {
+ list_for_each(node, &video->video_device_list) {
dev = container_of(node, struct acpi_video_device, entry);
status = acpi_video_device_get_state(dev, &state);
if (state & 0x2) {
- dev_next =
- container_of(node->next, struct acpi_video_device,
- entry);
- dev_prev =
- container_of(node->prev, struct acpi_video_device,
- entry);
+ dev_next = container_of(node->next,
+ struct acpi_video_device, entry);
+ dev_prev = container_of(node->prev,
+ struct acpi_video_device, entry);
goto out;
}
}
+
dev_next = container_of(node->next, struct acpi_video_device, entry);
dev_prev = container_of(node->prev, struct acpi_video_device, entry);
- out:
+
+ out:
+ mutex_unlock(&video->device_list_lock);
+
switch (event) {
case ACPI_VIDEO_NOTIFY_CYCLE:
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
@@ -1691,24 +1697,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
struct acpi_device *device)
{
int status = 0;
- struct list_head *node, *next;
-
+ struct acpi_device *dev;
acpi_video_device_enumerate(video);
- list_for_each_safe(node, next, &device->children) {
- struct acpi_device *dev =
- list_entry(node, struct acpi_device, node);
-
- if (!dev)
- continue;
+ list_for_each_entry(dev, &device->children, node) {
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Cant attach device"));
continue;
}
-
}
return status;
}
@@ -1724,9 +1723,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
video = device->video;
- down(&video->sem);
- list_del(&device->entry);
- up(&video->sem);
acpi_video_device_remove_fs(device->dev);
status = acpi_remove_notify_handler(device->dev->handle,
@@ -1734,32 +1730,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
acpi_video_device_notify);
backlight_device_unregister(device->backlight);
video_output_unregister(device->output_dev);
+
return 0;
}
static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{
int status;
- struct list_head *node, *next;
+ struct acpi_video_device *dev, *next;
+ mutex_lock(&video->device_list_lock);
- list_for_each_safe(node, next, &video->video_device_list) {
- struct acpi_video_device *data =
- list_entry(node, struct acpi_video_device, entry);
- if (!data)
- continue;
+ list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
- status = acpi_video_bus_put_one_device(data);
+ status = acpi_video_bus_put_one_device(dev);
if (ACPI_FAILURE(status))
printk(KERN_WARNING PREFIX
"hhuuhhuu bug in acpi video driver.\n");
- if (data->brightness)
- kfree(data->brightness->levels);
- kfree(data->brightness);
- kfree(data);
+ if (dev->brightness) {
+ kfree(dev->brightness->levels);
+ kfree(dev->brightness);
+ }
+ list_del(&dev->entry);
+ kfree(dev);
}
+ mutex_unlock(&video->device_list_lock);
+
return 0;
}
@@ -1782,9 +1780,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
struct input_dev *input;
int keycode;
-
- printk("video bus notify\n");
-
if (!video)
return;
@@ -1897,14 +1892,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
static int instance;
static int acpi_video_bus_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_video_bus *video = NULL;
+ acpi_status status;
+ struct acpi_video_bus *video;
struct input_dev *input;
-
-
- if (!device)
- return -EINVAL;
+ int error;
video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
if (!video)
@@ -1923,15 +1914,15 @@ static int acpi_video_bus_add(struct acpi_device *device)
acpi_driver_data(device) = video;
acpi_video_bus_find_cap(video);
- result = acpi_video_bus_check(video);
- if (result)
- goto end;
+ error = acpi_video_bus_check(video);
+ if (error)
+ goto err_free_video;
- result = acpi_video_bus_add_fs(device);
- if (result)
- goto end;
+ error = acpi_video_bus_add_fs(device);
+ if (error)
+ goto err_free_video;
- init_MUTEX(&video->sem);
+ mutex_init(&video->device_list_lock);
INIT_LIST_HEAD(&video->video_device_list);
acpi_video_bus_get_devices(video, device);
@@ -1943,16 +1934,15 @@ static int acpi_video_bus_add(struct acpi_device *device)
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing notify handler\n"));
- acpi_video_bus_stop_devices(video);
- acpi_video_bus_put_devices(video);
- kfree(video->attached_array);
- acpi_video_bus_remove_fs(device);
- result = -ENODEV;
- goto end;
+ error = -ENODEV;
+ goto err_stop_video;
}
-
video->input = input = input_allocate_device();
+ if (!input) {
+ error = -ENOMEM;
+ goto err_uninstall_notify;
+ }
snprintf(video->phys, sizeof(video->phys),
"%s/video/input0", acpi_device_hid(video->device));
@@ -1961,6 +1951,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
input->phys = video->phys;
input->id.bustype = BUS_HOST;
input->id.product = 0x06;
+ input->dev.parent = &device->dev;
input->evbit[0] = BIT(EV_KEY);
set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
set_bit(KEY_VIDEO_NEXT, input->keybit);
@@ -1971,18 +1962,10 @@ static int acpi_video_bus_add(struct acpi_device *device)
set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
set_bit(KEY_DISPLAY_OFF, input->keybit);
set_bit(KEY_UNKNOWN, input->keybit);
- result = input_register_device(input);
- if (result) {
- acpi_remove_notify_handler(video->device->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_video_bus_notify);
- acpi_video_bus_stop_devices(video);
- acpi_video_bus_put_devices(video);
- kfree(video->attached_array);
- acpi_video_bus_remove_fs(device);
- goto end;
- }
+ error = input_register_device(input);
+ if (error)
+ goto err_free_input_dev;
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
@@ -1990,11 +1973,23 @@ static int acpi_video_bus_add(struct acpi_device *device)
video->flags.rom ? "yes" : "no",
video->flags.post ? "yes" : "no");
- end:
- if (result)
- kfree(video);
+ return 0;
+
+ err_free_input_dev:
+ input_free_device(input);
+ err_uninstall_notify:
+ acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+ acpi_video_bus_notify);
+ err_stop_video:
+ acpi_video_bus_stop_devices(video);
+ acpi_video_bus_put_devices(video);
+ kfree(video->attached_array);
+ acpi_video_bus_remove_fs(device);
+ err_free_video:
+ kfree(video);
+ acpi_driver_data(device) = NULL;
- return result;
+ return error;
}
static int acpi_video_bus_remove(struct acpi_device *device, int type)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index f08cca21702..b538e1d22bf 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -119,18 +119,19 @@ enum {
PIIX_80C_SEC = (1 << 7) | (1 << 6),
/* controller IDs */
- piix_pata_33 = 0, /* PIIX4 at 33Mhz */
- ich_pata_33 = 1, /* ICH up to UDMA 33 only */
- ich_pata_66 = 2, /* ICH up to 66 Mhz */
- ich_pata_100 = 3, /* ICH up to UDMA 100 */
- ich5_sata = 5,
- ich6_sata = 6,
- ich6_sata_ahci = 7,
- ich6m_sata_ahci = 8,
- ich8_sata_ahci = 9,
- piix_pata_mwdma = 10, /* PIIX3 MWDMA only */
- tolapai_sata_ahci = 11,
- ich9_2port_sata = 12,
+ piix_pata_mwdma = 0, /* PIIX3 MWDMA only */
+ piix_pata_33, /* PIIX4 at 33Mhz */
+ ich_pata_33, /* ICH up to UDMA 33 only */
+ ich_pata_66, /* ICH up to 66 Mhz */
+ ich_pata_100, /* ICH up to UDMA 100 */
+ ich5_sata,
+ ich6_sata,
+ ich6_sata_ahci,
+ ich6m_sata_ahci,
+ ich8_sata_ahci,
+ ich8_2port_sata,
+ ich8m_apple_sata_ahci, /* locks up on second port enable */
+ tolapai_sata_ahci,
/* constants for mapping table */
P0 = 0, /* port 0 */
@@ -239,19 +240,21 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* SATA Controller 1 IDE (ICH8) */
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller 2 IDE (ICH8) */
- { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
+ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* Mobile SATA Controller IDE (ICH8M) */
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* Mobile SATA Controller IDE (ICH8M), Apple */
+ { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata_ahci },
/* SATA Controller IDE (ICH9) */
{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (ICH9) */
- { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
+ { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (ICH9) */
- { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
+ { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (ICH9M) */
- { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
+ { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (ICH9M) */
- { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata },
+ { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (ICH9M) */
{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
/* SATA Controller IDE (Tolapai) */
@@ -427,7 +430,7 @@ static const struct piix_map_db ich6m_map_db = {
static const struct piix_map_db ich8_map_db = {
.mask = 0x3,
- .port_enable = 0x3,
+ .port_enable = 0xf,
.map = {
/* PM PS SM SS MAP */
{ P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */
@@ -437,7 +440,7 @@ static const struct piix_map_db ich8_map_db = {
},
};
-static const struct piix_map_db tolapai_map_db = {
+static const struct piix_map_db ich8_2port_map_db = {
.mask = 0x3,
.port_enable = 0x3,
.map = {
@@ -449,7 +452,19 @@ static const struct piix_map_db tolapai_map_db = {
},
};
-static const struct piix_map_db ich9_2port_map_db = {
+static const struct piix_map_db ich8m_apple_map_db = {
+ .mask = 0x3,
+ .port_enable = 0x1,
+ .map = {
+ /* PM PS SM SS MAP */
+ { P0, NA, NA, NA }, /* 00b */
+ { RV, RV, RV, RV },
+ { P0, P2, IDE, IDE }, /* 10b */
+ { RV, RV, RV, RV },
+ },
+};
+
+static const struct piix_map_db tolapai_map_db = {
.mask = 0x3,
.port_enable = 0x3,
.map = {
@@ -467,11 +482,21 @@ static const struct piix_map_db *piix_map_db_table[] = {
[ich6_sata_ahci] = &ich6_map_db,
[ich6m_sata_ahci] = &ich6m_map_db,
[ich8_sata_ahci] = &ich8_map_db,
+ [ich8_2port_sata] = &ich8_2port_map_db,
+ [ich8m_apple_sata_ahci] = &ich8m_apple_map_db,
[tolapai_sata_ahci] = &tolapai_map_db,
- [ich9_2port_sata] = &ich9_2port_map_db,
};
static struct ata_port_info piix_port_info[] = {
+ [piix_pata_mwdma] = /* PIIX3 MWDMA only */
+ {
+ .sht = &piix_sht,
+ .flags = PIIX_PATA_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+ .port_ops = &piix_pata_ops,
+ },
+
[piix_pata_33] = /* PIIX4 at 33MHz */
{
.sht = &piix_sht,
@@ -565,13 +590,15 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- [piix_pata_mwdma] = /* PIIX3 MWDMA only */
+ [ich8_2port_sata] =
{
.sht = &piix_sht,
- .flags = PIIX_PATA_FLAGS,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+ PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
- .port_ops = &piix_pata_ops,
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
},
[tolapai_sata_ahci] =
@@ -585,7 +612,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- [ich9_2port_sata] =
+ [ich8m_apple_sata_ahci] =
{
.sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@@ -595,6 +622,7 @@ static struct ata_port_info piix_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
+
};
static struct pci_bits piix_enable_bits[] = {
@@ -939,6 +967,13 @@ static int piix_broken_suspend(void)
},
},
{
+ .ident = "TECRA M3",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M3"),
+ },
+ },
+ {
.ident = "TECRA M5",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -953,6 +988,20 @@ static int piix_broken_suspend(void)
},
},
{
+ .ident = "TECRA A8",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"),
+ },
+ },
+ {
+ .ident = "Satellite R25",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R25"),
+ },
+ },
+ {
.ident = "Satellite U200",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -960,6 +1009,20 @@ static int piix_broken_suspend(void)
},
},
{
+ .ident = "Satellite U200",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U200"),
+ },
+ },
+ {
+ .ident = "Satellite Pro U200",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"),
+ },
+ },
+ {
.ident = "Satellite U205",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -967,6 +1030,13 @@ static int piix_broken_suspend(void)
},
},
{
+ .ident = "SATELLITE U205",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"),
+ },
+ },
+ {
.ident = "Portege M500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -1079,12 +1149,12 @@ static int piix_disable_ahci(struct pci_dev *pdev)
if (!mmio)
return -ENOMEM;
- tmp = readl(mmio + AHCI_GLOBAL_CTL);
+ tmp = ioread32(mmio + AHCI_GLOBAL_CTL);
if (tmp & AHCI_ENABLE) {
tmp &= ~AHCI_ENABLE;
- writel(tmp, mmio + AHCI_GLOBAL_CTL);
+ iowrite32(tmp, mmio + AHCI_GLOBAL_CTL);
- tmp = readl(mmio + AHCI_GLOBAL_CTL);
+ tmp = ioread32(mmio + AHCI_GLOBAL_CTL);
if (tmp & AHCI_ENABLE)
rc = -EIO;
}
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 08a52dd45fb..545ea865ceb 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm);
*
* RETURNS:
* Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
- * contain valid data. -errno on other errors.
+ * contain valid data.
*/
static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
void **ptr_to_free)
@@ -339,7 +339,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING,
"_GTF evaluation failed (AE 0x%x)\n",
status);
- rc = -EIO;
}
goto out_free;
}
@@ -359,7 +358,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING,
"_GTF unexpected object type 0x%x\n",
out_obj->type);
- rc = -EINVAL;
goto out_free;
}
@@ -367,7 +365,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
ata_dev_printk(dev, KERN_WARNING,
"unexpected _GTF length (%d)\n",
out_obj->buffer.length);
- rc = -EINVAL;
goto out_free;
}
@@ -511,10 +508,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev)
int gtf_count, i, rc;
/* get taskfiles */
- rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
- if (rc < 0)
- return rc;
- gtf_count = rc;
+ gtf_count = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
/* execute them */
for (i = 0, rc = 0; i < gtf_count; i++) {
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index ec3ce120a51..b514a80f137 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -30,6 +30,14 @@
* Hardware documentation available from http://www.t13.org/ and
* http://www.sata-io.org/
*
+ * Standards documents from:
+ * http://www.t13.org (ATA standards, PCI DMA IDE spec)
+ * http://www.t10.org (SCSI MMC - for ATAPI MMC)
+ * http://www.sata-io.org (SATA)
+ * http://www.compactflash.org (CF)
+ * http://www.qic.org (QIC157 - Tape and DSC)
+ * http://www.ce-ata.org (CE-ATA: not supported)
+ *
*/
#include <linux/kernel.h>
@@ -2307,8 +2315,10 @@ int ata_dev_configure(struct ata_device *dev)
}
if ((dev->class == ATA_DEV_ATAPI) &&
- (atapi_command_packet_set(id) == TYPE_TAPE))
+ (atapi_command_packet_set(id) == TYPE_TAPE)) {
dev->max_sectors = ATA_MAX_SECTORS_TAPE;
+ dev->horkage |= ATA_HORKAGE_STUCK_ERR;
+ }
if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
@@ -2581,81 +2591,6 @@ void sata_print_link_status(struct ata_link *link)
}
/**
- * __sata_phy_reset - Wake/reset a low-level SATA PHY
- * @ap: SATA port associated with target SATA PHY.
- *
- * This function issues commands to standard SATA Sxxx
- * PHY registers, to wake up the phy (and device), and
- * clear any reset condition.
- *
- * LOCKING:
- * PCI/etc. bus probe sem.
- *
- */
-void __sata_phy_reset(struct ata_port *ap)
-{
- struct ata_link *link = &ap->link;
- unsigned long timeout = jiffies + (HZ * 5);
- u32 sstatus;
-
- if (ap->flags & ATA_FLAG_SATA_RESET) {
- /* issue phy wake/reset */
- sata_scr_write_flush(link, SCR_CONTROL, 0x301);
- /* Couldn't find anything in SATA I/II specs, but
- * AHCI-1.1 10.4.2 says at least 1 ms. */
- mdelay(1);
- }
- /* phy wake/clear reset */
- sata_scr_write_flush(link, SCR_CONTROL, 0x300);
-
- /* wait for phy to become ready, if necessary */
- do {
- msleep(200);
- sata_scr_read(link, SCR_STATUS, &sstatus);
- if ((sstatus & 0xf) != 1)
- break;
- } while (time_before(jiffies, timeout));
-
- /* print link status */
- sata_print_link_status(link);
-
- /* TODO: phy layer with polling, timeouts, etc. */
- if (!ata_link_offline(link))
- ata_port_probe(ap);
- else
- ata_port_disable(ap);
-
- if (ap->flags & ATA_FLAG_DISABLED)
- return;
-
- if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
- ata_port_disable(ap);
- return;
- }
-
- ap->cbl = ATA_CBL_SATA;
-}
-
-/**
- * sata_phy_reset - Reset SATA bus.
- * @ap: SATA port associated with target SATA PHY.
- *
- * This function resets the SATA bus, and then probes
- * the bus for devices.
- *
- * LOCKING:
- * PCI/etc. bus probe sem.
- *
- */
-void sata_phy_reset(struct ata_port *ap)
-{
- __sata_phy_reset(ap);
- if (ap->flags & ATA_FLAG_DISABLED)
- return;
- ata_bus_reset(ap);
-}
-
-/**
* ata_dev_pair - return other device on cable
* @adev: device
*
@@ -3373,14 +3308,20 @@ void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
* to clear 0xff after reset. For example, HHD424020F7SV00
* iVDR needs >= 800ms while. Quantum GoVault needs even more
* than that.
+ *
+ * Note that some PATA controllers (pata_ali) explode if
+ * status register is read more than once when there's no
+ * device attached.
*/
- while (1) {
- u8 status = ata_chk_status(ap);
+ if (ap->flags & ATA_FLAG_SATA) {
+ while (1) {
+ u8 status = ata_chk_status(ap);
- if (status != 0xff || time_after(jiffies, deadline))
- return;
+ if (status != 0xff || time_after(jiffies, deadline))
+ return;
- msleep(50);
+ msleep(50);
+ }
}
}
@@ -4244,6 +4185,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices which get the IVB wrong */
{ "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
{ "TSSTcorp CDDVDW SH-S202J", "SB00", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202J", "SB01", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, },
+ { "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, },
/* End Marker */
{ }
@@ -5484,11 +5428,19 @@ fsm_start:
* let the EH abort the command or reset the device.
*/
if (unlikely(status & (ATA_ERR | ATA_DF))) {
- ata_port_printk(ap, KERN_WARNING, "DRQ=1 with device "
- "error, dev_stat 0x%X\n", status);
- qc->err_mask |= AC_ERR_HSM;
- ap->hsm_task_state = HSM_ST_ERR;
- goto fsm_start;
+ /* Some ATAPI tape drives forget to clear the ERR bit
+ * when doing the next command (mostly request sense).
+ * We ignore ERR here to workaround and proceed sending
+ * the CDB.
+ */
+ if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+ ata_port_printk(ap, KERN_WARNING,
+ "DRQ=1 with device error, "
+ "dev_stat 0x%X\n", status);
+ qc->err_mask |= AC_ERR_HSM;
+ ap->hsm_task_state = HSM_ST_ERR;
+ goto fsm_start;
+ }
}
/* Send the CDB (atapi) or the first data block (ata pio out).
@@ -6821,19 +6773,6 @@ static void ata_host_release(struct device *gendev, void *res)
if (!ap)
continue;
- if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop)
- ap->ops->port_stop(ap);
- }
-
- if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop)
- host->ops->host_stop(host);
-
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
-
- if (!ap)
- continue;
-
if (ap->scsi_host)
scsi_host_put(ap->scsi_host);
@@ -6960,6 +6899,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
return host;
}
+static void ata_host_stop(struct device *gendev, void *res)
+{
+ struct ata_host *host = dev_get_drvdata(gendev);
+ int i;
+
+ WARN_ON(!(host->flags & ATA_HOST_STARTED));
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap->ops->port_stop)
+ ap->ops->port_stop(ap);
+ }
+
+ if (host->ops->host_stop)
+ host->ops->host_stop(host);
+}
+
/**
* ata_host_start - start and freeze ports of an ATA host
* @host: ATA host to start ports for
@@ -6978,6 +6935,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
*/
int ata_host_start(struct ata_host *host)
{
+ int have_stop = 0;
+ void *start_dr = NULL;
int i, rc;
if (host->flags & ATA_HOST_STARTED)
@@ -6989,18 +6948,35 @@ int ata_host_start(struct ata_host *host)
if (!host->ops && !ata_port_is_dummy(ap))
host->ops = ap->ops;
+ if (ap->ops->port_stop)
+ have_stop = 1;
+ }
+
+ if (host->ops->host_stop)
+ have_stop = 1;
+
+ if (have_stop) {
+ start_dr = devres_alloc(ata_host_stop, 0, GFP_KERNEL);
+ if (!start_dr)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
if (ap->ops->port_start) {
rc = ap->ops->port_start(ap);
if (rc) {
- ata_port_printk(ap, KERN_ERR, "failed to "
- "start port (errno=%d)\n", rc);
+ if (rc != -ENODEV)
+ dev_printk(KERN_ERR, host->dev, "failed to start port %d (errno=%d)\n", i, rc);
goto err_out;
}
}
-
ata_eh_freeze_port(ap);
}
+ if (start_dr)
+ devres_add(host->dev, start_dr);
host->flags |= ATA_HOST_STARTED;
return 0;
@@ -7011,6 +6987,7 @@ int ata_host_start(struct ata_host *host)
if (ap->ops->port_stop)
ap->ops->port_stop(ap);
}
+ devres_free(start_dr);
return rc;
}
@@ -7178,6 +7155,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
* request IRQ and register it. This helper takes necessasry
* arguments and performs the three steps in one go.
*
+ * An invalid IRQ skips the IRQ registration and expects the host to
+ * have set polling mode on the port. In this case, @irq_handler
+ * should be NULL.
+ *
* LOCKING:
* Inherited from calling layer (may sleep).
*
@@ -7194,6 +7175,12 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc)
return rc;
+ /* Special case for polling mode */
+ if (!irq) {
+ WARN_ON(irq_handler);
+ return ata_host_register(host, sht);
+ }
+
rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags,
dev_driver_string(host->dev), host);
if (rc)
@@ -7611,8 +7598,6 @@ EXPORT_SYMBOL_GPL(ata_dev_disable);
EXPORT_SYMBOL_GPL(sata_set_spd);
EXPORT_SYMBOL_GPL(sata_link_debounce);
EXPORT_SYMBOL_GPL(sata_link_resume);
-EXPORT_SYMBOL_GPL(sata_phy_reset);
-EXPORT_SYMBOL_GPL(__sata_phy_reset);
EXPORT_SYMBOL_GPL(ata_bus_reset);
EXPORT_SYMBOL_GPL(ata_std_prereset);
EXPORT_SYMBOL_GPL(ata_std_softreset);
@@ -7683,7 +7668,6 @@ EXPORT_SYMBOL_GPL(ata_port_desc);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(ata_port_pbar_desc);
#endif /* CONFIG_PCI */
-EXPORT_SYMBOL_GPL(ata_eng_timeout);
EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
EXPORT_SYMBOL_GPL(ata_link_abort);
EXPORT_SYMBOL_GPL(ata_port_abort);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index ed8813b222a..e6605f03864 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -559,101 +559,6 @@ void ata_port_wait_eh(struct ata_port *ap)
}
}
-/**
- * ata_qc_timeout - Handle timeout of queued command
- * @qc: Command that timed out
- *
- * Some part of the kernel (currently, only the SCSI layer)
- * has noticed that the active command on port @ap has not
- * completed after a specified length of time. Handle this
- * condition by disabling DMA (if necessary) and completing
- * transactions, with error if necessary.
- *
- * This also handles the case of the "lost interrupt", where
- * for some reason (possibly hardware bug, possibly driver bug)
- * an interrupt was not delivered to the driver, even though the
- * transaction completed successfully.
- *
- * TODO: kill this function once old EH is gone.
- *
- * LOCKING:
- * Inherited from SCSI layer (none, can sleep)
- */
-static void ata_qc_timeout(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- u8 host_stat = 0, drv_stat;
- unsigned long flags;
-
- DPRINTK("ENTER\n");
-
- ap->hsm_task_state = HSM_ST_IDLE;
-
- spin_lock_irqsave(ap->lock, flags);
-
- switch (qc->tf.protocol) {
-
- case ATA_PROT_DMA:
- case ATA_PROT_ATAPI_DMA:
- host_stat = ap->ops->bmdma_status(ap);
-
- /* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(qc);
-
- /* fall through */
-
- default:
- ata_altstatus(ap);
- drv_stat = ata_chk_status(ap);
-
- /* ack bmdma irq events */
- ap->ops->irq_clear(ap);
-
- ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
- "stat 0x%x host_stat 0x%x\n",
- qc->tf.command, drv_stat, host_stat);
-
- /* complete taskfile transaction */
- qc->err_mask |= AC_ERR_TIMEOUT;
- break;
- }
-
- spin_unlock_irqrestore(ap->lock, flags);
-
- ata_eh_qc_complete(qc);
-
- DPRINTK("EXIT\n");
-}
-
-/**
- * ata_eng_timeout - Handle timeout of queued command
- * @ap: Port on which timed-out command is active
- *
- * Some part of the kernel (currently, only the SCSI layer)
- * has noticed that the active command on port @ap has not
- * completed after a specified length of time. Handle this
- * condition by disabling DMA (if necessary) and completing
- * transactions, with error if necessary.
- *
- * This also handles the case of the "lost interrupt", where
- * for some reason (possibly hardware bug, possibly driver bug)
- * an interrupt was not delivered to the driver, even though the
- * transaction completed successfully.
- *
- * TODO: kill this function once old EH is gone.
- *
- * LOCKING:
- * Inherited from SCSI layer (none, can sleep)
- */
-void ata_eng_timeout(struct ata_port *ap)
-{
- DPRINTK("ENTER\n");
-
- ata_qc_timeout(ata_qc_from_tag(ap, ap->link.active_tag));
-
- DPRINTK("EXIT\n");
-}
-
static int ata_eh_nr_in_flight(struct ata_port *ap)
{
unsigned int tag;
@@ -1945,30 +1850,54 @@ static void ata_eh_link_report(struct ata_link *link)
ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "");
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
- static const char *dma_str[] = {
- [DMA_BIDIRECTIONAL] = "bidi",
- [DMA_TO_DEVICE] = "out",
- [DMA_FROM_DEVICE] = "in",
- [DMA_NONE] = "",
- };
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
+ const u8 *cdb = qc->cdb;
+ char data_buf[20] = "";
+ char cdb_buf[70] = "";
if (!(qc->flags & ATA_QCFLAG_FAILED) ||
qc->dev->link != link || !qc->err_mask)
continue;
+ if (qc->dma_dir != DMA_NONE) {
+ static const char *dma_str[] = {
+ [DMA_BIDIRECTIONAL] = "bidi",
+ [DMA_TO_DEVICE] = "out",
+ [DMA_FROM_DEVICE] = "in",
+ };
+ static const char *prot_str[] = {
+ [ATA_PROT_PIO] = "pio",
+ [ATA_PROT_DMA] = "dma",
+ [ATA_PROT_NCQ] = "ncq",
+ [ATA_PROT_ATAPI] = "pio",
+ [ATA_PROT_ATAPI_DMA] = "dma",
+ };
+
+ snprintf(data_buf, sizeof(data_buf), " %s %u %s",
+ prot_str[qc->tf.protocol], qc->nbytes,
+ dma_str[qc->dma_dir]);
+ }
+
+ if (is_atapi_taskfile(&qc->tf))
+ snprintf(cdb_buf, sizeof(cdb_buf),
+ "cdb %02x %02x %02x %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n ",
+ cdb[0], cdb[1], cdb[2], cdb[3],
+ cdb[4], cdb[5], cdb[6], cdb[7],
+ cdb[8], cdb[9], cdb[10], cdb[11],
+ cdb[12], cdb[13], cdb[14], cdb[15]);
+
ata_dev_printk(qc->dev, KERN_ERR,
"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
- "tag %d cdb 0x%x data %u %s\n "
+ "tag %d%s\n %s"
"res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
"Emask 0x%x (%s)%s\n",
cmd->command, cmd->feature, cmd->nsect,
cmd->lbal, cmd->lbam, cmd->lbah,
cmd->hob_feature, cmd->hob_nsect,
cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah,
- cmd->device, qc->tag, qc->cdb[0], qc->nbytes,
- dma_str[qc->dma_dir],
+ cmd->device, qc->tag, data_buf, cdb_buf,
res->command, res->feature, res->nsect,
res->lbal, res->lbam, res->lbah,
res->hob_feature, res->hob_nsect,
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 94144ed50a6..a883bb03d4c 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2485,11 +2485,40 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
if (!using_pio && ata_check_atapi_dma(qc))
using_pio = 1;
- /* Some controller variants snoop this value for Packet transfers
- to do state machine and FIFO management. Thus we want to set it
- properly, and for DMA where it is effectively meaningless */
+ /* Some controller variants snoop this value for Packet
+ * transfers to do state machine and FIFO management. Thus we
+ * want to set it properly, and for DMA where it is
+ * effectively meaningless.
+ */
nbytes = min(qc->nbytes, (unsigned int)63 * 1024);
+ /* Most ATAPI devices which honor transfer chunk size don't
+ * behave according to the spec when odd chunk size which
+ * matches the transfer length is specified. If the number of
+ * bytes to transfer is 2n+1. According to the spec, what
+ * should happen is to indicate that 2n+1 is going to be
+ * transferred and transfer 2n+2 bytes where the last byte is
+ * padding.
+ *
+ * In practice, this doesn't happen. ATAPI devices first
+ * indicate and transfer 2n bytes and then indicate and
+ * transfer 2 bytes where the last byte is padding.
+ *
+ * This inconsistency confuses several controllers which
+ * perform PIO using DMA such as Intel AHCIs and sil3124/32.
+ * These controllers use actual number of transferred bytes to
+ * update DMA poitner and transfer of 4n+2 bytes make those
+ * controller push DMA pointer by 4n+4 bytes because SATA data
+ * FISes are aligned to 4 bytes. This causes data corruption
+ * and buffer overrun.
+ *
+ * Always setting nbytes to even number solves this problem
+ * because then ATAPI devices don't have to split data at 2n
+ * boundaries.
+ */
+ if (nbytes & 0x1)
+ nbytes++;
+
qc->tf.lbam = (nbytes & 0xFF);
qc->tf.lbah = (nbytes >> 8);
@@ -2869,7 +2898,8 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
xlat_func = NULL;
if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
/* relay SCSI command to ATAPI device */
- if (unlikely(scmd->cmd_len > dev->cdb_len))
+ int len = COMMAND_SIZE(scsi_op);
+ if (unlikely(len > scmd->cmd_len || len > dev->cdb_len))
goto bad_cdb_len;
xlat_func = atapi_xlat;
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 364534e7aff..8caf9afc8b9 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -63,6 +63,9 @@ static int ali_cable_override(struct pci_dev *pdev)
/* Fujitsu P2000 */
if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
return 1;
+ /* Mitac 8317 (Winbook-A) and relatives */
+ if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
+ return 1;
/* Systems by DMI */
if (dmi_check_system(cable_dmi_table))
return 1;
@@ -282,6 +285,21 @@ static void ali_lock_sectors(struct ata_device *adev)
adev->max_sectors = 255;
}
+/**
+ * ali_check_atapi_dma - DMA check for most ALi controllers
+ * @adev: Device
+ *
+ * Called to decide whether commands should be sent by DMA or PIO
+ */
+
+static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ /* If its not a media command, its not worth it */
+ if (qc->nbytes < 2048)
+ return -EOPNOTSUPP;
+ return 0;
+}
+
static struct scsi_host_template ali_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -378,6 +396,7 @@ static struct ata_port_operations ali_c2_port_ops = {
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
+ .check_atapi_dma = ali_check_atapi_dma,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
@@ -415,6 +434,7 @@ static struct ata_port_operations ali_c5_port_ops = {
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
+ .check_atapi_dma = ali_check_atapi_dma,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
index bb250a48e27..67e574de31e 100644
--- a/drivers/ata/pata_at32.c
+++ b/drivers/ata/pata_at32.c
@@ -28,7 +28,7 @@
#include <asm/arch/smc.h>
#define DRV_NAME "pata_at32"
-#define DRV_VERSION "0.0.2"
+#define DRV_VERSION "0.0.3"
/*
* CompactFlash controller memory layout relative to the base address:
@@ -64,6 +64,8 @@
* Mode 2 | 8.3 | 240 ns | 0x07
* Mode 3 | 11.1 | 180 ns | 0x0f
* Mode 4 | 16.7 | 120 ns | 0x1f
+ *
+ * Alter PIO_MASK below according to table to set maximal PIO mode.
*/
#define PIO_MASK (0x1f)
@@ -85,36 +87,40 @@ struct at32_ide_info {
*/
static int pata_at32_setup_timing(struct device *dev,
struct at32_ide_info *info,
- const struct ata_timing *timing)
+ const struct ata_timing *ata)
{
- /* These two values are found through testing */
- const int min_recover = 25;
- const int ncs_hold = 15;
-
struct smc_config *smc = &info->smc;
+ struct smc_timing timing;
int active;
int recover;
+ memset(&timing, 0, sizeof(struct smc_timing));
+
/* Total cycle time */
- smc->read_cycle = timing->cyc8b;
+ timing.read_cycle = ata->cyc8b;
/* DIOR <= CFIOR timings */
- smc->nrd_setup = timing->setup;
- smc->nrd_pulse = timing->act8b;
+ timing.nrd_setup = ata->setup;
+ timing.nrd_pulse = ata->act8b;
+ timing.nrd_recover = ata->rec8b;
+
+ /* Convert nanosecond timing to clock cycles */
+ smc_set_timing(smc, &timing);
- /* Compute recover, extend total cycle if needed */
- active = smc->nrd_setup + smc->nrd_pulse;
+ /* Add one extra cycle setup due to signal ring */
+ smc->nrd_setup = smc->nrd_setup + 1;
+
+ active = smc->nrd_setup + smc->nrd_pulse;
recover = smc->read_cycle - active;
- if (recover < min_recover) {
- smc->read_cycle = active + min_recover;
- recover = min_recover;
- }
+ /* Need at least two cycles recovery */
+ if (recover < 2)
+ smc->read_cycle = active + 2;
/* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
- smc->ncs_read_setup = 0;
- smc->ncs_read_pulse = active + ncs_hold;
+ smc->ncs_read_setup = 1;
+ smc->ncs_read_pulse = smc->read_cycle - 2;
/* Write timings same as read timings */
smc->write_cycle = smc->read_cycle;
@@ -123,11 +129,13 @@ static int pata_at32_setup_timing(struct device *dev,
smc->ncs_write_setup = smc->ncs_read_setup;
smc->ncs_write_pulse = smc->ncs_read_pulse;
- /* Do some debugging output */
- dev_dbg(dev, "SMC: C=%d S=%d P=%d R=%d NCSS=%d NCSP=%d NCSR=%d\n",
+ /* Do some debugging output of ATA and SMC timings */
+ dev_dbg(dev, "ATA: C=%d S=%d P=%d R=%d\n",
+ ata->cyc8b, ata->setup, ata->act8b, ata->rec8b);
+
+ dev_dbg(dev, "SMC: C=%d S=%d P=%d NS=%d NP=%d\n",
smc->read_cycle, smc->nrd_setup, smc->nrd_pulse,
- recover, smc->ncs_read_setup, smc->ncs_read_pulse,
- smc->read_cycle - smc->ncs_read_pulse);
+ smc->ncs_read_setup, smc->ncs_read_pulse);
/* Finally, configure the SMC */
return smc_set_configuration(info->cs, smc);
@@ -182,7 +190,6 @@ static struct scsi_host_template at32_sht = {
};
static struct ata_port_operations at32_port_ops = {
- .port_disable = ata_port_disable,
.set_piomode = pata_at32_set_piomode,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -203,7 +210,6 @@ static struct ata_port_operations at32_port_ops = {
.irq_clear = pata_at32_irq_clear,
.irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
.port_start = ata_sff_port_start,
};
@@ -223,8 +229,7 @@ static int __init pata_at32_init_one(struct device *dev,
/* Setup ATA bindings */
ap->ops = &at32_port_ops;
ap->pio_mask = PIO_MASK;
- ap->flags = ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS
- | ATA_FLAG_PIO_POLLING;
+ ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS;
/*
* Since all 8-bit taskfile transfers has to go on the lower
@@ -357,12 +362,12 @@ static int __init pata_at32_probe(struct platform_device *pdev)
info->smc.tdf_mode = 0; /* TDF optimization disabled */
info->smc.tdf_cycles = 0; /* No TDF wait cycles */
- /* Setup ATA timing */
+ /* Setup SMC to ATA timing */
ret = pata_at32_setup_timing(dev, info, &initial_timing);
if (ret)
goto err_setup_timing;
- /* Setup ATA addresses */
+ /* Map ATA address space */
ret = -ENOMEM;
info->ide_addr = devm_ioremap(dev, info->res_ide.start, 16);
info->alt_addr = devm_ioremap(dev, info->res_alt.start, 16);
@@ -373,7 +378,7 @@ static int __init pata_at32_probe(struct platform_device *pdev)
pata_at32_debug_bus(dev, info);
#endif
- /* Register ATA device */
+ /* Setup and register ATA device */
ret = pata_at32_init_one(dev, info);
if (ret)
goto err_ata_device;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index b5e38426b81..088a41f4e65 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1145,13 +1145,13 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
unsigned short int_status = ATAPI_GET_INT_STATUS(base);
if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) {
- host_stat = ATA_DMA_ACTIVE;
+ host_stat |= ATA_DMA_ACTIVE;
}
if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) {
- host_stat = ATA_DMA_INTR;
+ host_stat |= ATA_DMA_INTR;
}
if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) {
- host_stat = ATA_DMA_ERR;
+ host_stat |= ATA_DMA_ERR;
}
return host_stat;
@@ -1489,6 +1489,8 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
int board_idx = 0;
struct resource *res;
struct ata_host *host;
+ unsigned int fsclk = get_sclk();
+ int udma_mode = 5;
const struct ata_port_info *ppi[] =
{ &bfin_port_info[board_idx], NULL };
@@ -1507,6 +1509,11 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
if (res == NULL)
return -EINVAL;
+ while (bfin_port_info[board_idx].udma_mask>0 && udma_fsclk[udma_mode] > fsclk) {
+ udma_mode--;
+ bfin_port_info[board_idx].udma_mask >>= 1;
+ }
+
/*
* Now that that's out of the way, wire up the port..
*/
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 3816b8605e0..46dc70e0dee 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -329,7 +329,7 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
/* Restore state */
pci_write_config_byte(pdev, 0x5B, scr2);
- if (ata66 & (1 << ap->port_no))
+ if (ata66 & (2 >> ap->port_no))
ap->cbl = ATA_CBL_PATA40;
else
ap->cbl = ATA_CBL_PATA80;
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 88ab0e1d353..4320e798632 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -75,13 +75,16 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
struct ata_host *host;
struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
+ int irq = 0;
+ irq_handler_t handler = NULL;
if (pnp_port_valid(idev, 0) == 0)
return -ENODEV;
- /* FIXME: Should selected polled PIO here not fail */
- if (pnp_irq_valid(idev, 0) == 0)
- return -ENODEV;
+ if (pnp_irq_valid(idev, 0)) {
+ irq = pnp_irq(idev, 0);
+ handler = ata_interrupt;
+ }
/* allocate host */
host = ata_host_alloc(&idev->dev, 1);
@@ -115,7 +118,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
(unsigned long long)pnp_port_start(idev, 1));
/* activate */
- return ata_host_activate(host, pnp_irq(idev, 0), ata_interrupt, 0,
+ return ata_host_activate(host, irq, handler, 0,
&isapnp_sht);
}
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 225a7223a72..5b8174d9406 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -80,11 +80,10 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
* actually do our cable checking etc. Thankfully we don't need
* to do the plumbing for other cases.
*/
- switch (port_map[port])
- {
+ switch (port_map[port]) {
case PORT_PATA0:
- if (control & (1 << 5))
- return 0;
+ if ((control & (1 << 5)) == 0)
+ return -ENOENT;
if (control & (1 << 3)) /* 40/80 pin primary */
ap->cbl = ATA_CBL_PATA40;
else
@@ -93,7 +92,7 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
case PORT_PATA1:
/* Bit 21 is set if the port is enabled */
if ((control5 & (1 << 21)) == 0)
- return 0;
+ return -ENOENT;
if (control5 & (1 << 19)) /* 40/80 pin secondary */
ap->cbl = ATA_CBL_PATA40;
else
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index fc72a965643..ac03a90a616 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -1,7 +1,7 @@
/*
* Generic platform device PATA driver
*
- * Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2006 - 2007 Paul Mundt
*
* Based on pata_pcmcia:
*
@@ -22,7 +22,7 @@
#include <linux/pata_platform.h>
#define DRV_NAME "pata_platform"
-#define DRV_VERSION "1.1"
+#define DRV_VERSION "1.2"
static int pio_mask = 1;
@@ -120,15 +120,20 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
* Register a platform bus IDE interface. Such interfaces are PIO and we
* assume do not support IRQ sharing.
*
- * Platform devices are expected to contain 3 resources per port:
+ * Platform devices are expected to contain at least 2 resources per port:
*
* - I/O Base (IORESOURCE_IO or IORESOURCE_MEM)
* - CTL Base (IORESOURCE_IO or IORESOURCE_MEM)
+ *
+ * and optionally:
+ *
* - IRQ (IORESOURCE_IRQ)
*
* If the base resources are both mem types, the ioremap() is handled
* here. For IORESOURCE_IO, it's assumed that there's no remapping
* necessary.
+ *
+ * If no IRQ resource is present, PIO polling mode is used instead.
*/
static int __devinit pata_platform_probe(struct platform_device *pdev)
{
@@ -137,11 +142,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
struct ata_port *ap;
struct pata_platform_info *pp_info;
unsigned int mmio;
+ int irq;
/*
* Simple resource validation ..
*/
- if (unlikely(pdev->num_resources != 3)) {
+ if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
dev_err(&pdev->dev, "invalid number of resources\n");
return -EINVAL;
}
@@ -173,6 +179,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
(ctl_res->flags == IORESOURCE_MEM));
/*
+ * And the IRQ
+ */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ irq = 0; /* no irq */
+
+ /*
* Now that that's out of the way, wire up the port..
*/
host = ata_host_alloc(&pdev->dev, 1);
@@ -185,6 +198,14 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
ap->flags |= ATA_FLAG_SLAVE_POSS;
/*
+ * Use polling mode if there's no IRQ
+ */
+ if (!irq) {
+ ap->flags |= ATA_FLAG_PIO_POLLING;
+ ata_port_desc(ap, "no IRQ, using PIO polling");
+ }
+
+ /*
* Handle the MMIO case
*/
if (mmio) {
@@ -213,9 +234,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
(unsigned long long)ctl_res->start);
/* activate */
- return ata_host_activate(host, platform_get_irq(pdev, 0),
- ata_interrupt, pp_info ? pp_info->irq_flags
- : 0, &pata_platform_sht);
+ return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
+ pp_info ? pp_info->irq_flags : 0,
+ &pata_platform_sht);
}
/**
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 5c1e9cb59ec..503245a1eaf 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -33,7 +33,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_sil680"
-#define DRV_VERSION "0.4.7"
+#define DRV_VERSION "0.4.8"
#define SIL680_MMIO_BAR 5
@@ -94,34 +94,6 @@ static int sil680_cable_detect(struct ata_port *ap) {
}
/**
- * sil680_bus_reset - reset the SIL680 bus
- * @link: ATA link to reset
- * @deadline: deadline jiffies for the operation
- *
- * Perform the SIL680 housekeeping when doing an ATA bus reset
- */
-
-static int sil680_bus_reset(struct ata_link *link, unsigned int *classes,
- unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- unsigned long addr = sil680_selreg(ap, 0);
- u8 reset;
-
- pci_read_config_byte(pdev, addr, &reset);
- pci_write_config_byte(pdev, addr, reset | 0x03);
- udelay(25);
- pci_write_config_byte(pdev, addr, reset);
- return ata_std_softreset(link, classes, deadline);
-}
-
-static void sil680_error_handler(struct ata_port *ap)
-{
- ata_bmdma_drive_eh(ap, ata_std_prereset, sil680_bus_reset, NULL, ata_std_postreset);
-}
-
-/**
* sil680_set_piomode - set initial PIO mode data
* @ap: ATA interface
* @adev: ATA device
@@ -249,7 +221,7 @@ static struct ata_port_operations sil680_port_ops = {
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
- .error_handler = sil680_error_handler,
+ .error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = sil680_cable_detect,
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 3b5be77e861..87546d9f1ca 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -55,6 +55,7 @@ static const struct sis_laptop sis_laptop[] = {
/* devid, subvendor, subdev */
{ 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
{ 0x5513, 0x1734, 0x105F }, /* FSC Amilo A1630 */
+ { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */
/* end marker */
{ 0, }
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index a43f64d2775..8d864e5e97e 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -164,10 +164,14 @@ enum {
MV_PCI_ERR_ATTRIBUTE = 0x1d48,
MV_PCI_ERR_COMMAND = 0x1d50,
- PCI_IRQ_CAUSE_OFS = 0x1d58,
- PCI_IRQ_MASK_OFS = 0x1d5c,
+ PCI_IRQ_CAUSE_OFS = 0x1d58,
+ PCI_IRQ_MASK_OFS = 0x1d5c,
PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */
+ PCIE_IRQ_CAUSE_OFS = 0x1900,
+ PCIE_IRQ_MASK_OFS = 0x1910,
+ PCIE_UNMASK_ALL_IRQS = 0x70a, /* assorted bits */
+
HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
HC_MAIN_IRQ_MASK_OFS = 0x1d64,
PORT0_ERR = (1 << 0), /* shift by port # */
@@ -303,6 +307,7 @@ enum {
MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */
MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */
MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */
+ MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */
/* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
@@ -388,7 +393,15 @@ struct mv_port_signal {
u32 pre;
};
-struct mv_host_priv;
+struct mv_host_priv {
+ u32 hp_flags;
+ struct mv_port_signal signal[8];
+ const struct mv_hw_ops *ops;
+ u32 irq_cause_ofs;
+ u32 irq_mask_ofs;
+ u32 unmask_all_irqs;
+};
+
struct mv_hw_ops {
void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
unsigned int port);
@@ -401,12 +414,6 @@ struct mv_hw_ops {
void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
};
-struct mv_host_priv {
- u32 hp_flags;
- struct mv_port_signal signal[8];
- const struct mv_hw_ops *ops;
-};
-
static void mv_irq_clear(struct ata_port *ap);
static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
@@ -631,11 +638,13 @@ static const struct pci_device_id mv_pci_tbl[] = {
/* Adaptec 1430SA */
{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
- { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
-
- /* add Marvell 7042 support */
+ /* Marvell 7042 support */
{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
+ /* Highpoint RocketRAID PCIe series */
+ { PCI_VDEVICE(TTI, 0x2300), chip_7042 },
+ { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
+
{ } /* terminate list */
};
@@ -1648,13 +1657,14 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
{
+ struct mv_host_priv *hpriv = host->private_data;
struct ata_port *ap;
struct ata_queued_cmd *qc;
struct ata_eh_info *ehi;
unsigned int i, err_mask, printed = 0;
u32 err_cause;
- err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS);
+ err_cause = readl(mmio + hpriv->irq_cause_ofs);
dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
err_cause);
@@ -1662,7 +1672,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
DPRINTK("All regs @ PCI error\n");
mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
- writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+ writelfl(0, mmio + hpriv->irq_cause_ofs);
for (i = 0; i < host->n_ports; i++) {
ap = host->ports[i];
@@ -1926,6 +1936,8 @@ static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
#define ZERO(reg) writel(0, mmio + (reg))
static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct mv_host_priv *hpriv = host->private_data;
u32 tmp;
tmp = readl(mmio + MV_PCI_MODE);
@@ -1937,8 +1949,8 @@ static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
ZERO(HC_MAIN_IRQ_MASK_OFS);
ZERO(MV_PCI_SERR_MASK);
- ZERO(PCI_IRQ_CAUSE_OFS);
- ZERO(PCI_IRQ_MASK_OFS);
+ ZERO(hpriv->irq_cause_ofs);
+ ZERO(hpriv->irq_mask_ofs);
ZERO(MV_PCI_ERR_LOW_ADDRESS);
ZERO(MV_PCI_ERR_HIGH_ADDRESS);
ZERO(MV_PCI_ERR_ATTRIBUTE);
@@ -2170,7 +2182,7 @@ static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
mv_scr_read(ap, SCR_ERROR, &serror);
mv_scr_read(ap, SCR_CONTROL, &scontrol);
DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
- "SCtrl 0x%08x\n", status, serror, scontrol);
+ "SCtrl 0x%08x\n", sstatus, serror, scontrol);
}
#endif
@@ -2490,6 +2502,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
break;
case chip_7042:
+ hp_flags |= MV_HP_PCIE;
case chip_6042:
hpriv->ops = &mv6xxx_ops;
hp_flags |= MV_HP_GEN_IIE;
@@ -2516,6 +2529,15 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
}
hpriv->hp_flags = hp_flags;
+ if (hp_flags & MV_HP_PCIE) {
+ hpriv->irq_cause_ofs = PCIE_IRQ_CAUSE_OFS;
+ hpriv->irq_mask_ofs = PCIE_IRQ_MASK_OFS;
+ hpriv->unmask_all_irqs = PCIE_UNMASK_ALL_IRQS;
+ } else {
+ hpriv->irq_cause_ofs = PCI_IRQ_CAUSE_OFS;
+ hpriv->irq_mask_ofs = PCI_IRQ_MASK_OFS;
+ hpriv->unmask_all_irqs = PCI_UNMASK_ALL_IRQS;
+ }
return 0;
}
@@ -2595,10 +2617,10 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
}
/* Clear any currently outstanding host interrupt conditions */
- writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+ writelfl(0, mmio + hpriv->irq_cause_ofs);
/* and unmask interrupt generation for host regs */
- writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+ writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
if (IS_GEN_I(hpriv))
writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
@@ -2609,8 +2631,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
"PCI int cause/mask=0x%08x/0x%08x\n",
readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
readl(mmio + HC_MAIN_IRQ_MASK_OFS),
- readl(mmio + PCI_IRQ_CAUSE_OFS),
- readl(mmio + PCI_IRQ_MASK_OFS));
+ readl(mmio + hpriv->irq_cause_ofs),
+ readl(mmio + hpriv->irq_mask_ofs));
done:
return rc;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 35b2df29752..44f9e5d9e36 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1629,7 +1629,7 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
/* SATA hardreset fails to retrieve proper device signature on
* some controllers. Don't classify on hardreset. For more
- * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
+ * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352
*/
return sata_std_hardreset(link, &dummy, deadline);
}
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 6d43ba79e15..2f1de6ec044 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -103,7 +103,7 @@ enum {
QS_DMA_BOUNDARY = ~0UL
};
-typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
+typedef enum { qs_state_mmio, qs_state_pkt } qs_state_t;
struct qs_port_priv {
u8 *pkt;
@@ -116,14 +116,15 @@ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int qs_port_start(struct ata_port *ap);
static void qs_host_stop(struct ata_host *host);
-static void qs_phy_reset(struct ata_port *ap);
static void qs_qc_prep(struct ata_queued_cmd *qc);
static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
static void qs_bmdma_stop(struct ata_queued_cmd *qc);
static u8 qs_bmdma_status(struct ata_port *ap);
static void qs_irq_clear(struct ata_port *ap);
-static void qs_eng_timeout(struct ata_port *ap);
+static void qs_freeze(struct ata_port *ap);
+static void qs_thaw(struct ata_port *ap);
+static void qs_error_handler(struct ata_port *ap);
static struct scsi_host_template qs_ata_sht = {
.module = THIS_MODULE,
@@ -150,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = {
.check_atapi_dma = qs_check_atapi_dma,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
- .phy_reset = qs_phy_reset,
.qc_prep = qs_qc_prep,
.qc_issue = qs_qc_issue,
.data_xfer = ata_data_xfer,
- .eng_timeout = qs_eng_timeout,
+ .freeze = qs_freeze,
+ .thaw = qs_thaw,
+ .error_handler = qs_error_handler,
.irq_clear = qs_irq_clear,
.irq_on = ata_irq_on,
.scr_read = qs_scr_read,
@@ -169,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = {
/* board_2068_idx */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET |
- //FIXME ATA_FLAG_SRST |
ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */
.udma_mask = ATA_UDMA6,
@@ -219,7 +219,9 @@ static void qs_irq_clear(struct ata_port *ap)
static inline void qs_enter_reg_mode(struct ata_port *ap)
{
u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
+ struct qs_port_priv *pp = ap->private_data;
+ pp->state = qs_state_mmio;
writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
readb(chan + QS_CCT_CTR0); /* flush */
}
@@ -233,23 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap)
qs_enter_reg_mode(ap);
}
-static void qs_phy_reset(struct ata_port *ap)
+static void qs_freeze(struct ata_port *ap)
{
- struct qs_port_priv *pp = ap->private_data;
+ u8 __iomem *mmio_base = qs_mmio_base(ap->host);
- pp->state = qs_state_idle;
- qs_reset_channel_logic(ap);
- sata_phy_reset(ap);
+ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
+ qs_enter_reg_mode(ap);
}
-static void qs_eng_timeout(struct ata_port *ap)
+static void qs_thaw(struct ata_port *ap)
{
- struct qs_port_priv *pp = ap->private_data;
+ u8 __iomem *mmio_base = qs_mmio_base(ap->host);
+
+ qs_enter_reg_mode(ap);
+ writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
+}
+
+static int qs_prereset(struct ata_link *link, unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
- if (pp->state != qs_state_idle) /* healthy paranoia */
- pp->state = qs_state_mmio;
qs_reset_channel_logic(ap);
- ata_eng_timeout(ap);
+ return ata_std_prereset(link, deadline);
}
static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
@@ -260,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return 0;
}
+static void qs_error_handler(struct ata_port *ap)
+{
+ qs_enter_reg_mode(ap);
+ ata_do_eh(ap, qs_prereset, ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
@@ -358,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
-
pp->state = qs_state_pkt;
qs_packet_start(qc);
return 0;
@@ -375,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
+static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status)
+{
+ qc->err_mask |= ac_err_mask(status);
+
+ if (!qc->err_mask) {
+ ata_qc_complete(qc);
+ } else {
+ struct ata_port *ap = qc->ap;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "status 0x%02X", status);
+
+ if (qc->err_mask == AC_ERR_DEV)
+ ata_port_abort(ap);
+ else
+ ata_port_freeze(ap);
+ }
+}
+
static inline unsigned int qs_intr_pkt(struct ata_host *host)
{
unsigned int handled = 0;
@@ -406,10 +439,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host)
switch (sHST) {
case 0: /* successful CPB */
case 3: /* device error */
- pp->state = qs_state_idle;
qs_enter_reg_mode(qc->ap);
- qc->err_mask |= ac_err_mask(sDST);
- ata_qc_complete(qc);
+ qs_do_or_die(qc, sDST);
break;
default:
break;
@@ -431,25 +462,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
- struct qs_port_priv *pp = ap->private_data;
- if (!pp || pp->state != qs_state_mmio)
- continue;
+ struct qs_port_priv *pp;
qc = ata_qc_from_tag(ap, ap->link.active_tag);
- if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-
- /* check main status, clearing INTRQ */
- u8 status = ata_check_status(ap);
- if ((status & ATA_BUSY))
- continue;
- DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
- ap->print_id, qc->tf.protocol, status);
-
- /* complete taskfile transaction */
- pp->state = qs_state_idle;
- qc->err_mask |= ac_err_mask(status);
- ata_qc_complete(qc);
+ if (!qc || !(qc->flags & ATA_QCFLAG_ACTIVE)) {
+ /*
+ * The qstor hardware generates spurious
+ * interrupts from time to time when switching
+ * in and out of packet mode.
+ * There's no obvious way to know if we're
+ * here now due to that, so just ack the irq
+ * and pretend we knew it was ours.. (ugh).
+ * This does not affect packet mode.
+ */
+ ata_check_status(ap);
handled = 1;
+ continue;
}
+ pp = ap->private_data;
+ if (!pp || pp->state != qs_state_mmio)
+ continue;
+ if (!(qc->tf.flags & ATA_TFLAG_POLLING))
+ handled |= ata_host_intr(ap, qc);
}
}
return handled;
@@ -459,12 +492,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int handled = 0;
+ unsigned long flags;
VPRINTK("ENTER\n");
- spin_lock(&host->lock);
+ spin_lock_irqsave(&host->lock, flags);
handled = qs_intr_pkt(host) | qs_intr_mmio(host);
- spin_unlock(&host->lock);
+ spin_unlock_irqrestore(&host->lock, flags);
VPRINTK("EXIT\n");
@@ -501,7 +535,6 @@ static int qs_port_start(struct ata_port *ap)
rc = ata_port_start(ap);
if (rc)
return rc;
- qs_enter_reg_mode(ap);
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
@@ -512,6 +545,7 @@ static int qs_port_start(struct ata_port *ap)
memset(pp->pkt, 0, QS_PKT_BYTES);
ap->private_data = pp;
+ qs_enter_reg_mode(ap);
addr = (u64)pp->pkt_dma;
writel((u32) addr, chan + QS_CCF_CPBA);
writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 187dcb02c68..96fd5260446 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -63,6 +63,21 @@ enum {
SIL24_HOST_BAR = 0,
SIL24_PORT_BAR = 2,
+ /* sil24 fetches in chunks of 64bytes. The first block
+ * contains the PRB and two SGEs. From the second block, it's
+ * consisted of four SGEs and called SGT. Calculate the
+ * number of SGTs that fit into one page.
+ */
+ SIL24_PRB_SZ = sizeof(struct sil24_prb)
+ + 2 * sizeof(struct sil24_sge),
+ SIL24_MAX_SGT = (PAGE_SIZE - SIL24_PRB_SZ)
+ / (4 * sizeof(struct sil24_sge)),
+
+ /* This will give us one unused SGEs for ATA. This extra SGE
+ * will be used to store CDB for ATAPI devices.
+ */
+ SIL24_MAX_SGE = 4 * SIL24_MAX_SGT + 1,
+
/*
* Global controller registers (128 bytes @ BAR0)
*/
@@ -247,13 +262,13 @@ enum {
struct sil24_ata_block {
struct sil24_prb prb;
- struct sil24_sge sge[LIBATA_MAX_PRD];
+ struct sil24_sge sge[SIL24_MAX_SGE];
};
struct sil24_atapi_block {
struct sil24_prb prb;
u8 cdb[16];
- struct sil24_sge sge[LIBATA_MAX_PRD - 1];
+ struct sil24_sge sge[SIL24_MAX_SGE];
};
union sil24_cmd_block {
@@ -378,7 +393,7 @@ static struct scsi_host_template sil24_sht = {
.change_queue_depth = ata_scsi_change_queue_depth,
.can_queue = SIL24_MAX_CMDS,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = SIL24_MAX_SGE,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -1284,6 +1299,7 @@ static void sil24_init_controller(struct ata_host *host)
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ extern int __MARKER__sil24_cmd_block_is_sized_wrongly;
static int printed_version;
struct ata_port_info pi = sil24_port_info[ent->driver_data];
const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -1292,6 +1308,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
int i, rc;
u32 tmp;
+ /* cause link error if sil24_cmd_block is sized wrongly */
+ if (sizeof(union sil24_cmd_block) != PAGE_SIZE)
+ __MARKER__sil24_cmd_block_is_sized_wrongly = 1;
+
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index d33aba6864c..3b64a99772e 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -394,6 +394,11 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
he_dev->atm_dev->dev_data = he_dev;
atm_dev->dev_data = he_dev;
he_dev->number = atm_dev->number;
+#ifdef USE_TASKLET
+ tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
+#endif
+ spin_lock_init(&he_dev->global_lock);
+
if (he_start(atm_dev)) {
he_stop(he_dev);
err = -ENODEV;
@@ -1173,11 +1178,6 @@ he_start(struct atm_dev *dev)
if ((err = he_init_irq(he_dev)) != 0)
return err;
-#ifdef USE_TASKLET
- tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
-#endif
- spin_lock_init(&he_dev->global_lock);
-
/* 4.11 enable pci bus controller state machines */
host_cntl |= (OUTFF_ENB | CMDFF_ENB |
QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 3f4d6aa1399..2683eac30c6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -770,9 +770,10 @@ int device_add(struct device *dev)
error = device_add_attrs(dev);
if (error)
goto AttrsError;
- error = device_pm_add(dev);
+ error = dpm_sysfs_add(dev);
if (error)
goto PMError;
+ device_pm_add(dev);
error = bus_add_device(dev);
if (error)
goto BusError;
@@ -797,6 +798,7 @@ int device_add(struct device *dev)
return error;
BusError:
device_pm_remove(dev);
+ dpm_sysfs_remove(dev);
PMError:
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index a803733c839..44504e6618f 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,5 +1,6 @@
obj-y := shutdown.o
-obj-$(CONFIG_PM_SLEEP) += main.o sysfs.o
+obj-$(CONFIG_PM) += sysfs.o
+obj-$(CONFIG_PM_SLEEP) += main.o
obj-$(CONFIG_PM_TRACE) += trace.o
ifeq ($(CONFIG_DEBUG_DRIVER),y)
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 0ab4ab21f56..691ffb64cc3 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -38,20 +38,14 @@ static DEFINE_MUTEX(dpm_list_mtx);
int (*platform_enable_wakeup)(struct device *dev, int is_on);
-int device_pm_add(struct device *dev)
+void device_pm_add(struct device *dev)
{
- int error;
-
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
mutex_lock(&dpm_list_mtx);
list_add_tail(&dev->power.entry, &dpm_active);
- error = dpm_sysfs_add(dev);
- if (error)
- list_del(&dev->power.entry);
mutex_unlock(&dpm_list_mtx);
- return error;
}
void device_pm_remove(struct device *dev)
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 5c4efd493fa..379da4e958e 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -13,14 +13,29 @@ extern void device_shutdown(void);
extern struct list_head dpm_active; /* The active device list */
-static inline struct device * to_device(struct list_head * entry)
+static inline struct device *to_device(struct list_head *entry)
{
return container_of(entry, struct device, power.entry);
}
-extern int device_pm_add(struct device *);
+extern void device_pm_add(struct device *);
extern void device_pm_remove(struct device *);
+#else /* CONFIG_PM_SLEEP */
+
+
+static inline void device_pm_add(struct device *dev)
+{
+}
+
+static inline void device_pm_remove(struct device *dev)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PM
+
/*
* sysfs.c
*/
@@ -28,16 +43,15 @@ extern void device_pm_remove(struct device *);
extern int dpm_sysfs_add(struct device *);
extern void dpm_sysfs_remove(struct device *);
-#else /* CONFIG_PM_SLEEP */
-
+#else /* CONFIG_PM */
-static inline int device_pm_add(struct device * dev)
+static inline int dpm_sysfs_add(struct device *dev)
{
return 0;
}
-static inline void device_pm_remove(struct device * dev)
-{
+static inline void dpm_sysfs_remove(struct device *dev)
+{
}
#endif
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 6332acad078..b4c0888aedc 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -28,6 +28,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <net/sock.h>
+#include <linux/net.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -126,7 +127,7 @@ static void sock_shutdown(struct nbd_device *lo, int lock)
if (lo->sock) {
printk(KERN_WARNING "%s: shutting down socket\n",
lo->disk->disk_name);
- lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
+ kernel_sock_shutdown(lo->sock, SHUT_RDWR);
lo->sock = NULL;
}
if (lock)
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index ceffa6034e2..e7fe6ca97dd 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -488,13 +488,11 @@ static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fu
return r;
}
-#define DBMSG(msg) ((verbose>1)?(msg):NULL)
-
static void pf_lock(struct pf_unit *pf, int func)
{
char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
- pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock");
+ pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock");
}
static void pf_eject(struct pf_unit *pf)
@@ -555,7 +553,7 @@ static void pf_mode_sense(struct pf_unit *pf)
{ ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
char buf[8];
- pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense"));
+ pf_atapi(pf, ms_cmd, 8, buf, "mode sense");
pf->media_status = PF_RW;
if (buf[3] & 0x80)
pf->media_status = PF_RO;
@@ -591,7 +589,7 @@ static void pf_get_capacity(struct pf_unit *pf)
char buf[8];
int bs;
- if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) {
+ if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) {
pf->media_status = PF_NM;
return;
}
@@ -804,13 +802,18 @@ static int pf_next_buf(void)
pf_buf += 512;
pf_block++;
if (!pf_run)
- return 0;
- if (!pf_count)
return 1;
- spin_lock_irqsave(&pf_spin_lock, saved_flags);
- pf_end_request(1);
- spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
- return 1;
+ if (!pf_count) {
+ spin_lock_irqsave(&pf_spin_lock, saved_flags);
+ pf_end_request(1);
+ pf_req = elv_next_request(pf_queue);
+ spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
+ if (!pf_req)
+ return 1;
+ pf_count = pf_req->current_nr_sectors;
+ pf_buf = pf_req->buffer;
+ }
+ return 0;
}
static inline void next_request(int success)
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index a8130a4ad6d..a5ee21319d3 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -358,10 +358,19 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
size_t count)
{
unsigned int major, minor;
+
if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
+ /* pkt_setup_dev() expects caller to hold reference to self */
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
pkt_setup_dev(MKDEV(major, minor), NULL);
+
+ module_put(THIS_MODULE);
+
return count;
}
+
return -EINVAL;
}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 47f8ac6cce5..82f4eecc869 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -189,6 +189,18 @@ static int ramdisk_set_page_dirty(struct page *page)
return 0;
}
+/*
+ * releasepage is called by pagevec_strip/try_to_release_page if
+ * buffers_heads_over_limit is true. Without a releasepage function
+ * try_to_free_buffers is called instead. That can unset the dirty
+ * bit of our ram disk pages, which will be eventually freed, even
+ * if the page is still in use.
+ */
+static int ramdisk_releasepage(struct page *page, gfp_t dummy)
+{
+ return 0;
+}
+
static const struct address_space_operations ramdisk_aops = {
.readpage = ramdisk_readpage,
.prepare_write = ramdisk_prepare_write,
@@ -196,6 +208,7 @@ static const struct address_space_operations ramdisk_aops = {
.writepage = ramdisk_writepage,
.set_page_dirty = ramdisk_set_page_dirty,
.writepages = ramdisk_writepages,
+ .releasepage = ramdisk_releasepage,
};
static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector,
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 3cf7129d83e..924ddd8bccd 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -223,7 +223,7 @@ static int virtblk_probe(struct virtio_device *vdev)
err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap);
if (err) {
dev_err(&vdev->dev, "Bad/missing capacity in config\n");
- goto out_put_disk;
+ goto out_cleanup_queue;
}
/* If capacity is too big, truncate with warning. */
@@ -239,7 +239,7 @@ static int virtblk_probe(struct virtio_device *vdev)
blk_queue_max_segment_size(vblk->disk->queue, v);
else if (err != -ENOENT) {
dev_err(&vdev->dev, "Bad SIZE_MAX in config\n");
- goto out_put_disk;
+ goto out_cleanup_queue;
}
err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v);
@@ -247,12 +247,14 @@ static int virtblk_probe(struct virtio_device *vdev)
blk_queue_max_hw_segments(vblk->disk->queue, v);
else if (err != -ENOENT) {
dev_err(&vdev->dev, "Bad SEG_MAX in config\n");
- goto out_put_disk;
+ goto out_cleanup_queue;
}
add_disk(vblk->disk);
return 0;
+out_cleanup_queue:
+ blk_cleanup_queue(vblk->disk->queue);
out_put_disk:
put_disk(vblk->disk);
out_unregister_blkdev:
@@ -277,6 +279,8 @@ static void virtblk_remove(struct virtio_device *vdev)
put_disk(vblk->disk);
unregister_blkdev(major, "virtblk");
mempool_destroy(vblk->pool);
+ /* There should be nothing in the queue now, so no need to shutdown */
+ vdev->config->del_vq(vblk->vq);
kfree(vblk);
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index bf18d757b87..a509b8d7978 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -457,7 +457,7 @@ config LEGACY_PTYS
config LEGACY_PTY_COUNT
int "Maximum number of legacy PTY in use"
depends on LEGACY_PTYS
- range 1 256
+ range 0 256
default "256"
---help---
The maximum number of legacy PTYs that can be used at any one time.
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index cc5d77797de..02518da6a38 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -47,7 +47,7 @@
/* #define ATR_CSUM */
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index a0b9c8728d5..5f291bf739a 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -41,7 +41,7 @@
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1756b1f7cb7..5fee0566182 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1494,7 +1494,7 @@ __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
seq += keyptr->count;
- seq += ktime_get_real().tv64;
+ seq += ktime_to_ns(ktime_get_real());
return seq;
}
@@ -1556,7 +1556,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
* overlaps less than one time per MSL (2 minutes).
* Choosing a clock of 64 ns period is OK. (period of 274 s)
*/
- seq += ktime_get_real().tv64 >> 6;
+ seq += ktime_to_ns(ktime_get_real()) >> 6;
#if 0
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
saddr, daddr, sport, dport, seq);
@@ -1616,7 +1616,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
seq = half_md4_transform(hash, keyptr->secret);
seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
- seq += ktime_get_real().tv64;
+ seq += ktime_to_ns(ktime_get_real());
seq &= (1ull << 48) - 1;
#if 0
printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index ec6b65ec69e..0c66b802736 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -918,6 +918,31 @@ static const struct file_operations rtc_proc_fops = {
};
#endif
+static resource_size_t rtc_size;
+
+static struct resource * __init rtc_request_region(resource_size_t size)
+{
+ struct resource *r;
+
+ if (RTC_IOMAPPED)
+ r = request_region(RTC_PORT(0), size, "rtc");
+ else
+ r = request_mem_region(RTC_PORT(0), size, "rtc");
+
+ if (r)
+ rtc_size = size;
+
+ return r;
+}
+
+static void rtc_release_region(void)
+{
+ if (RTC_IOMAPPED)
+ release_region(RTC_PORT(0), rtc_size);
+ else
+ release_mem_region(RTC_PORT(0), rtc_size);
+}
+
static int __init rtc_init(void)
{
#ifdef CONFIG_PROC_FS
@@ -968,10 +993,17 @@ found:
}
no_irq:
#else
- if (RTC_IOMAPPED)
- r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
- else
- r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
+ r = rtc_request_region(RTC_IO_EXTENT);
+
+ /*
+ * If we've already requested a smaller range (for example, because
+ * PNPBIOS or ACPI told us how the device is configured), the request
+ * above might fail because it's too big.
+ *
+ * If so, request just the range we actually use.
+ */
+ if (!r)
+ r = rtc_request_region(RTC_IO_EXTENT_USED);
if (!r) {
#ifdef RTC_IRQ
rtc_has_irq = 0;
@@ -992,10 +1024,7 @@ no_irq:
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
- if (RTC_IOMAPPED)
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- else
- release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
return -EIO;
}
hpet_rtc_timer_init();
@@ -1009,7 +1038,7 @@ no_irq:
free_irq(RTC_IRQ, NULL);
rtc_has_irq = 0;
#endif
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
return -ENODEV;
}
@@ -1091,10 +1120,7 @@ static void __exit rtc_exit (void)
if (rtc_has_irq)
free_irq (rtc_irq, &rtc_port);
#else
- if (RTC_IOMAPPED)
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- else
- release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
#ifdef RTC_IRQ
if (rtc_has_irq)
free_irq (RTC_IRQ, NULL);
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 877e53dcb99..921c6d2bc8f 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1163,7 +1163,7 @@ static struct acpi_driver sonypi_acpi_driver = {
};
#endif
-static int __devinit sonypi_create_input_devices(void)
+static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
@@ -1177,6 +1177,7 @@ static int __devinit sonypi_create_input_devices(void)
jog_dev->name = "Sony Vaio Jogdial";
jog_dev->id.bustype = BUS_ISA;
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
+ jog_dev->dev.parent = &pdev->dev;
jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
@@ -1191,6 +1192,7 @@ static int __devinit sonypi_create_input_devices(void)
key_dev->name = "Sony Vaio Keys";
key_dev->id.bustype = BUS_ISA;
key_dev->id.vendor = PCI_VENDOR_ID_SONY;
+ key_dev->dev.parent = &pdev->dev;
/* Initialize the Input Drivers: special keys */
key_dev->evbit[0] = BIT_MASK(EV_KEY);
@@ -1385,7 +1387,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
if (useinput) {
- error = sonypi_create_input_devices();
+ error = sonypi_create_input_devices(dev);
if (error) {
printk(KERN_ERR
"sonypi: failed to create input devices\n");
@@ -1432,7 +1434,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
{
sonypi_disable();
- synchronize_sched(); /* Allow sonypi interrupt to complete. */
+ synchronize_irq(sonypi_device.irq);
flush_scheduled_work();
if (useinput) {
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index fd771a4d6d1..81503d94fec 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -450,6 +450,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
goto out_err;
}
+ if (request_locality(chip, 0) != 0) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
/* Default timeouts */
@@ -487,11 +492,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
dev_dbg(dev, "\tData Avail Int Support\n");
- if (request_locality(chip, 0) != 0) {
- rc = -ENODEV;
- goto out_err;
- }
-
/* INTERRUPT Setup */
init_waitqueue_head(&chip->vendor.read_queue);
init_waitqueue_head(&chip->vendor.int_queue);
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 7a003504c26..1bdd2bf4f37 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -730,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch)
return 0;
}
-int n_tty_ioctl(struct tty_struct * tty, struct file * file,
- unsigned int cmd, unsigned long arg)
+/**
+ * tty_mode_ioctl - mode related ioctls
+ * @tty: tty for the ioctl
+ * @file: file pointer for the tty
+ * @cmd: command
+ * @arg: ioctl argument
+ *
+ * Perform non line discipline specific mode control ioctls. This
+ * is designed to be called by line disciplines to ensure they provide
+ * consistent mode setting.
+ */
+
+int tty_mode_ioctl(struct tty_struct * tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct tty_struct * real_tty;
void __user *p = (void __user *)arg;
- int retval;
- struct tty_ldisc *ld;
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
@@ -799,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
case TCSETA:
return set_termios(real_tty, p, TERMIOS_TERMIO);
+#ifndef TCGETS2
+ case TIOCGLCKTRMIOS:
+ if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
+ return -EFAULT;
+ return 0;
+
+ case TIOCSLCKTRMIOS:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
+ return -EFAULT;
+ return 0;
+#else
+ case TIOCGLCKTRMIOS:
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
+ return -EFAULT;
+ return 0;
+
+ case TIOCSLCKTRMIOS:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
+ return -EFAULT;
+ return 0;
+#endif
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
+ case TIOCSSOFTCAR:
+ if (get_user(arg, (unsigned int __user *) arg))
+ return -EFAULT;
+ mutex_lock(&tty->termios_mutex);
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ mutex_unlock(&tty->termios_mutex);
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+EXPORT_SYMBOL_GPL(tty_mode_ioctl);
+
+int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+{
+ struct tty_ldisc *ld;
+ int retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+
+ ld = tty_ldisc_ref(tty);
+ switch (arg) {
+ case TCIFLUSH:
+ if (ld && ld->flush_buffer)
+ ld->flush_buffer(tty);
+ break;
+ case TCIOFLUSH:
+ if (ld && ld->flush_buffer)
+ ld->flush_buffer(tty);
+ /* fall through */
+ case TCOFLUSH:
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ break;
+ default:
+ tty_ldisc_deref(ld);
+ return -EINVAL;
+ }
+ tty_ldisc_deref(ld);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tty_perform_flush);
+
+int n_tty_ioctl(struct tty_struct * tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct tty_struct * real_tty;
+ int retval;
+
+ if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+ tty->driver->subtype == PTY_TYPE_MASTER)
+ real_tty = tty->link;
+ else
+ real_tty = tty;
+
+ switch (cmd) {
case TCXONC:
retval = tty_check_change(tty);
if (retval)
@@ -829,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
}
return 0;
case TCFLSH:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
-
- ld = tty_ldisc_ref(tty);
- switch (arg) {
- case TCIFLUSH:
- if (ld && ld->flush_buffer)
- ld->flush_buffer(tty);
- break;
- case TCIOFLUSH:
- if (ld && ld->flush_buffer)
- ld->flush_buffer(tty);
- /* fall through */
- case TCOFLUSH:
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
- break;
- default:
- tty_ldisc_deref(ld);
- return -EINVAL;
- }
- tty_ldisc_deref(ld);
- return 0;
+ return tty_perform_flush(tty, arg);
case TIOCOUTQ:
return put_user(tty->driver->chars_in_buffer ?
tty->driver->chars_in_buffer(tty) : 0,
@@ -862,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (L_ICANON(tty))
retval = inq_canon(tty);
return put_user(retval, (unsigned int __user *) arg);
-#ifndef TCGETS2
- case TIOCGLCKTRMIOS:
- if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
- return -EFAULT;
- return 0;
-
- case TIOCSLCKTRMIOS:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
- return -EFAULT;
- return 0;
-#else
- case TIOCGLCKTRMIOS:
- if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
- return -EFAULT;
- return 0;
-
- case TIOCSLCKTRMIOS:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
- return -EFAULT;
- return 0;
-#endif
-
case TIOCPKT:
{
int pktmode;
@@ -906,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
tty->packet = 0;
return 0;
}
- case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
- case TIOCSSOFTCAR:
- if (get_user(arg, (unsigned int __user *) arg))
- return -EFAULT;
- mutex_lock(&tty->termios_mutex);
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- mutex_unlock(&tty->termios_mutex);
- return 0;
default:
- return -ENOIOCTLCMD;
+ /* Try the mode commands */
+ return tty_mode_ioctl(tty, file, cmd, arg);
}
}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 4bd33ce8a6f..1bba99747f5 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -37,17 +37,17 @@
#define DEF_FREQUENCY_UP_THRESHOLD (80)
#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
-/*
- * The polling frequency of this governor depends on the capability of
+/*
+ * The polling frequency of this governor depends on the capability of
* the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
+ * latency of the processor. The governor will work on any processor with
+ * transition latency <= 10mS, using appropriate sampling
* rate.
* For CPUs with transition latency > 10mS (mostly drivers
* with CPUFREQ_ETERNAL), this governor will not work.
* All times here are in uS.
*/
-static unsigned int def_sampling_rate;
+static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE_RATIO (2)
/* for correct statistics, we need at least 10 ticks between each measure */
#define MIN_STAT_SAMPLING_RATE \
@@ -63,12 +63,12 @@ static unsigned int def_sampling_rate;
static void do_dbs_timer(struct work_struct *work);
struct cpu_dbs_info_s {
- struct cpufreq_policy *cur_policy;
- unsigned int prev_cpu_idle_up;
- unsigned int prev_cpu_idle_down;
- unsigned int enable;
- unsigned int down_skip;
- unsigned int requested_freq;
+ struct cpufreq_policy *cur_policy;
+ unsigned int prev_cpu_idle_up;
+ unsigned int prev_cpu_idle_down;
+ unsigned int enable;
+ unsigned int down_skip;
+ unsigned int requested_freq;
};
static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
@@ -82,24 +82,24 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */
* cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
* is recursive for the same process. -Venki
*/
-static DEFINE_MUTEX (dbs_mutex);
+static DEFINE_MUTEX (dbs_mutex);
static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer);
struct dbs_tuners {
- unsigned int sampling_rate;
- unsigned int sampling_down_factor;
- unsigned int up_threshold;
- unsigned int down_threshold;
- unsigned int ignore_nice;
- unsigned int freq_step;
+ unsigned int sampling_rate;
+ unsigned int sampling_down_factor;
+ unsigned int up_threshold;
+ unsigned int down_threshold;
+ unsigned int ignore_nice;
+ unsigned int freq_step;
};
static struct dbs_tuners dbs_tuners_ins = {
- .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
- .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
- .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
- .ignore_nice = 0,
- .freq_step = 5,
+ .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+ .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
+ .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+ .ignore_nice = 0,
+ .freq_step = 5,
};
static inline unsigned int get_cpu_idle_time(unsigned int cpu)
@@ -109,13 +109,34 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu)
if (dbs_tuners_ins.ignore_nice)
add_nice = kstat_cpu(cpu).cpustat.nice;
- ret = kstat_cpu(cpu).cpustat.idle +
+ ret = kstat_cpu(cpu).cpustat.idle +
kstat_cpu(cpu).cpustat.iowait +
add_nice;
return ret;
}
+/* keep track of frequency transitions */
+static int
+dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct cpufreq_freqs *freq = data;
+ struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info,
+ freq->cpu);
+
+ if (!this_dbs_info->enable)
+ return 0;
+
+ this_dbs_info->requested_freq = freq->new;
+
+ return 0;
+}
+
+static struct notifier_block dbs_cpufreq_notifier_block = {
+ .notifier_call = dbs_cpufreq_notifier
+};
+
/************************** sysfs interface ************************/
static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
{
@@ -127,8 +148,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
}
-#define define_one_ro(_name) \
-static struct freq_attr _name = \
+#define define_one_ro(_name) \
+static struct freq_attr _name = \
__ATTR(_name, 0444, show_##_name, NULL)
define_one_ro(sampling_rate_max);
@@ -148,7 +169,7 @@ show_one(down_threshold, down_threshold);
show_one(ignore_nice_load, ignore_nice);
show_one(freq_step, freq_step);
-static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
+static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -164,7 +185,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
+static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -183,7 +204,7 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_up_threshold(struct cpufreq_policy *unused,
+static ssize_t store_up_threshold(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -202,7 +223,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_down_threshold(struct cpufreq_policy *unused,
+static ssize_t store_down_threshold(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -228,16 +249,16 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
int ret;
unsigned int j;
-
- ret = sscanf (buf, "%u", &input);
- if ( ret != 1 )
+
+ ret = sscanf(buf, "%u", &input);
+ if (ret != 1)
return -EINVAL;
- if ( input > 1 )
+ if (input > 1)
input = 1;
-
+
mutex_lock(&dbs_mutex);
- if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
+ if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
mutex_unlock(&dbs_mutex);
return count;
}
@@ -261,14 +282,14 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy,
unsigned int input;
int ret;
- ret = sscanf (buf, "%u", &input);
+ ret = sscanf(buf, "%u", &input);
- if ( ret != 1 )
+ if (ret != 1)
return -EINVAL;
- if ( input > 100 )
+ if (input > 100)
input = 100;
-
+
/* no need to test here if freq_step is zero as the user might actually
* want this, they would be crazy though :) */
mutex_lock(&dbs_mutex);
@@ -322,18 +343,18 @@ static void dbs_check_cpu(int cpu)
policy = this_dbs_info->cur_policy;
- /*
- * The default safe range is 20% to 80%
+ /*
+ * The default safe range is 20% to 80%
* Every sampling_rate, we check
- * - If current idle time is less than 20%, then we try to
- * increase frequency
+ * - If current idle time is less than 20%, then we try to
+ * increase frequency
* Every sampling_rate*sampling_down_factor, we check
- * - If current idle time is more than 80%, then we try to
- * decrease frequency
+ * - If current idle time is more than 80%, then we try to
+ * decrease frequency
*
- * Any frequency increase takes it to the maximum frequency.
- * Frequency reduction happens at minimum steps of
- * 5% (default) of max_frequency
+ * Any frequency increase takes it to the maximum frequency.
+ * Frequency reduction happens at minimum steps of
+ * 5% (default) of max_frequency
*/
/* Check for frequency increase */
@@ -361,13 +382,13 @@ static void dbs_check_cpu(int cpu)
/* if we are already at full speed then break out early */
if (this_dbs_info->requested_freq == policy->max)
return;
-
+
freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
/* max freq cannot be less than 100. But who knows.... */
if (unlikely(freq_step == 0))
freq_step = 5;
-
+
this_dbs_info->requested_freq += freq_step;
if (this_dbs_info->requested_freq > policy->max)
this_dbs_info->requested_freq = policy->max;
@@ -427,15 +448,15 @@ static void dbs_check_cpu(int cpu)
}
static void do_dbs_timer(struct work_struct *work)
-{
+{
int i;
mutex_lock(&dbs_mutex);
for_each_online_cpu(i)
dbs_check_cpu(i);
- schedule_delayed_work(&dbs_work,
+ schedule_delayed_work(&dbs_work,
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
mutex_unlock(&dbs_mutex);
-}
+}
static inline void dbs_timer_init(void)
{
@@ -462,13 +483,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
switch (event) {
case CPUFREQ_GOV_START:
- if ((!cpu_online(cpu)) ||
- (!policy->cur))
+ if ((!cpu_online(cpu)) || (!policy->cur))
return -EINVAL;
if (this_dbs_info->enable) /* Already enabled */
break;
-
+
mutex_lock(&dbs_mutex);
rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
@@ -481,7 +501,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
-
+
j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu);
j_dbs_info->prev_cpu_idle_down
= j_dbs_info->prev_cpu_idle_up;
@@ -511,8 +531,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
dbs_tuners_ins.sampling_rate = def_sampling_rate;
dbs_timer_init();
+ cpufreq_register_notifier(
+ &dbs_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
}
-
+
mutex_unlock(&dbs_mutex);
break;
@@ -525,9 +548,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
* Stop the timerschedule work, when this governor
* is used for first time
*/
- if (dbs_enable == 0)
+ if (dbs_enable == 0) {
dbs_timer_exit();
-
+ cpufreq_unregister_notifier(
+ &dbs_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ }
+
mutex_unlock(&dbs_mutex);
break;
@@ -537,11 +564,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (policy->max < this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
this_dbs_info->cur_policy,
- policy->max, CPUFREQ_RELATION_H);
+ policy->max, CPUFREQ_RELATION_H);
else if (policy->min > this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
this_dbs_info->cur_policy,
- policy->min, CPUFREQ_RELATION_L);
+ policy->min, CPUFREQ_RELATION_L);
mutex_unlock(&dbs_mutex);
break;
}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 5fd6688a444..ddd3a259cea 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -12,7 +12,7 @@ if CRYPTO_HW
config CRYPTO_DEV_PADLOCK
tristate "Support for VIA PadLock ACE"
- depends on X86_32
+ depends on X86_32 && !UML
select CRYPTO_ALGAPI
help
Some VIA processors come with an integrated crypto engine
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index f9a34abbf4f..711e246e1ef 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -110,8 +110,7 @@ geode_aes_crypt(struct geode_aes_op *op)
* we don't need to worry
*/
- if (op->src == op->dst)
- flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
+ flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
if (op->dir == AES_DIR_ENCRYPT)
flags |= AES_CTRL_ENCRYPT;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 6a7d25fc247..c46b7c219ee 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -3,11 +3,13 @@
#
menuconfig DMADEVICES
- bool "DMA Offload Engine support"
+ bool "DMA Engine support"
depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
help
- Intel(R) offload engines enable offloading memory copies in the
- network stack and RAID operations in the MD driver.
+ DMA engines can do asynchronous data transfers without
+ involving the host CPU. Currently, this framework can be
+ used to offload memory copies in the network stack and
+ RAID operations in the MD driver.
if DMADEVICES
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 82489923af0..d59b2f41730 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -182,10 +182,9 @@ static void dma_client_chan_alloc(struct dma_client *client)
/* we are done once this client rejects
* an available resource
*/
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_get(chan);
- kref_get(&device->refcount);
- } else if (ack == DMA_NAK)
+ else if (ack == DMA_NAK)
return;
}
}
@@ -272,11 +271,8 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
/* client was holding resources for this channel so
* free it
*/
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_put(chan);
- kref_put(&chan->device->refcount,
- dma_async_device_cleanup);
- }
}
mutex_unlock(&dma_list_mutex);
@@ -316,11 +312,8 @@ void dma_async_client_unregister(struct dma_client *client)
ack = client->event_callback(client, chan,
DMA_RESOURCE_REMOVED);
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_put(chan);
- kref_put(&chan->device->refcount,
- dma_async_device_cleanup);
- }
}
list_del(&client->global_node);
@@ -397,6 +390,8 @@ int dma_async_device_register(struct dma_device *device)
goto err_out;
}
+ /* One for the channel, one of the class device */
+ kref_get(&device->refcount);
kref_get(&device->refcount);
kref_init(&chan->refcount);
chan->slow_ref = 0;
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index f204c39fb41..16e0fd8facf 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -39,10 +39,14 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");
static struct pci_device_id ioat_pci_tbl[] = {
+ /* I/OAT v1 platforms */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },
{ PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
+
+ /* I/OAT v2 platforms */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
{ 0, }
};
@@ -74,10 +78,17 @@ static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase)
if (device->dma && ioat_dca_enabled)
device->dca = ioat_dca_init(pdev, iobase);
break;
+ case IOAT_VER_2_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat2_dca_init(pdev, iobase);
+ break;
default:
err = -ENODEV;
break;
}
+ if (!device->dma)
+ err = -ENODEV;
return err;
}
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index ba985715b80..0fa8a98051a 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -261,3 +261,167 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
return dca;
}
+
+static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 id;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+ id = dcaid_from_pcidev(pdev);
+
+ if (ioatdca->requester_count == ioatdca->max_requesters)
+ return -ENODEV;
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == NULL) {
+ /* found an empty slot */
+ ioatdca->requester_count++;
+ ioatdca->req_slots[i].pdev = pdev;
+ ioatdca->req_slots[i].rid = id;
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET);
+ writel(id | IOAT_DCA_GREQID_VALID,
+ ioatdca->iobase + global_req_table + (i * 4));
+ return i;
+ }
+ }
+ /* Error, ioatdma->requester_count is out of whack */
+ return -EFAULT;
+}
+
+static int ioat2_dca_remove_requester(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev) {
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET);
+ writel(0, ioatdca->iobase + global_req_table + (i * 4));
+ ioatdca->req_slots[i].pdev = NULL;
+ ioatdca->req_slots[i].rid = 0;
+ ioatdca->requester_count--;
+ return i;
+ }
+ }
+ return -ENODEV;
+}
+
+static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu)
+{
+ u8 tag;
+
+ tag = ioat_dca_get_tag(dca, cpu);
+ tag = (~tag) & 0x1F;
+ return tag;
+}
+
+static struct dca_ops ioat2_dca_ops = {
+ .add_requester = ioat2_dca_add_requester,
+ .remove_requester = ioat2_dca_remove_requester,
+ .get_tag = ioat2_dca_get_tag,
+};
+
+static int ioat2_dca_count_dca_slots(void *iobase, u16 dca_offset)
+{
+ int slots = 0;
+ u32 req;
+ u16 global_req_table;
+
+ global_req_table = readw(iobase + dca_offset + IOAT_DCA_GREQID_OFFSET);
+ if (global_req_table == 0)
+ return 0;
+ do {
+ req = readl(iobase + global_req_table + (slots * sizeof(u32)));
+ slots++;
+ } while ((req & IOAT_DCA_GREQID_LASTID) == 0);
+
+ return slots;
+}
+
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct dca_provider *dca;
+ struct ioat_dca_priv *ioatdca;
+ int slots;
+ int i;
+ int err;
+ u32 tag_map;
+ u16 dca_offset;
+ u16 csi_fsb_control;
+ u16 pcie_control;
+ u8 bit;
+
+ if (!system_has_dca_enabled(pdev))
+ return NULL;
+
+ dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
+ if (dca_offset == 0)
+ return NULL;
+
+ slots = ioat2_dca_count_dca_slots(iobase, dca_offset);
+ if (slots == 0)
+ return NULL;
+
+ dca = alloc_dca_provider(&ioat2_dca_ops,
+ sizeof(*ioatdca)
+ + (sizeof(struct ioat_dca_slot) * slots));
+ if (!dca)
+ return NULL;
+
+ ioatdca = dca_priv(dca);
+ ioatdca->iobase = iobase;
+ ioatdca->dca_base = iobase + dca_offset;
+ ioatdca->max_requesters = slots;
+
+ /* some bios might not know to turn these on */
+ csi_fsb_control = readw(ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET);
+ if ((csi_fsb_control & IOAT_FSB_CAP_ENABLE_PREFETCH) == 0) {
+ csi_fsb_control |= IOAT_FSB_CAP_ENABLE_PREFETCH;
+ writew(csi_fsb_control,
+ ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET);
+ }
+ pcie_control = readw(ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET);
+ if ((pcie_control & IOAT_PCI_CAP_ENABLE_MEMWR) == 0) {
+ pcie_control |= IOAT_PCI_CAP_ENABLE_MEMWR;
+ writew(pcie_control,
+ ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET);
+ }
+
+
+ /* TODO version, compatibility and configuration checks */
+
+ /* copy out the APIC to DCA tag map */
+ tag_map = readl(ioatdca->dca_base + IOAT_APICID_TAG_MAP_OFFSET);
+ for (i = 0; i < 5; i++) {
+ bit = (tag_map >> (4 * i)) & 0x0f;
+ if (bit < 8)
+ ioatdca->tag_map[i] = bit | DCA_TAG_MAP_VALID;
+ else
+ ioatdca->tag_map[i] = 0;
+ }
+
+ err = register_dca_provider(dca, &pdev->dev);
+ if (err) {
+ free_dca_provider(dca);
+ return NULL;
+ }
+
+ return dca;
+}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 7e4a785c2df..c1c2dcc6fc2 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -36,18 +36,24 @@
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
-#define INITIAL_IOAT_DESC_COUNT 128
-
#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
#define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common)
#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
+static int ioat_pending_level = 4;
+module_param(ioat_pending_level, int, 0644);
+MODULE_PARM_DESC(ioat_pending_level,
+ "high-water mark for pushing ioat descriptors (default: 4)");
+
/* internal functions */
static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);
static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
+
+static struct ioat_desc_sw *
+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
static struct ioat_desc_sw *
-ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
+ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
static inline struct ioat_dma_chan *ioat_lookup_chan_by_index(
struct ioatdma_device *device,
@@ -130,6 +136,12 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
ioat_chan->device = device;
ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
ioat_chan->xfercap = xfercap;
+ ioat_chan->desccount = 0;
+ if (ioat_chan->device->version != IOAT_VER_1_2) {
+ writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
+ | IOAT_DMA_DCA_ANY_CPU,
+ ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
+ }
spin_lock_init(&ioat_chan->cleanup_lock);
spin_lock_init(&ioat_chan->desc_lock);
INIT_LIST_HEAD(&ioat_chan->free_desc);
@@ -161,13 +173,17 @@ static void ioat_set_dest(dma_addr_t addr,
tx_to_ioat_desc(tx)->dst = addr;
}
-static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx)
+static inline void __ioat1_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan);
+static inline void __ioat2_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan);
+
+static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
struct ioat_desc_sw *first = tx_to_ioat_desc(tx);
struct ioat_desc_sw *prev, *new;
struct ioat_dma_descriptor *hw;
- int append = 0;
dma_cookie_t cookie;
LIST_HEAD(new_chain);
u32 copy;
@@ -209,7 +225,7 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx)
list_add_tail(&new->node, &new_chain);
desc_count++;
prev = new;
- } while (len && (new = ioat_dma_get_next_descriptor(ioat_chan)));
+ } while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));
hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
if (new->async_tx.callback) {
@@ -246,20 +262,98 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx)
first->async_tx.phys;
__list_splice(&new_chain, ioat_chan->used_desc.prev);
+ ioat_chan->dmacount += desc_count;
ioat_chan->pending += desc_count;
- if (ioat_chan->pending >= 4) {
- append = 1;
- ioat_chan->pending = 0;
- }
+ if (ioat_chan->pending >= ioat_pending_level)
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
- if (append)
- writeb(IOAT_CHANCMD_APPEND,
- ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+ return cookie;
+}
+
+static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+ struct ioat_desc_sw *first = tx_to_ioat_desc(tx);
+ struct ioat_desc_sw *new;
+ struct ioat_dma_descriptor *hw;
+ dma_cookie_t cookie;
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+ int orig_ack;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+ orig_ack = first->async_tx.ack;
+ new = first;
+
+ /* ioat_chan->desc_lock is still in force in version 2 path */
+
+ do {
+ copy = min((u32) len, ioat_chan->xfercap);
+
+ new->async_tx.ack = 1;
+
+ hw = new->hw;
+ hw->size = copy;
+ hw->ctl = 0;
+ hw->src_addr = src;
+ hw->dst_addr = dst;
+
+ len -= copy;
+ dst += copy;
+ src += copy;
+ desc_count++;
+ } while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));
+
+ hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ if (new->async_tx.callback) {
+ hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
+ if (first != new) {
+ /* move callback into to last desc */
+ new->async_tx.callback = first->async_tx.callback;
+ new->async_tx.callback_param
+ = first->async_tx.callback_param;
+ first->async_tx.callback = NULL;
+ first->async_tx.callback_param = NULL;
+ }
+ }
+
+ new->tx_cnt = desc_count;
+ new->async_tx.ack = orig_ack; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+ new->src = first->src;
+ new->dst = first->dst;
+ new->len = first->len;
+ }
+
+ /* cookie incr and addition to used_list must be atomic */
+ cookie = ioat_chan->common.cookie;
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
+ ioat_chan->common.cookie = new->async_tx.cookie = cookie;
+
+ ioat_chan->dmacount += desc_count;
+ ioat_chan->pending += desc_count;
+ if (ioat_chan->pending >= ioat_pending_level)
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
return cookie;
}
+/**
+ * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair
+ * @ioat_chan: the channel supplying the memory pool for the descriptors
+ * @flags: allocation flags
+ */
static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
struct ioat_dma_chan *ioat_chan,
gfp_t flags)
@@ -284,15 +378,57 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
desc_sw->async_tx.tx_set_src = ioat_set_src;
desc_sw->async_tx.tx_set_dest = ioat_set_dest;
- desc_sw->async_tx.tx_submit = ioat_tx_submit;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc_sw->async_tx.tx_submit = ioat1_tx_submit;
+ break;
+ case IOAT_VER_2_0:
+ desc_sw->async_tx.tx_submit = ioat2_tx_submit;
+ break;
+ }
INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
+
desc_sw->hw = desc;
desc_sw->async_tx.phys = phys;
return desc_sw;
}
-/* returns the actual number of allocated descriptors */
+static int ioat_initial_desc_count = 256;
+module_param(ioat_initial_desc_count, int, 0644);
+MODULE_PARM_DESC(ioat_initial_desc_count,
+ "initial descriptors per channel (default: 256)");
+
+/**
+ * ioat2_dma_massage_chan_desc - link the descriptors into a circle
+ * @ioat_chan: the channel to be massaged
+ */
+static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *desc, *_desc;
+
+ /* setup used_desc */
+ ioat_chan->used_desc.next = ioat_chan->free_desc.next;
+ ioat_chan->used_desc.prev = NULL;
+
+ /* pull free_desc out of the circle so that every node is a hw
+ * descriptor, but leave it pointing to the list
+ */
+ ioat_chan->free_desc.prev->next = ioat_chan->free_desc.next;
+ ioat_chan->free_desc.next->prev = ioat_chan->free_desc.prev;
+
+ /* circle link the hw descriptors */
+ desc = to_ioat_desc(ioat_chan->free_desc.next);
+ desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;
+ list_for_each_entry_safe(desc, _desc, ioat_chan->free_desc.next, node) {
+ desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;
+ }
+}
+
+/**
+ * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
+ * @chan: the channel to be filled out
+ */
static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
@@ -304,7 +440,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
/* have we already been set up? */
if (!list_empty(&ioat_chan->free_desc))
- return INITIAL_IOAT_DESC_COUNT;
+ return ioat_chan->desccount;
/* Setup register to interrupt and write completion status on error */
chanctrl = IOAT_CHANCTRL_ERR_INT_EN |
@@ -320,7 +456,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
}
/* Allocate descriptors */
- for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) {
+ for (i = 0; i < ioat_initial_desc_count; i++) {
desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
if (!desc) {
dev_err(&ioat_chan->device->pdev->dev,
@@ -330,7 +466,10 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
list_add_tail(&desc->node, &tmp_list);
}
spin_lock_bh(&ioat_chan->desc_lock);
+ ioat_chan->desccount = i;
list_splice(&tmp_list, &ioat_chan->free_desc);
+ if (ioat_chan->device->version != IOAT_VER_1_2)
+ ioat2_dma_massage_chan_desc(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
/* allocate a completion writeback area */
@@ -347,10 +486,14 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
tasklet_enable(&ioat_chan->cleanup_task);
- ioat_dma_start_null_desc(ioat_chan);
- return i;
+ ioat_dma_start_null_desc(ioat_chan); /* give chain to dma device */
+ return ioat_chan->desccount;
}
+/**
+ * ioat_dma_free_chan_resources - release all the descriptors
+ * @chan: the channel to be cleaned
+ */
static void ioat_dma_free_chan_resources(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
@@ -364,22 +507,45 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
/* Delay 100ms after reset to allow internal DMA logic to quiesce
* before removing DMA descriptor resources.
*/
- writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
mdelay(100);
spin_lock_bh(&ioat_chan->desc_lock);
- list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
- in_use_descs++;
- list_del(&desc->node);
- pci_pool_free(ioatdma_device->dma_pool, desc->hw,
- desc->async_tx.phys);
- kfree(desc);
- }
- list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
- list_del(&desc->node);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->used_desc, node) {
+ in_use_descs++;
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->free_desc, node) {
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ break;
+ case IOAT_VER_2_0:
+ list_for_each_entry_safe(desc, _desc,
+ ioat_chan->free_desc.next, node) {
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ desc = to_ioat_desc(ioat_chan->free_desc.next);
pci_pool_free(ioatdma_device->dma_pool, desc->hw,
desc->async_tx.phys);
kfree(desc);
+ INIT_LIST_HEAD(&ioat_chan->free_desc);
+ INIT_LIST_HEAD(&ioat_chan->used_desc);
+ break;
}
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -395,6 +561,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
ioat_chan->last_completion = ioat_chan->completion_addr = 0;
ioat_chan->pending = 0;
+ ioat_chan->dmacount = 0;
}
/**
@@ -406,7 +573,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
* has run out.
*/
static struct ioat_desc_sw *
-ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
{
struct ioat_desc_sw *new = NULL;
@@ -425,7 +592,82 @@ ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
return new;
}
-static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy(
+static struct ioat_desc_sw *
+ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *new = NULL;
+
+ /*
+ * used.prev points to where to start processing
+ * used.next points to next free descriptor
+ * if used.prev == NULL, there are none waiting to be processed
+ * if used.next == used.prev.prev, there is only one free descriptor,
+ * and we need to use it to as a noop descriptor before
+ * linking in a new set of descriptors, since the device
+ * has probably already read the pointer to it
+ */
+ if (ioat_chan->used_desc.prev &&
+ ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) {
+
+ struct ioat_desc_sw *desc = NULL;
+ struct ioat_desc_sw *noop_desc = NULL;
+ int i;
+
+ /* set up the noop descriptor */
+ noop_desc = to_ioat_desc(ioat_chan->used_desc.next);
+ noop_desc->hw->size = 0;
+ noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+ noop_desc->hw->src_addr = 0;
+ noop_desc->hw->dst_addr = 0;
+
+ ioat_chan->used_desc.next = ioat_chan->used_desc.next->next;
+ ioat_chan->pending++;
+ ioat_chan->dmacount++;
+
+ /* get a few more descriptors */
+ for (i = 16; i; i--) {
+ desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+ BUG_ON(!desc);
+ list_add_tail(&desc->node, ioat_chan->used_desc.next);
+
+ desc->hw->next
+ = to_ioat_desc(desc->node.next)->async_tx.phys;
+ to_ioat_desc(desc->node.prev)->hw->next
+ = desc->async_tx.phys;
+ ioat_chan->desccount++;
+ }
+
+ ioat_chan->used_desc.next = noop_desc->node.next;
+ }
+ new = to_ioat_desc(ioat_chan->used_desc.next);
+ prefetch(new);
+ ioat_chan->used_desc.next = new->node.next;
+
+ if (ioat_chan->used_desc.prev == NULL)
+ ioat_chan->used_desc.prev = &new->node;
+
+ prefetch(new->hw);
+ return new;
+}
+
+static struct ioat_desc_sw *ioat_dma_get_next_descriptor(
+ struct ioat_dma_chan *ioat_chan)
+{
+ if (!ioat_chan)
+ return NULL;
+
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ return ioat1_dma_get_next_descriptor(ioat_chan);
+ break;
+ case IOAT_VER_2_0:
+ return ioat2_dma_get_next_descriptor(ioat_chan);
+ break;
+ }
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
struct dma_chan *chan,
size_t len,
int int_en)
@@ -441,19 +683,62 @@ static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy(
return new ? &new->async_tx : NULL;
}
+static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
+ struct dma_chan *chan,
+ size_t len,
+ int int_en)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioat_desc_sw *new;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ new = ioat2_dma_get_next_descriptor(ioat_chan);
+ new->len = len;
+
+ /* leave ioat_chan->desc_lock set in version 2 path */
+ return new ? &new->async_tx : NULL;
+}
+
+
/**
* ioat_dma_memcpy_issue_pending - push potentially unrecognized appended
* descriptors to hw
* @chan: DMA channel handle
*/
-static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
+static inline void __ioat1_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET);
+}
+
+static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
if (ioat_chan->pending != 0) {
- ioat_chan->pending = 0;
- writeb(IOAT_CHANCMD_APPEND,
- ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ }
+}
+
+static inline void __ioat2_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writew(ioat_chan->dmacount,
+ ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+}
+
+static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (ioat_chan->pending != 0) {
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
}
}
@@ -465,11 +750,17 @@ static void ioat_dma_cleanup_tasklet(unsigned long data)
chan->reg_base + IOAT_CHANCTRL_OFFSET);
}
+/**
+ * ioat_dma_memcpy_cleanup - cleanup up finished descriptors
+ * @chan: ioat channel to be cleaned up
+ */
static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
{
unsigned long phys_complete;
struct ioat_desc_sw *desc, *_desc;
dma_cookie_t cookie = 0;
+ unsigned long desc_phys;
+ struct ioat_desc_sw *latest_desc;
prefetch(ioat_chan->completion_virt);
@@ -507,56 +798,115 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
cookie = 0;
spin_lock_bh(&ioat_chan->desc_lock);
- list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
-
- /*
- * Incoming DMA requests may use multiple descriptors, due to
- * exceeding xfercap, perhaps. If so, only the last one will
- * have a cookie, and require unmapping.
- */
- if (desc->async_tx.cookie) {
- cookie = desc->async_tx.cookie;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->used_desc, node) {
/*
- * yes we are unmapping both _page and _single alloc'd
- * regions with unmap_page. Is this *really* that bad?
+ * Incoming DMA requests may use multiple descriptors,
+ * due to exceeding xfercap, perhaps. If so, only the
+ * last one will have a cookie, and require unmapping.
*/
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
- if (desc->async_tx.callback) {
- desc->async_tx.callback(
- desc->async_tx.callback_param);
- desc->async_tx.callback = NULL;
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
+
+ /*
+ * yes we are unmapping both _page and _single
+ * alloc'd regions with unmap_page. Is this
+ * *really* that bad?
+ */
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+
+ if (desc->async_tx.callback) {
+ desc->async_tx.callback(desc->async_tx.callback_param);
+ desc->async_tx.callback = NULL;
+ }
}
- }
- if (desc->async_tx.phys != phys_complete) {
- /*
- * a completed entry, but not the last, so cleanup
- * if the client is done with the descriptor
- */
- if (desc->async_tx.ack) {
- list_del(&desc->node);
- list_add_tail(&desc->node,
- &ioat_chan->free_desc);
- } else
+ if (desc->async_tx.phys != phys_complete) {
+ /*
+ * a completed entry, but not the last, so clean
+ * up if the client is done with the descriptor
+ */
+ if (desc->async_tx.ack) {
+ list_del(&desc->node);
+ list_add_tail(&desc->node,
+ &ioat_chan->free_desc);
+ } else
+ desc->async_tx.cookie = 0;
+ } else {
+ /*
+ * last used desc. Do not remove, so we can
+ * append from it, but don't look at it next
+ * time, either
+ */
desc->async_tx.cookie = 0;
- } else {
- /*
- * last used desc. Do not remove, so we can append from
- * it, but don't look at it next time, either
- */
- desc->async_tx.cookie = 0;
- /* TODO check status bits? */
+ /* TODO check status bits? */
+ break;
+ }
+ }
+ break;
+ case IOAT_VER_2_0:
+ /* has some other thread has already cleaned up? */
+ if (ioat_chan->used_desc.prev == NULL)
break;
+
+ /* work backwards to find latest finished desc */
+ desc = to_ioat_desc(ioat_chan->used_desc.next);
+ latest_desc = NULL;
+ do {
+ desc = to_ioat_desc(desc->node.prev);
+ desc_phys = (unsigned long)desc->async_tx.phys
+ & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+ if (desc_phys == phys_complete) {
+ latest_desc = desc;
+ break;
+ }
+ } while (&desc->node != ioat_chan->used_desc.prev);
+
+ if (latest_desc != NULL) {
+
+ /* work forwards to clear finished descriptors */
+ for (desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ &desc->node != latest_desc->node.next &&
+ &desc->node != ioat_chan->used_desc.next;
+ desc = to_ioat_desc(desc->node.next)) {
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
+ desc->async_tx.cookie = 0;
+
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+
+ if (desc->async_tx.callback) {
+ desc->async_tx.callback(desc->async_tx.callback_param);
+ desc->async_tx.callback = NULL;
+ }
+ }
+ }
+
+ /* move used.prev up beyond those that are finished */
+ if (&desc->node == ioat_chan->used_desc.next)
+ ioat_chan->used_desc.prev = NULL;
+ else
+ ioat_chan->used_desc.prev = &desc->node;
}
+ break;
}
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -621,8 +971,6 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
return dma_async_is_complete(cookie, last_complete, last_used);
}
-/* PCI API */
-
static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
{
struct ioat_desc_sw *desc;
@@ -633,21 +981,34 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL
| IOAT_DMA_DESCRIPTOR_CTL_INT_GN
| IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
- desc->hw->next = 0;
desc->hw->size = 0;
desc->hw->src_addr = 0;
desc->hw->dst_addr = 0;
desc->async_tx.ack = 1;
-
- list_add_tail(&desc->node, &ioat_chan->used_desc);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc->hw->next = 0;
+ list_add_tail(&desc->node, &ioat_chan->used_desc);
+
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ writeb(IOAT_CHANCMD_START, ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ break;
+ case IOAT_VER_2_0:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
+
+ ioat_chan->dmacount++;
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ break;
+ }
spin_unlock_bh(&ioat_chan->desc_lock);
-
- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
- ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW);
- writel(((u64) desc->async_tx.phys) >> 32,
- ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH);
-
- writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
}
/*
@@ -693,14 +1054,14 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (ioat_dma_alloc_chan_resources(dma_chan) < 1) {
+ if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
dev_err(&device->pdev->dev,
"selftest cannot allocate chan resource\n");
err = -ENODEV;
goto out;
}
- tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+ tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
if (!tx) {
dev_err(&device->pdev->dev,
"Self-test prep failed, disabling\n");
@@ -710,24 +1071,25 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
async_tx_ack(tx);
addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
- DMA_TO_DEVICE);
- ioat_set_src(addr, tx, 0);
+ DMA_TO_DEVICE);
+ tx->tx_set_src(addr, tx, 0);
addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
- DMA_FROM_DEVICE);
- ioat_set_dest(addr, tx, 0);
+ DMA_FROM_DEVICE);
+ tx->tx_set_dest(addr, tx, 0);
tx->callback = ioat_dma_test_callback;
tx->callback_param = (void *)0x8086;
- cookie = ioat_tx_submit(tx);
+ cookie = tx->tx_submit(tx);
if (cookie < 0) {
dev_err(&device->pdev->dev,
"Self-test setup failed, disabling\n");
err = -ENODEV;
goto free_resources;
}
- ioat_dma_memcpy_issue_pending(dma_chan);
+ device->common.device_issue_pending(dma_chan);
msleep(1);
- if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+ if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
+ != DMA_SUCCESS) {
dev_err(&device->pdev->dev,
"Self-test copy timed out, disabling\n");
err = -ENODEV;
@@ -741,7 +1103,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
}
free_resources:
- ioat_dma_free_chan_resources(dma_chan);
+ device->common.device_free_chan_resources(dma_chan);
out:
kfree(src);
kfree(dest);
@@ -941,16 +1303,28 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
INIT_LIST_HEAD(&device->common.channels);
ioat_dma_enumerate_channels(device);
- dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
device->common.device_alloc_chan_resources =
ioat_dma_alloc_chan_resources;
device->common.device_free_chan_resources =
ioat_dma_free_chan_resources;
- device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
+ device->common.dev = &pdev->dev;
+
+ dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
device->common.device_is_tx_complete = ioat_dma_is_complete;
- device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
device->common.device_dependency_added = ioat_dma_dependency_added;
- device->common.dev = &pdev->dev;
+ switch (device->version) {
+ case IOAT_VER_1_2:
+ device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
+ device->common.device_issue_pending =
+ ioat1_dma_memcpy_issue_pending;
+ break;
+ case IOAT_VER_2_0:
+ device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;
+ device->common.device_issue_pending =
+ ioat2_dma_memcpy_issue_pending;
+ break;
+ }
+
dev_err(&device->pdev->dev,
"Intel(R) I/OAT DMA Engine found,"
" %d channels, device version 0x%02x, driver version %s\n",
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index 5f9881e7b0e..b668234ef65 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,7 @@
#include <linux/cache.h>
#include <linux/pci_ids.h>
-#define IOAT_DMA_VERSION "1.26"
+#define IOAT_DMA_VERSION "2.04"
enum ioat_interrupt {
none = 0,
@@ -39,6 +39,8 @@ enum ioat_interrupt {
};
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0
+#define IOAT_DMA_DCA_ANY_CPU ~0
+
/**
* struct ioatdma_device - internal representation of a IOAT device
@@ -47,6 +49,9 @@ enum ioat_interrupt {
* @dma_pool: for allocating DMA descriptors
* @common: embedded struct dma_device
* @version: version of ioatdma device
+ * @irq_mode: which style irq to use
+ * @msix_entries: irq handlers
+ * @idx: per channel data
*/
struct ioatdma_device {
@@ -63,23 +68,7 @@ struct ioatdma_device {
/**
* struct ioat_dma_chan - internal representation of a DMA channel
- * @device:
- * @reg_base:
- * @sw_in_use:
- * @completion:
- * @completion_low:
- * @completion_high:
- * @completed_cookie: last cookie seen completed on cleanup
- * @cookie: value of last cookie given to client
- * @last_completion:
- * @xfercap:
- * @desc_lock:
- * @free_desc:
- * @used_desc:
- * @resource:
- * @device_node:
*/
-
struct ioat_dma_chan {
void __iomem *reg_base;
@@ -95,6 +84,8 @@ struct ioat_dma_chan {
struct list_head used_desc;
int pending;
+ int dmacount;
+ int desccount;
struct ioatdma_device *device;
struct dma_chan common;
@@ -134,12 +125,13 @@ struct ioat_desc_sw {
struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
void __iomem *iobase);
void ioat_dma_remove(struct ioatdma_device *device);
-struct dca_provider *ioat_dca_init(struct pci_dev *pdev,
- void __iomem *iobase);
+struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
#else
#define ioat_dma_probe(pdev, iobase) NULL
#define ioat_dma_remove(device) do { } while (0)
#define ioat_dca_init(pdev, iobase) NULL
+#define ioat2_dca_init(pdev, iobase) NULL
#endif
#endif /* IOATDMA_H */
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index 9e7434e1551..dd470fa91d8 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,12 +22,19 @@
#define _IOAT_HW_H_
/* PCI Configuration Space Values */
-#define IOAT_PCI_VID 0x8086
-#define IOAT_PCI_DID 0x1A38
-#define IOAT_PCI_RID 0x00
-#define IOAT_PCI_SVID 0x8086
-#define IOAT_PCI_SID 0x8086
-#define IOAT_VER_1_2 0x12 /* Version 1.2 */
+#define IOAT_PCI_VID 0x8086
+
+/* CB device ID's */
+#define IOAT_PCI_DID_5000 0x1A38
+#define IOAT_PCI_DID_CNB 0x360B
+#define IOAT_PCI_DID_SCNB 0x65FF
+#define IOAT_PCI_DID_SNB 0x402F
+
+#define IOAT_PCI_RID 0x00
+#define IOAT_PCI_SVID 0x8086
+#define IOAT_PCI_SID 0x8086
+#define IOAT_VER_1_2 0x12 /* Version 1.2 */
+#define IOAT_VER_2_0 0x20 /* Version 2.0 */
struct ioat_dma_descriptor {
uint32_t size;
@@ -47,6 +54,16 @@ struct ioat_dma_descriptor {
#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008
#define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010
#define IOAT_DMA_DESCRIPTOR_NUL 0x00000020
-#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000
+#define IOAT_DMA_DESCRIPTOR_CTL_SP_BRK 0x00000040
+#define IOAT_DMA_DESCRIPTOR_CTL_DP_BRK 0x00000080
+#define IOAT_DMA_DESCRIPTOR_CTL_BNDL 0x00000100
+#define IOAT_DMA_DESCRIPTOR_CTL_DCA 0x00000200
+#define IOAT_DMA_DESCRIPTOR_CTL_BUFHINT 0x00000400
+
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_CONTEXT 0xFF000000
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_DMA 0x00000000
+
+#define IOAT_DMA_DESCRIPTOR_CTL_CONTEXT_DCA 0x00000001
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_MASK 0xFF000000
#endif
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index baaab5ea146..9832d7ebd93 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -42,26 +42,25 @@
#define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */
#define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */
#define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */
-#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */
+#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */
#define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */
#define IOAT_VER_OFFSET 0x08 /* 8-bit */
#define IOAT_VER_MAJOR_MASK 0xF0
#define IOAT_VER_MINOR_MASK 0x0F
-#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK)
+#define GET_IOAT_VER_MAJOR(x) (((x) & IOAT_VER_MAJOR_MASK) >> 4)
#define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK)
#define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */
#define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */
#define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */
-#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */
+#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */
#define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */
#define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001
-
#define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */
/* DMA Channel Registers */
@@ -74,25 +73,101 @@
#define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004
#define IOAT_CHANCTRL_INT_DISABLE 0x0001
-#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */
-#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */
-
-#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */
-#define IOAT_CHANSTS_OFFSET_LOW 0x04
-#define IOAT_CHANSTS_OFFSET_HIGH 0x08
-#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL
+#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */
+#define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */
+#define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */
+
+
+#define IOAT1_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */
+#define IOAT2_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */
+#define IOAT_CHANSTS_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET : IOAT2_CHANSTS_OFFSET)
+#define IOAT1_CHANSTS_OFFSET_LOW 0x04
+#define IOAT2_CHANSTS_OFFSET_LOW 0x08
+#define IOAT_CHANSTS_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET_LOW : IOAT2_CHANSTS_OFFSET_LOW)
+#define IOAT1_CHANSTS_OFFSET_HIGH 0x08
+#define IOAT2_CHANSTS_OFFSET_HIGH 0x0C
+#define IOAT_CHANSTS_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET_HIGH : IOAT2_CHANSTS_OFFSET_HIGH)
+#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR ~0x3F
#define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010
+#define IOAT_CHANSTS_UNAFFILIATED_ERR 0x0000000000000008
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3
-#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
-#define IOAT_CHAINADDR_OFFSET_LOW 0x0C
-#define IOAT_CHAINADDR_OFFSET_HIGH 0x10
-#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */
+
+#define IOAT_CHAN_DMACOUNT_OFFSET 0x06 /* 16-bit DMA Count register */
+
+#define IOAT_DCACTRL_OFFSET 0x30 /* 32 bit Direct Cache Access Control Register */
+#define IOAT_DCACTRL_CMPL_WRITE_ENABLE 0x10000
+#define IOAT_DCACTRL_TARGET_CPU_MASK 0xFFFF /* APIC ID */
+
+/* CB DCA Memory Space Registers */
+#define IOAT_DCAOFFSET_OFFSET 0x14
+/* CB_BAR + IOAT_DCAOFFSET value */
+#define IOAT_DCA_VER_OFFSET 0x00
+#define IOAT_DCA_VER_MAJOR_MASK 0xF0
+#define IOAT_DCA_VER_MINOR_MASK 0x0F
+
+#define IOAT_DCA_COMP_OFFSET 0x02
+#define IOAT_DCA_COMP_V1 0x1
+
+#define IOAT_FSB_CAPABILITY_OFFSET 0x04
+#define IOAT_FSB_CAPABILITY_PREFETCH 0x1
+
+#define IOAT_PCI_CAPABILITY_OFFSET 0x06
+#define IOAT_PCI_CAPABILITY_MEMWR 0x1
+
+#define IOAT_FSB_CAP_ENABLE_OFFSET 0x08
+#define IOAT_FSB_CAP_ENABLE_PREFETCH 0x1
+
+#define IOAT_PCI_CAP_ENABLE_OFFSET 0x0A
+#define IOAT_PCI_CAP_ENABLE_MEMWR 0x1
+
+#define IOAT_APICID_TAG_MAP_OFFSET 0x0C
+#define IOAT_APICID_TAG_MAP_TAG0 0x0000000F
+#define IOAT_APICID_TAG_MAP_TAG0_SHIFT 0
+#define IOAT_APICID_TAG_MAP_TAG1 0x000000F0
+#define IOAT_APICID_TAG_MAP_TAG1_SHIFT 4
+#define IOAT_APICID_TAG_MAP_TAG2 0x00000F00
+#define IOAT_APICID_TAG_MAP_TAG2_SHIFT 8
+#define IOAT_APICID_TAG_MAP_TAG3 0x0000F000
+#define IOAT_APICID_TAG_MAP_TAG3_SHIFT 12
+#define IOAT_APICID_TAG_MAP_TAG4 0x000F0000
+#define IOAT_APICID_TAG_MAP_TAG4_SHIFT 16
+#define IOAT_APICID_TAG_CB2_VALID 0x8080808080
+
+#define IOAT_DCA_GREQID_OFFSET 0x10
+#define IOAT_DCA_GREQID_SIZE 0x04
+#define IOAT_DCA_GREQID_MASK 0xFFFF
+#define IOAT_DCA_GREQID_IGNOREFUN 0x10000000
+#define IOAT_DCA_GREQID_VALID 0x20000000
+#define IOAT_DCA_GREQID_LASTID 0x80000000
+
+
+
+#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
+#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */
+#define IOAT_CHAINADDR_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET : IOAT2_CHAINADDR_OFFSET)
+#define IOAT1_CHAINADDR_OFFSET_LOW 0x0C
+#define IOAT2_CHAINADDR_OFFSET_LOW 0x10
+#define IOAT_CHAINADDR_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET_LOW : IOAT2_CHAINADDR_OFFSET_LOW)
+#define IOAT1_CHAINADDR_OFFSET_HIGH 0x10
+#define IOAT2_CHAINADDR_OFFSET_HIGH 0x14
+#define IOAT_CHAINADDR_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET_HIGH : IOAT2_CHAINADDR_OFFSET_HIGH)
+
+#define IOAT1_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */
+#define IOAT2_CHANCMD_OFFSET 0x04 /* 8-bit DMA Channel Command Register */
+#define IOAT_CHANCMD_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANCMD_OFFSET : IOAT2_CHANCMD_OFFSET)
#define IOAT_CHANCMD_RESET 0x20
#define IOAT_CHANCMD_RESUME 0x10
#define IOAT_CHANCMD_ABORT 0x08
@@ -124,6 +199,7 @@
#define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000
#define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000
#define IOAT_CHANERR_SOFT_ERR 0x4000
+#define IOAT_CHANERR_UNAFFILIATED_ERR 0x8000
#define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 96f7e63e399..a1f24c42d5f 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1462,7 +1462,7 @@ MODULE_DEVICE_TABLE(pci, i5000_pci_tbl);
*
*/
static struct pci_driver i5000_driver = {
- .name = __stringify(KBUILD_BASENAME),
+ .name = KBUILD_BASENAME,
.probe = i5000_init_one,
.remove = __devexit_p(i5000_remove_one),
.id_table = i5000_pci_tbl,
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 5596df65c8e..624ff3e082f 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -650,13 +650,14 @@ static void sbp2_login(struct work_struct *work)
if (sbp2_send_management_orb(lu, node_id, generation,
SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
if (lu->retries++ < 5) {
- queue_delayed_work(sbp2_wq, &lu->work,
- DIV_ROUND_UP(HZ, 5));
+ if (queue_delayed_work(sbp2_wq, &lu->work,
+ DIV_ROUND_UP(HZ, 5)))
+ kref_get(&lu->tgt->kref);
} else {
fw_error("failed to login to %s LUN %04x\n",
unit->device.bus_id, lu->lun);
- kref_put(&lu->tgt->kref, sbp2_release_target);
}
+ kref_put(&lu->tgt->kref, sbp2_release_target);
return;
}
@@ -914,7 +915,9 @@ static void sbp2_reconnect(struct work_struct *work)
lu->retries = 0;
PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
}
- queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5));
+ if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
+ kref_get(&lu->tgt->kref);
+ kref_put(&lu->tgt->kref, sbp2_release_target);
return;
}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 700a1657554..a0445bea9f7 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -216,6 +216,16 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module
will be called ds1621.
+config SENSORS_I5K_AMB
+ tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
+ depends on PCI && EXPERIMENTAL
+ help
+ If you say yes here you get support for FB-DIMM AMB temperature
+ monitoring chips on systems with the Intel 5000 series chipset.
+
+ This driver can also be built as a module. If so, the module
+ will be called i5k_amb.
+
config SENSORS_F71805F
tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
depends on EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 6da3eef9430..55595f6e1aa 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
+obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index cb2331bfd9d..d9f04ce9032 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -503,7 +503,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 FAN", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001A, "unknown", {
+ { 0x001A, "Abit IP35 Pro", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -530,6 +530,60 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
+ { 0x001B, "unknown", {
+ { "CPU Core", 0, 0, 10, 1, 0 },
+ { "DDR3", 1, 0, 20, 1, 0 },
+ { "DDR3 VTT", 2, 0, 10, 1, 0 },
+ { "CPU VTT", 3, 0, 10, 1, 0 },
+ { "MCH 1.25V", 4, 0, 10, 1, 0 },
+ { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
+ { "ICH 1.05V", 6, 0, 10, 1, 0 },
+ { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+ { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
+ { "ATX +5V", 9, 0, 30, 1, 0 },
+ { "+3.3V", 10, 0, 20, 1, 0 },
+ { "5VSB", 11, 0, 30, 1, 0 },
+ { "CPU", 24, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM Phase1", 26, 1, 1, 1, 0 },
+ { "PWM Phase2", 27, 1, 1, 1, 0 },
+ { "PWM Phase3", 28, 1, 1, 1, 0 },
+ { "PWM Phase4", 29, 1, 1, 1, 0 },
+ { "PWM Phase5", 30, 1, 1, 1, 0 },
+ { "CPU Fan", 32, 2, 60, 1, 0 },
+ { "SYS Fan", 34, 2, 60, 1, 0 },
+ { "AUX1 Fan", 33, 2, 60, 1, 0 },
+ { "AUX2 Fan", 35, 2, 60, 1, 0 },
+ { "AUX3 Fan", 36, 2, 60, 1, 0 },
+ { NULL, 0, 0, 0, 0, 0 } }
+ },
+ { 0x001C, "unknown", {
+ { "CPU Core", 0, 0, 10, 1, 0 },
+ { "DDR2", 1, 0, 20, 1, 0 },
+ { "DDR2 VTT", 2, 0, 10, 1, 0 },
+ { "CPU VTT", 3, 0, 10, 1, 0 },
+ { "MCH 1.25V", 4, 0, 10, 1, 0 },
+ { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
+ { "ICH 1.05V", 6, 0, 10, 1, 0 },
+ { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+ { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
+ { "ATX +5V", 9, 0, 30, 1, 0 },
+ { "+3.3V", 10, 0, 20, 1, 0 },
+ { "5VSB", 11, 0, 30, 1, 0 },
+ { "CPU", 24, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM Phase1", 26, 1, 1, 1, 0 },
+ { "PWM Phase2", 27, 1, 1, 1, 0 },
+ { "PWM Phase3", 28, 1, 1, 1, 0 },
+ { "PWM Phase4", 29, 1, 1, 1, 0 },
+ { "PWM Phase5", 30, 1, 1, 1, 0 },
+ { "CPU Fan", 32, 2, 60, 1, 0 },
+ { "SYS Fan", 34, 2, 60, 1, 0 },
+ { "AUX1 Fan", 33, 2, 60, 1, 0 },
+ { "AUX2 Fan", 35, 2, 60, 1, 0 },
+ { "AUX3 Fan", 36, 2, 60, 1, 0 },
+ { NULL, 0, 0, 0, 0, 0 } }
+ },
{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
};
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 1001d2e122a..86c66c345f8 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -80,7 +80,7 @@
/*
* Temperature sensors keys (sp78 - 2 bytes).
*/
-static const char* temperature_sensors_sets[][13] = {
+static const char* temperature_sensors_sets[][36] = {
/* Set 0: Macbook Pro */
{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
"Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
@@ -88,7 +88,13 @@ static const char* temperature_sensors_sets[][13] = {
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
"Th1H", "Ts0P", NULL },
/* Set 2: Macmini set */
- { "TC0D", "TC0P", NULL }
+ { "TC0D", "TC0P", NULL },
+/* Set 3: Mac Pro (2 x Quad-Core) */
+ { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
+ "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
+ "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
+ "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
+ "TM9S", "TN0H", "TS0C", NULL },
};
/* List of keys used to read/write fan speeds */
@@ -990,14 +996,18 @@ static struct attribute *fan##offset##_attributes[] = { \
/*
* Create the needed functions for each fan using the macro defined above
- * (2 fans are supported)
+ * (4 fans are supported)
*/
sysfs_fan_speeds_offset(1);
sysfs_fan_speeds_offset(2);
+sysfs_fan_speeds_offset(3);
+sysfs_fan_speeds_offset(4);
static const struct attribute_group fan_attribute_groups[] = {
{ .attrs = fan1_attributes },
- { .attrs = fan2_attributes }
+ { .attrs = fan2_attributes },
+ { .attrs = fan3_attributes },
+ { .attrs = fan4_attributes },
};
/*
@@ -1027,6 +1037,52 @@ static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
applesmc_show_temperature, NULL, 10);
static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
applesmc_show_temperature, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 14);
+static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 15);
+static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 16);
+static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 17);
+static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 18);
+static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 19);
+static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 20);
+static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 21);
+static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 22);
+static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 23);
+static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 24);
+static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 25);
+static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 26);
+static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 27);
+static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 28);
+static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 29);
+static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 30);
+static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 31);
+static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 32);
+static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 33);
+static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 34);
static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1041,6 +1097,29 @@ static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp10_input.dev_attr.attr,
&sensor_dev_attr_temp11_input.dev_attr.attr,
&sensor_dev_attr_temp12_input.dev_attr.attr,
+ &sensor_dev_attr_temp13_input.dev_attr.attr,
+ &sensor_dev_attr_temp14_input.dev_attr.attr,
+ &sensor_dev_attr_temp15_input.dev_attr.attr,
+ &sensor_dev_attr_temp16_input.dev_attr.attr,
+ &sensor_dev_attr_temp17_input.dev_attr.attr,
+ &sensor_dev_attr_temp18_input.dev_attr.attr,
+ &sensor_dev_attr_temp19_input.dev_attr.attr,
+ &sensor_dev_attr_temp20_input.dev_attr.attr,
+ &sensor_dev_attr_temp21_input.dev_attr.attr,
+ &sensor_dev_attr_temp22_input.dev_attr.attr,
+ &sensor_dev_attr_temp23_input.dev_attr.attr,
+ &sensor_dev_attr_temp24_input.dev_attr.attr,
+ &sensor_dev_attr_temp25_input.dev_attr.attr,
+ &sensor_dev_attr_temp26_input.dev_attr.attr,
+ &sensor_dev_attr_temp27_input.dev_attr.attr,
+ &sensor_dev_attr_temp28_input.dev_attr.attr,
+ &sensor_dev_attr_temp29_input.dev_attr.attr,
+ &sensor_dev_attr_temp30_input.dev_attr.attr,
+ &sensor_dev_attr_temp31_input.dev_attr.attr,
+ &sensor_dev_attr_temp32_input.dev_attr.attr,
+ &sensor_dev_attr_temp33_input.dev_attr.attr,
+ &sensor_dev_attr_temp34_input.dev_attr.attr,
+ &sensor_dev_attr_temp35_input.dev_attr.attr,
NULL
};
@@ -1137,6 +1216,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 1, .light = 0, .temperature_set = 1 },
/* MacMini: temperature set 2 */
{ .accelerometer = 0, .light = 0, .temperature_set = 2 },
+/* MacPro: temperature set 3 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 3 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1154,6 +1235,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
(void*)&applesmc_dmi_data[2]},
+ { applesmc_dmi_match, "Apple MacPro2", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
+ (void*)&applesmc_dmi_data[3]},
{ .ident = NULL }
};
@@ -1204,9 +1289,19 @@ static int __init applesmc_init(void)
switch (count) {
default:
- printk(KERN_WARNING "applesmc: More than 2 fans found,"
- " but at most 2 fans are supported"
+ printk(KERN_WARNING "applesmc: More than 4 fans found,"
+ " but at most 4 fans are supported"
" by the driver.\n");
+ case 4:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[3]);
+ if (ret)
+ goto out_key_enumeration;
+ case 3:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[2]);
+ if (ret)
+ goto out_key_enumeration;
case 2:
ret = sysfs_create_group(&pdev->dev.kobj,
&fan_attribute_groups[1]);
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 13a041326a0..6892f76fc18 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -34,6 +34,7 @@
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/f75375s.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END };
@@ -86,7 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
struct f75375_data {
unsigned short addr;
- struct i2c_client client;
+ struct i2c_client *client;
struct device *hwmon_dev;
const char *name;
@@ -116,15 +117,25 @@ struct f75375_data {
static int f75375_attach_adapter(struct i2c_adapter *adapter);
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
static int f75375_detach_client(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client);
+static int f75375_remove(struct i2c_client *client);
-static struct i2c_driver f75375_driver = {
+static struct i2c_driver f75375_legacy_driver = {
.driver = {
- .name = "f75375",
+ .name = "f75375_legacy",
},
.attach_adapter = f75375_attach_adapter,
.detach_client = f75375_detach_client,
};
+static struct i2c_driver f75375_driver = {
+ .driver = {
+ .name = "f75375",
+ },
+ .probe = f75375_probe,
+ .remove = f75375_remove,
+};
+
static inline int f75375_read8(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@@ -276,19 +287,14 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", data->pwm_enable[nr]);
}
-static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
{
- int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
struct f75375_data *data = i2c_get_clientdata(client);
- int val = simple_strtoul(buf, NULL, 10);
u8 fanmode;
if (val < 0 || val > 4)
return -EINVAL;
- mutex_lock(&data->update_lock);
fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
fanmode = ~(3 << FAN_CTRL_MODE(nr));
@@ -310,8 +316,22 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
}
f75375_write8(client, F75375_REG_FAN_TIMER, fanmode);
data->pwm_enable[nr] = val;
+ return 0;
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct f75375_data *data = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ int err = 0;
+
+ mutex_lock(&data->update_lock);
+ err = set_pwm_enable_direct(client, nr, val);
mutex_unlock(&data->update_lock);
- return count;
+ return err ? err : count;
}
static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
@@ -323,7 +343,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
int val = simple_strtoul(buf, NULL, 10);
u8 conf = 0;
- if (val != 0 || val != 1 || data->kind == f75373)
+ if (!(val == 0 || val == 1))
return -EINVAL;
mutex_lock(&data->update_lock);
@@ -529,13 +549,13 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR,
show_pwm, set_pwm, 0);
static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR,
show_pwm_enable, set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO,
show_pwm_mode, set_pwm_mode, 0);
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR,
show_pwm, set_pwm, 1);
static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR,
show_pwm_enable, set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO,
show_pwm_mode, set_pwm_mode, 1);
static struct attribute *f75375_attributes[] = {
@@ -580,12 +600,9 @@ static const struct attribute_group f75375_group = {
static int f75375_detach_client(struct i2c_client *client)
{
- struct f75375_data *data = i2c_get_clientdata(client);
int err;
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &f75375_group);
-
+ f75375_remove(client);
err = i2c_detach_client(client);
if (err) {
dev_err(&client->dev,
@@ -593,7 +610,91 @@ static int f75375_detach_client(struct i2c_client *client)
"client not detached.\n");
return err;
}
+ kfree(client);
+ return 0;
+}
+
+static void f75375_init(struct i2c_client *client, struct f75375_data *data,
+ struct f75375s_platform_data *f75375s_pdata)
+{
+ int nr;
+ set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]);
+ set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]);
+ for (nr = 0; nr < 2; nr++) {
+ data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255);
+ f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr),
+ data->pwm[nr]);
+ }
+
+}
+
+static int f75375_probe(struct i2c_client *client)
+{
+ struct f75375_data *data = i2c_get_clientdata(client);
+ struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+ if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
+
+ if (strcmp(client->name, "f75375") == 0)
+ data->kind = f75375;
+ else if (strcmp(client->name, "f75373") == 0)
+ data->kind = f75373;
+ else {
+ dev_err(&client->dev, "Unsupported device: %s\n", client->name);
+ return -ENODEV;
+ }
+
+ if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ goto exit_free;
+
+ if (data->kind == f75375) {
+ err = sysfs_chmod_file(&client->dev.kobj,
+ &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+ S_IRUGO | S_IWUSR);
+ if (err)
+ goto exit_remove;
+ err = sysfs_chmod_file(&client->dev.kobj,
+ &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+ S_IRUGO | S_IWUSR);
+ if (err)
+ goto exit_remove;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ if (f75375s_pdata != NULL)
+ f75375_init(client, data, f75375s_pdata);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &f75375_group);
+exit_free:
kfree(data);
+ i2c_set_clientdata(client, NULL);
+ return err;
+}
+
+static int f75375_remove(struct i2c_client *client)
+{
+ struct f75375_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &f75375_group);
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
return 0;
}
@@ -608,20 +709,17 @@ static int f75375_attach_adapter(struct i2c_adapter *adapter)
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
- struct f75375_data *data;
u8 version = 0;
int err = 0;
const char *name = "";
- if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) {
+ if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- client = &data->client;
- i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
- client->driver = &f75375_driver;
+ client->driver = &f75375_legacy_driver;
if (kind < 0) {
u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
@@ -644,42 +742,42 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == f75373) {
name = "f75373";
}
-
dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
strlcpy(client->name, name, I2C_NAME_SIZE);
- data->kind = kind;
- mutex_init(&data->update_lock);
+
if ((err = i2c_attach_client(client)))
goto exit_free;
- if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ if ((err = f75375_probe(client)) < 0)
goto exit_detach;
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
return 0;
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &f75375_group);
exit_detach:
i2c_detach_client(client);
exit_free:
- kfree(data);
+ kfree(client);
exit:
return err;
}
static int __init sensors_f75375_init(void)
{
- return i2c_add_driver(&f75375_driver);
+ int status;
+ status = i2c_add_driver(&f75375_driver);
+ if (status)
+ return status;
+
+ status = i2c_add_driver(&f75375_legacy_driver);
+ if (status)
+ i2c_del_driver(&f75375_driver);
+
+ return status;
}
static void __exit sensors_f75375_exit(void)
{
+ i2c_del_driver(&f75375_legacy_driver);
i2c_del_driver(&f75375_driver);
}
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
new file mode 100644
index 00000000000..6ac5c6f5358
--- /dev/null
+++ b/drivers/hwmon/i5k_amb.c
@@ -0,0 +1,552 @@
+/*
+ * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB
+ * temperature sensors
+ * Copyright (C) 2007 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#define DRVNAME "i5k_amb"
+
+#define I5K_REG_AMB_BASE_ADDR 0x48
+#define I5K_REG_AMB_LEN_ADDR 0x50
+#define I5K_REG_CHAN0_PRESENCE_ADDR 0x64
+#define I5K_REG_CHAN1_PRESENCE_ADDR 0x66
+
+#define AMB_REG_TEMP_MIN_ADDR 0x80
+#define AMB_REG_TEMP_MID_ADDR 0x81
+#define AMB_REG_TEMP_MAX_ADDR 0x82
+#define AMB_REG_TEMP_STATUS_ADDR 0x84
+#define AMB_REG_TEMP_ADDR 0x85
+
+#define AMB_CONFIG_SIZE 2048
+#define AMB_FUNC_3_OFFSET 768
+
+static unsigned long amb_reg_temp_status(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_min(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_mid(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_max(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+#define MAX_MEM_CHANNELS 4
+#define MAX_AMBS_PER_CHANNEL 16
+#define MAX_AMBS (MAX_MEM_CHANNELS * \
+ MAX_AMBS_PER_CHANNEL)
+/*
+ * Ugly hack: For some reason the highest bit is set if there
+ * are _any_ DIMMs in the channel. Attempting to read from
+ * this "high-order" AMB results in a memory bus error, so
+ * for now we'll just ignore that top bit, even though that
+ * might prevent us from seeing the 16th DIMM in the channel.
+ */
+#define REAL_MAX_AMBS_PER_CHANNEL 15
+#define KNOBS_PER_AMB 5
+
+static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit)
+{
+ return byte_num * MAX_AMBS_PER_CHANNEL + bit;
+}
+
+#define AMB_SYSFS_NAME_LEN 16
+struct i5k_device_attribute {
+ struct sensor_device_attribute s_attr;
+ char name[AMB_SYSFS_NAME_LEN];
+};
+
+struct i5k_amb_data {
+ struct device *hwmon_dev;
+
+ unsigned long amb_base;
+ unsigned long amb_len;
+ u16 amb_present[MAX_MEM_CHANNELS];
+ void __iomem *amb_mmio;
+ struct i5k_device_attribute *attrs;
+ unsigned int num_attrs;
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", DRVNAME);
+}
+
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct platform_device *amb_pdev;
+
+static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset)
+{
+ return ioread8(data->amb_mmio + offset);
+}
+
+static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset,
+ u8 val)
+{
+ iowrite8(val, data->amb_mmio + offset);
+}
+
+static ssize_t show_amb_alarm(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+
+ if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) &&
+ (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8))
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t store_amb_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_min(attr->index), temp);
+ return count;
+}
+
+static ssize_t store_amb_mid(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_mid(attr->index), temp);
+ return count;
+}
+
+static ssize_t store_amb_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_max(attr->index), temp);
+ return count;
+}
+
+static ssize_t show_amb_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_min(attr->index)));
+}
+
+static ssize_t show_amb_mid(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index)));
+}
+
+static ssize_t show_amb_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_max(attr->index)));
+}
+
+static ssize_t show_amb_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp(attr->index)));
+}
+
+static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+{
+ int i, j, k, d = 0;
+ u16 c;
+ int res = 0;
+ int num_ambs = 0;
+ struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+ /* Count the number of AMBs found */
+ /* ignore the high-order bit, see "Ugly hack" comment above */
+ for (i = 0; i < MAX_MEM_CHANNELS; i++)
+ num_ambs += hweight16(data->amb_present[i] & 0x7fff);
+
+ /* Set up sysfs stuff */
+ data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB,
+ GFP_KERNEL);
+ if (!data->attrs)
+ return -ENOMEM;
+ data->num_attrs = 0;
+
+ for (i = 0; i < MAX_MEM_CHANNELS; i++) {
+ c = data->amb_present[i];
+ for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) {
+ struct i5k_device_attribute *iattr;
+
+ k = amb_num_from_reg(i, j);
+ if (!(c & 0x1))
+ continue;
+ d++;
+
+ /* Temperature sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_input", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_temp;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature min sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_min", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_min;
+ iattr->s_attr.dev_attr.store = store_amb_min;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature mid sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_mid", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_mid;
+ iattr->s_attr.dev_attr.store = store_amb_mid;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature max sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_max", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_max;
+ iattr->s_attr.dev_attr.store = store_amb_max;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature alarm sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_alarm", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_alarm;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+ }
+ }
+
+ res = device_create_file(&pdev->dev, &dev_attr_name);
+ if (res)
+ goto exit_remove;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ res = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ return res;
+
+exit_remove:
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < data->num_attrs; i++)
+ device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+ kfree(data->attrs);
+
+ return res;
+}
+
+static int __devinit i5k_amb_add(void)
+{
+ int res = -ENODEV;
+
+ /* only ever going to be one of these */
+ amb_pdev = platform_device_alloc(DRVNAME, 0);
+ if (!amb_pdev)
+ return -ENOMEM;
+
+ res = platform_device_add(amb_pdev);
+ if (res)
+ goto err;
+ return 0;
+
+err:
+ platform_device_put(amb_pdev);
+ return res;
+}
+
+static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
+{
+ struct pci_dev *pcidev;
+ u32 val32;
+ int res = -ENODEV;
+
+ /* Find AMB register memory space */
+ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5000_ERR,
+ NULL);
+ if (!pcidev)
+ return -ENODEV;
+
+ if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32))
+ goto out;
+ data->amb_base = val32;
+
+ if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32))
+ goto out;
+ data->amb_len = val32;
+
+ /* Is it big enough? */
+ if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) {
+ dev_err(&pcidev->dev, "AMB region too small!\n");
+ goto out;
+ }
+
+ res = 0;
+out:
+ pci_dev_put(pcidev);
+ return res;
+}
+
+static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+{
+ struct pci_dev *pcidev;
+ u16 val16;
+ int res = -ENODEV;
+
+ /* Copy the DIMM presence map for these two channels */
+ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL);
+ if (!pcidev)
+ return -ENODEV;
+
+ if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16))
+ goto out;
+ amb_present[0] = val16;
+
+ if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16))
+ goto out;
+ amb_present[1] = val16;
+
+ res = 0;
+
+out:
+ pci_dev_put(pcidev);
+ return res;
+}
+
+static int __devinit i5k_amb_probe(struct platform_device *pdev)
+{
+ struct i5k_amb_data *data;
+ struct resource *reso;
+ int res = -ENODEV;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* Figure out where the AMB registers live */
+ res = i5k_find_amb_registers(data);
+ if (res)
+ goto err;
+
+ /* Copy the DIMM presence map for the first two channels */
+ res = i5k_channel_probe(&data->amb_present[0],
+ PCI_DEVICE_ID_INTEL_5000_FBD0);
+ if (res)
+ goto err;
+
+ /* Copy the DIMM presence map for the optional second two channels */
+ i5k_channel_probe(&data->amb_present[2],
+ PCI_DEVICE_ID_INTEL_5000_FBD1);
+
+ /* Set up resource regions */
+ reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
+ if (!reso) {
+ res = -EBUSY;
+ goto err;
+ }
+
+ data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len);
+ if (!data->amb_mmio) {
+ res = -EBUSY;
+ goto err_map_failed;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ res = i5k_amb_hwmon_init(pdev);
+ if (res)
+ goto err_init_failed;
+
+ return res;
+
+err_init_failed:
+ iounmap(data->amb_mmio);
+ platform_set_drvdata(pdev, NULL);
+err_map_failed:
+ release_mem_region(data->amb_base, data->amb_len);
+err:
+ kfree(data);
+ return res;
+}
+
+static int __devexit i5k_amb_remove(struct platform_device *pdev)
+{
+ int i;
+ struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < data->num_attrs; i++)
+ device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+ kfree(data->attrs);
+ iounmap(data->amb_mmio);
+ release_mem_region(data->amb_base, data->amb_len);
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+ return 0;
+}
+
+static struct platform_driver i5k_amb_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = i5k_amb_probe,
+ .remove = __devexit_p(i5k_amb_remove),
+};
+
+static int __init i5k_amb_init(void)
+{
+ int res;
+
+ res = platform_driver_register(&i5k_amb_driver);
+ if (res)
+ return res;
+
+ res = i5k_amb_add();
+ if (res)
+ platform_driver_unregister(&i5k_amb_driver);
+
+ return res;
+}
+
+static void __exit i5k_amb_exit(void)
+{
+ platform_device_unregister(amb_pdev);
+ platform_driver_unregister(&i5k_amb_driver);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor");
+MODULE_LICENSE("GPL");
+
+module_init(i5k_amb_init);
+module_exit(i5k_amb_exit);
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index c462824ffcc..9c9cdb0685e 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -140,10 +140,10 @@ static int ibmpex_send_message(struct ibmpex_bmc_data *data)
return 0;
out1:
- printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err);
+ dev_err(data->bmc_device, "request_settime=%x\n", err);
return err;
out:
- printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err);
+ dev_err(data->bmc_device, "validate_addr=%x\n", err);
return err;
}
@@ -161,14 +161,14 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data)
data->sensor_major = data->rx_msg_data[0];
data->sensor_minor = data->rx_msg_data[1];
- printk(KERN_INFO DRVNAME ": Found BMC with sensor interface "
- "v%d.%d %d-%02d-%02d on interface %d\n",
- data->sensor_major,
- data->sensor_minor,
- extract_value(data->rx_msg_data, 2),
- data->rx_msg_data[4],
- data->rx_msg_data[5],
- data->interface);
+ dev_info(data->bmc_device, "Found BMC with sensor interface "
+ "v%d.%d %d-%02d-%02d on interface %d\n",
+ data->sensor_major,
+ data->sensor_minor,
+ extract_value(data->rx_msg_data, 2),
+ data->rx_msg_data[4],
+ data->rx_msg_data[5],
+ data->interface);
return 0;
}
@@ -212,8 +212,8 @@ static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor)
wait_for_completion(&data->read_complete);
if (data->rx_result || data->rx_msg_len < 26) {
- printk(KERN_ERR "Error reading sensor %d, please check.\n",
- sensor);
+ dev_err(data->bmc_device, "Error reading sensor %d.\n",
+ sensor);
return -ENOENT;
}
@@ -456,8 +456,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
- printk(KERN_ERR DRVNAME ": Insufficient memory for BMC "
- "interface %d.\n", data->interface);
+ dev_err(dev, "Insufficient memory for BMC interface.\n");
return;
}
@@ -471,9 +470,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
data, &data->user);
if (err < 0) {
- printk(KERN_ERR DRVNAME ": Error, unable to register user with "
- "ipmi interface %d\n",
- data->interface);
+ dev_err(dev, "Unable to register user with IPMI "
+ "interface %d\n", data->interface);
goto out;
}
@@ -495,9 +493,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
data->hwmon_dev = hwmon_device_register(data->bmc_device);
if (IS_ERR(data->hwmon_dev)) {
- printk(KERN_ERR DRVNAME ": Error, unable to register hwmon "
- "class device for interface %d\n",
- data->interface);
+ dev_err(data->bmc_device, "Unable to register hwmon "
+ "device for IPMI interface %d\n",
+ data->interface);
goto out_user;
}
@@ -508,7 +506,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
/* Now go find all the sensors */
err = ibmpex_find_sensors(data);
if (err) {
- printk(KERN_ERR "Error %d allocating memory\n", err);
+ dev_err(data->bmc_device, "Error %d finding sensors\n", err);
goto out_register;
}
@@ -561,10 +559,10 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
if (msg->msgid != data->tx_msgid) {
- printk(KERN_ERR "Received msgid (%02x) and transmitted "
- "msgid (%02x) mismatch!\n",
- (int)msg->msgid,
- (int)data->tx_msgid);
+ dev_err(data->bmc_device, "Mismatch between received msgid "
+ "(%02x) and transmitted msgid (%02x)!\n",
+ (int)msg->msgid,
+ (int)data->tx_msgid);
ipmi_free_recv_msg(msg);
return;
}
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index dd366889ce9..d435f003292 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -31,14 +31,15 @@
#include <linux/err.h>
#include <linux/sysfs.h>
#include <linux/hwmon.h>
+#include <linux/mutex.h>
#include <linux/spi/spi.h>
-#include <asm/semaphore.h>
+
#define DRVNAME "lm70"
struct lm70 {
struct device *hwmon_dev;
- struct semaphore sem;
+ struct mutex lock;
};
/* sysfs hook function */
@@ -51,7 +52,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
s16 raw=0;
struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
- if (down_interruptible(&p_lm70->sem))
+ if (mutex_lock_interruptible(&p_lm70->lock))
return -ERESTARTSYS;
/*
@@ -83,7 +84,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
val = ((int)raw/32) * 250;
status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
out:
- up(&p_lm70->sem);
+ mutex_unlock(&p_lm70->lock);
return status;
}
@@ -112,7 +113,7 @@ static int __devinit lm70_probe(struct spi_device *spi)
if (!p_lm70)
return -ENOMEM;
- init_MUTEX(&p_lm70->sem);
+ mutex_init(&p_lm70->lock);
/* sysfs hook */
p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 7e2d9787bab..a276806f3d5 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -435,6 +435,22 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ int nr = to_sensor_dev_attr(da)->index;
+ return sprintf(buf, "%u\n", (data->alarms >> nr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15);
+
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -447,22 +463,28 @@ static struct attribute *sis5595_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
+ &sensor_dev_attr_in0_alarm.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in2_min.dev_attr.attr,
&sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in3_min.dev_attr.attr,
&sensor_dev_attr_in3_max.dev_attr.attr,
+ &sensor_dev_attr_in3_alarm.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_min.dev_attr.attr,
&sensor_dev_attr_fan1_div.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
&sensor_dev_attr_fan2_min.dev_attr.attr,
&sensor_dev_attr_fan2_div.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
&dev_attr_alarms.attr,
&dev_attr_name.attr,
@@ -473,19 +495,28 @@ static const struct attribute_group sis5595_group = {
.attrs = sis5595_attributes,
};
-static struct attribute *sis5595_attributes_opt[] = {
+static struct attribute *sis5595_attributes_in4[] = {
&sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in4_max.dev_attr.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group sis5595_group_in4 = {
+ .attrs = sis5595_attributes_in4,
+};
+static struct attribute *sis5595_attributes_temp1[] = {
&dev_attr_temp1_input.attr,
&dev_attr_temp1_max.attr,
&dev_attr_temp1_max_hyst.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
NULL
};
-static const struct attribute_group sis5595_group_opt = {
- .attrs = sis5595_attributes_opt,
+static const struct attribute_group sis5595_group_temp1 = {
+ .attrs = sis5595_attributes_temp1,
};
/* This is called when the module is loaded */
@@ -540,20 +571,12 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
goto exit_free;
if (data->maxins == 4) {
- if ((err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_input.dev_attr))
- || (err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_min.dev_attr))
- || (err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_max.dev_attr)))
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &sis5595_group_in4)))
goto exit_remove_files;
} else {
- if ((err = device_create_file(&pdev->dev,
- &dev_attr_temp1_input))
- || (err = device_create_file(&pdev->dev,
- &dev_attr_temp1_max))
- || (err = device_create_file(&pdev->dev,
- &dev_attr_temp1_max_hyst)))
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &sis5595_group_temp1)))
goto exit_remove_files;
}
@@ -567,7 +590,8 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
exit_remove_files:
sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
- sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
exit_free:
kfree(data);
exit_release:
@@ -582,7 +606,8 @@ static int __devexit sis5595_remove(struct platform_device *pdev)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
- sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
release_region(data->addr, SIS5595_EXTENT);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 20ae425a198..879d0a6544c 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -170,20 +170,16 @@ superio_exit(void)
#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
(0x550 + (nr) - 7))
-#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
-#define W83781D_REG_FAN(nr) (0x27 + (nr))
-
-#define W83781D_REG_TEMP2_CONFIG 0x152
-#define W83781D_REG_TEMP3_CONFIG 0x252
-#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
- ((nr == 2) ? (0x0150) : \
- (0x27)))
-#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
- ((nr == 2) ? (0x153) : \
- (0x3A)))
-#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
- ((nr == 2) ? (0x155) : \
- (0x39)))
+/* nr:0-2 for fans:1-3 */
+#define W83627HF_REG_FAN_MIN(nr) (0x3b + (nr))
+#define W83627HF_REG_FAN(nr) (0x28 + (nr))
+
+#define W83627HF_REG_TEMP2_CONFIG 0x152
+#define W83627HF_REG_TEMP3_CONFIG 0x252
+/* these are zero-based, unlike config constants above */
+static const u16 w83627hf_reg_temp[] = { 0x27, 0x150, 0x250 };
+static const u16 w83627hf_reg_temp_hyst[] = { 0x3A, 0x153, 0x253 };
+static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 };
#define W83781D_REG_BANK 0x4E
@@ -360,12 +356,9 @@ struct w83627hf_data {
u8 in_min[9]; /* Register value */
u8 fan[3]; /* Register value */
u8 fan_min[3]; /* Register value */
- u8 temp;
- u8 temp_max; /* Register value */
- u8 temp_max_hyst; /* Register value */
- u16 temp_add[2]; /* Register value */
- u16 temp_max_add[2]; /* Register value */
- u16 temp_max_hyst_add[2]; /* Register value */
+ u16 temp[3]; /* Register value */
+ u16 temp_max[3]; /* Register value */
+ u16 temp_max_hyst[3]; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
@@ -590,7 +583,7 @@ store_fan_min(struct device *dev, struct device_attribute *devattr,
mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1),
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
data->fan_min[nr]);
mutex_unlock(&data->update_lock);
@@ -611,12 +604,10 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp));
- }
+
+ u16 tmp = data->temp[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -625,13 +616,10 @@ show_temp_max(struct device *dev, struct device_attribute *devattr,
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n",
- (long)TEMP_FROM_REG(data->temp_max));
- }
+
+ u16 tmp = data->temp_max[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -640,13 +628,10 @@ show_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n",
- (long)TEMP_FROM_REG(data->temp_max_hyst));
- }
+
+ u16 tmp = data->temp_max_hyst[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -656,18 +641,11 @@ store_temp_max(struct device *dev, struct device_attribute *devattr,
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10);
+ u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
- data->temp_max_add[nr-2]);
- } else { /* TEMP1 */
- data->temp_max = TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
- data->temp_max);
- }
+ data->temp_max[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
@@ -679,29 +657,22 @@ store_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10);
+ u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
- data->temp_max_hyst_add[nr-2]);
- } else { /* TEMP1 */
- data->temp_max_hyst = TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
- data->temp_max_hyst);
- }
+ data->temp_max_hyst[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
#define sysfs_temp_decl(offset) \
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp, NULL, offset); \
+ show_temp, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \
- show_temp_max, store_temp_max, offset); \
+ show_temp_max, store_temp_max, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \
- show_temp_max_hyst, store_temp_max_hyst, offset);
+ show_temp_max_hyst, store_temp_max_hyst, offset - 1);
sysfs_temp_decl(1);
sysfs_temp_decl(2);
@@ -844,7 +815,7 @@ store_fan_div(struct device *dev, struct device_attribute *devattr,
/* Restore fan_min */
data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -1170,7 +1141,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
struct w83627hf_sio_data *sio_data = dev->platform_data;
struct w83627hf_data *data;
struct resource *res;
- int err;
+ int err, i;
static const char *names[] = {
"w83627hf",
@@ -1204,9 +1175,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
w83627hf_init_device(pdev);
/* A few vars need to be filled upon startup */
- data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
- data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
- data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
+ for (i = 0; i <= 2; i++)
+ data->fan_min[i] = w83627hf_read_value(
+ data, W83627HF_REG_FAN_MIN(i));
w83627hf_update_fan_div(data);
/* Register common device attributes */
@@ -1514,23 +1485,23 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev)
if(init) {
/* Enable temp2 */
- tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG);
+ tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
if (tmp & 0x01) {
dev_warn(&pdev->dev, "Enabling temp2, readings "
"might not make sense\n");
- w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG,
+ w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
tmp & 0xfe);
}
/* Enable temp3 */
if (type != w83697hf) {
tmp = w83627hf_read_value(data,
- W83781D_REG_TEMP3_CONFIG);
+ W83627HF_REG_TEMP3_CONFIG);
if (tmp & 0x01) {
dev_warn(&pdev->dev, "Enabling temp3, "
"readings might not make sense\n");
w83627hf_write_value(data,
- W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+ W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
}
}
}
@@ -1563,7 +1534,7 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data)
static struct w83627hf_data *w83627hf_update_device(struct device *dev)
{
struct w83627hf_data *data = dev_get_drvdata(dev);
- int i;
+ int i, num_temps = (data->type == w83697hf) ? 2 : 3;
mutex_lock(&data->update_lock);
@@ -1584,12 +1555,12 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
w83627hf_read_value(data,
W83781D_REG_IN_MAX(i));
}
- for (i = 1; i <= 3; i++) {
- data->fan[i - 1] =
- w83627hf_read_value(data, W83781D_REG_FAN(i));
- data->fan_min[i - 1] =
+ for (i = 0; i <= 2; i++) {
+ data->fan[i] =
+ w83627hf_read_value(data, W83627HF_REG_FAN(i));
+ data->fan_min[i] =
w83627hf_read_value(data,
- W83781D_REG_FAN_MIN(i));
+ W83627HF_REG_FAN_MIN(i));
}
for (i = 0; i <= 2; i++) {
u8 tmp = w83627hf_read_value(data,
@@ -1616,25 +1587,13 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
break;
}
}
-
- data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
- data->temp_max =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1));
- data->temp_max_hyst =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1));
- data->temp_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP(2));
- data->temp_max_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2));
- data->temp_max_hyst_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2));
- if (data->type != w83697hf) {
- data->temp_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP(3));
- data->temp_max_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3));
- data->temp_max_hyst_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
+ for (i = 0; i < num_temps; i++) {
+ data->temp[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp[i]);
+ data->temp_max[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_over[i]);
+ data->temp_max_hyst[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_hyst[i]);
}
w83627hf_update_fan_div(data);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index a6a1edfe761..e0fa7520400 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1122,12 +1122,13 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
&sensor_dev_attr_temp3_beep.dev_attr)))
return err;
- if (kind != w83781d)
+ if (kind != w83781d) {
err = sysfs_chmod_file(&dev->kobj,
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
S_IRUGO | S_IWUSR);
if (err)
return err;
+ }
}
if (kind != w83781d && kind != as99127f) {
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 58e32714afb..ca18e0be490 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -51,6 +51,7 @@ struct pasemi_smbus {
#define MRXFIFO_DATA_M 0x000000ff
#define SMSTA_XEN 0x08000000
+#define SMSTA_MTN 0x00200000
#define CTL_MRR 0x00000400
#define CTL_MTR 0x00000200
@@ -98,6 +99,10 @@ static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
status = reg_read(smbus, REG_SMSTA);
}
+ /* Got NACK? */
+ if (status & SMSTA_MTN)
+ return -ENXIO;
+
if (timeout < 0) {
dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status);
reg_write(smbus, REG_SMSTA, status);
@@ -364,7 +369,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
- /* set up the driverfs linkage to our parent device */
+ /* set up the sysfs linkage to our parent device */
smbus->adapter.dev.parent = &dev->dev;
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index d3da1fb05b9..1a7eeebac50 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -128,13 +128,20 @@ static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
eeprom_update_client(client, slice);
- /* Hide Vaio security settings to regular users (16 first bytes) */
- if (data->nature == VAIO && off < 16 && !capable(CAP_SYS_ADMIN)) {
- size_t in_row1 = 16 - off;
- in_row1 = min(in_row1, count);
- memset(buf, 0, in_row1);
- if (count - in_row1 > 0)
- memcpy(buf + in_row1, &data->data[16], count - in_row1);
+ /* Hide Vaio private settings to regular users:
+ - BIOS passwords: bytes 0x00 to 0x0f
+ - UUID: bytes 0x10 to 0x1f
+ - Serial number: 0xc0 to 0xdf */
+ if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if ((off + i <= 0x1f) ||
+ (off + i >= 0xc0 && off + i <= 0xdf))
+ buf[i] = 0;
+ else
+ buf[i] = data->data[off + i];
+ }
} else {
memcpy(buf, &data->data[off], count);
}
@@ -197,14 +204,18 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_kfree;
/* Detect the Vaio nature of EEPROMs.
- We use the "PCG-" prefix as the signature. */
+ We use the "PCG-" or "VGN-" prefix as the signature. */
if (address == 0x57) {
- if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
- && i2c_smbus_read_byte(new_client) == 'C'
- && i2c_smbus_read_byte(new_client) == 'G'
- && i2c_smbus_read_byte(new_client) == '-') {
+ char name[4];
+
+ name[0] = i2c_smbus_read_byte_data(new_client, 0x80);
+ name[1] = i2c_smbus_read_byte(new_client);
+ name[2] = i2c_smbus_read_byte(new_client);
+ name[3] = i2c_smbus_read_byte(new_client);
+
+ if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
dev_info(&new_client->dev, "Vaio EEPROM detected, "
- "enabling password protection\n");
+ "enabling privacy protection\n");
data->nature = VAIO;
}
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 1a4e8dc03b3..b5e13e405e7 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -673,7 +673,7 @@ static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
return 0;
}
-int i2c_check_addr(struct i2c_adapter *adapter, int addr)
+static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
{
int rval;
@@ -683,7 +683,6 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
return rval;
}
-EXPORT_SYMBOL(i2c_check_addr);
int i2c_attach_client(struct i2c_client *client)
{
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 5a15e50748d..c21ae20ae36 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -38,6 +38,15 @@
static struct i2c_driver i2cdev_driver;
+/*
+ * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
+ * slave (i2c_client) with which messages will be exchanged. It's coupled
+ * with a character special file which is accessed by user mode drivers.
+ *
+ * The list of i2c_dev structures is parallel to the i2c_adapter lists
+ * maintained by the driver model, and is updated using notifications
+ * delivered to the i2cdev_driver.
+ */
struct i2c_dev {
struct list_head list;
struct i2c_adapter *adap;
@@ -103,6 +112,25 @@ static ssize_t show_adapter_name(struct device *dev,
}
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
+/* ------------------------------------------------------------------------- */
+
+/*
+ * After opening an instance of this character special file, a file
+ * descriptor starts out associated only with an i2c_adapter (and bus).
+ *
+ * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg
+ * traffic to any devices on the bus used by that adapter. That's because
+ * the i2c_msg vectors embed all the addressing information they need, and
+ * are submitted directly to an i2c_adapter. However, SMBus-only adapters
+ * don't support that interface.
+ *
+ * To use read()/write() system calls on that file descriptor, or to use
+ * SMBus interfaces (and work with SMBus-only hosts!), you must first issue
+ * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous
+ * (never registered) i2c_client so it holds the addressing information
+ * needed by those system calls and by this SMBus interface.
+ */
+
static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
@@ -154,6 +182,29 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
return ret;
}
+/* This address checking function differs from the one in i2c-core
+ in that it considers an address with a registered device, but no
+ bounded driver, as NOT busy. */
+static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+{
+ struct list_head *item;
+ struct i2c_client *client;
+ int res = 0;
+
+ mutex_lock(&adapter->clist_lock);
+ list_for_each(item, &adapter->clients) {
+ client = list_entry(item, struct i2c_client, list);
+ if (client->addr == addr) {
+ if (client->driver)
+ res = -EBUSY;
+ break;
+ }
+ }
+ mutex_unlock(&adapter->clist_lock);
+
+ return res;
+}
+
static int i2cdev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -172,11 +223,22 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
switch ( cmd ) {
case I2C_SLAVE:
case I2C_SLAVE_FORCE:
+ /* NOTE: devices set up to work with "new style" drivers
+ * can't use I2C_SLAVE, even when the device node is not
+ * bound to a driver. Only I2C_SLAVE_FORCE will work.
+ *
+ * Setting the PEC flag here won't affect kernel drivers,
+ * which will be using the i2c_client node registered with
+ * the driver model core. Likewise, when that client has
+ * the PEC flag already set, the i2c-dev driver won't see
+ * (or use) this setting.
+ */
if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
- if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
+ if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
return -EBUSY;
+ /* REVISIT: address could become busy later */
client->addr = arg;
return 0;
case I2C_TENBIT:
@@ -386,6 +448,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
if (!adap)
return -ENODEV;
+ /* This creates an anonymous i2c_client, which may later be
+ * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
+ *
+ * This client is ** NEVER REGISTERED ** with the driver model
+ * or I2C core code!! It just holds private copies of addressing
+ * information and maybe a PEC flag.
+ */
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client) {
i2c_put_adapter(adap);
@@ -394,7 +463,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
client->driver = &i2cdev_driver;
- /* registered with adapter, passed as client to user */
client->adapter = adap;
file->private_data = client;
@@ -422,6 +490,14 @@ static const struct file_operations i2cdev_fops = {
.release = i2cdev_release,
};
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The legacy "i2cdev_driver" is used primarily to get notifications when
+ * I2C adapters are added or removed, so that each one gets an i2c_dev
+ * and is thus made available to userspace driver code.
+ */
+
static struct class *i2c_dev_class;
static int i2cdev_attach_adapter(struct i2c_adapter *adap)
@@ -486,6 +562,12 @@ static struct i2c_driver i2cdev_driver = {
.detach_client = i2cdev_detach_client,
};
+/* ------------------------------------------------------------------------- */
+
+/*
+ * module load/unload record keeping
+ */
+
static int __init i2c_dev_init(void)
{
int res;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index d1e8df18722..45b22282f14 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -203,10 +203,6 @@ config BLK_DEV_IDECD
CD-ROM drive, you can say N to all other CD-ROM options, but be sure
to say Y or M to "ISO 9660 CD-ROM file system support".
- Note that older versions of LILO (LInux LOader) cannot properly deal
- with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
- <http://lilo.go.dyndns.org/>.
-
To compile this driver as a module, choose M here: the
module will be called ide-cd.
@@ -317,7 +313,6 @@ comment "IDE chipset support/bugfixes"
config IDE_GENERIC
tristate "generic/default IDE chipset support"
- default H8300
help
If unsure, say N.
@@ -488,6 +483,7 @@ config WDC_ALI15X3
config BLK_DEV_AMD74XX
tristate "AMD and nVidia IDE support"
+ depends on !ARM
select BLK_DEV_IDEDMA_PCI
help
This driver adds explicit support for AMD-7xx and AMD-8111 chips
@@ -887,6 +883,49 @@ config BLK_DEV_IDE_BAST
Say Y here if you want to support the onboard IDE channels on the
Simtec BAST or the Thorcom VR1000
+config ETRAX_IDE
+ bool "ETRAX IDE support"
+ depends on CRIS && BROKEN
+ select BLK_DEV_IDEDMA
+ select IDE_GENERIC
+ help
+ Enables the ETRAX IDE driver.
+
+ You can't use parallel ports or SCSI ports at the same time.
+
+config ETRAX_IDE_DELAY
+ int "Delay for drives to regain consciousness"
+ depends on ETRAX_IDE && ETRAX_ARCH_V10
+ default 15
+ help
+ Number of seconds to wait for IDE drives to spin up after an IDE
+ reset.
+
+choice
+ prompt "IDE reset pin"
+ depends on ETRAX_IDE && ETRAX_ARCH_V10
+ default ETRAX_IDE_PB7_RESET
+
+config ETRAX_IDE_PB7_RESET
+ bool "Port_PB_Bit_7"
+ help
+ IDE reset on pin 7 on port B
+
+config ETRAX_IDE_G27_RESET
+ bool "Port_G_Bit_27"
+ help
+ IDE reset on pin 27 on port G
+
+endchoice
+
+config IDE_H8300
+ bool "H8300 IDE support"
+ depends on H8300
+ select IDE_GENERIC
+ default y
+ help
+ Enables the H8300 IDE driver.
+
config BLK_DEV_GAYLE
bool "Amiga Gayle IDE interface support"
depends on AMIGA
@@ -967,7 +1006,7 @@ config BLK_DEV_Q40IDE
config BLK_DEV_MPC8xx_IDE
bool "MPC8xx IDE support"
- depends on 8xx && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
+ depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
select IDE_GENERIC
help
This option provides support for IDE on Motorola MPC8xx Systems.
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 75dc6969e0a..b181fc67205 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -39,7 +39,7 @@ ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o
ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o
# built-in only drivers from h8300/
-ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o
+ide-core-$(CONFIG_IDE_H8300) += h8300/ide-h8300.o
obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index e196aefa207..476e0d65ed4 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -748,8 +748,7 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
hold = ATA_DMA2_HOLD;
break;
default:
- BUG();
- break;
+ return;
}
if (speed >= XFER_UDMA_0)
@@ -774,15 +773,16 @@ init_e100_ide (void)
/* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0);
- /* first fill in some stuff in the ide_hwifs fields */
+ for (h = 0; h < 4; h++) {
+ ide_hwif_t *hwif = NULL;
- for(h = 0; h < MAX_HWIFS; h++) {
- ide_hwif_t *hwif = &ide_hwifs[h];
ide_setup_ports(&hw, cris_ide_base_address(h),
ide_offsets,
0, 0, cris_ide_ack_intr,
ide_default_irq(0));
ide_register_hw(&hw, NULL, 1, &hwif);
+ if (hwif == NULL)
+ continue;
hwif->mmio = 1;
hwif->chipset = ide_etrax100;
hwif->set_pio_mode = &cris_set_pio_mode;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index e3add70b9cd..0d795a1678c 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -130,6 +130,7 @@ static const struct drive_list_entry drive_blacklist [] = {
{ "_NEC DV5800A", NULL },
{ "SAMSUNG CD-ROM SN-124", "N001" },
{ "Seagate STT20000A", NULL },
+ { "CD-ROM CDR_U200", "1.09" },
{ NULL , NULL }
};
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 755011827af..db22d1ff4e5 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -885,7 +885,6 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return do_rw_taskfile(drive, args);
} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
u8 *args = rq->buffer;
- u8 sel;
if (!args)
goto done;
@@ -903,10 +902,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
hwif->OUTB(args[3], IDE_SECTOR_REG);
hwif->OUTB(args[4], IDE_LCYL_REG);
hwif->OUTB(args[5], IDE_HCYL_REG);
- sel = (args[6] & ~0x10);
- if (drive->select.b.unit)
- sel |= 0x10;
- hwif->OUTB(sel, IDE_SELECT_REG);
+ hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
return ide_started;
} else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index e17a9ee120e..5c3256180ae 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -303,9 +303,6 @@ void default_hwif_transport(ide_hwif_t *hwif)
hwif->atapi_output_bytes = atapi_output_bytes;
}
-/*
- * Beginning of Taskfile OPCODE Library and feature sets.
- */
void ide_fix_driveid (struct hd_driveid *id)
{
#ifndef __LITTLE_ENDIAN
@@ -592,6 +589,9 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list);
static const struct drive_list_entry ivb_list[] = {
{ "QUANTUM FIREBALLlct10 05" , "A03.0900" },
{ "TSSTcorp CDDVDW SH-S202J" , "SB00" },
+ { "TSSTcorp CDDVDW SH-S202J" , "SB01" },
+ { "TSSTcorp CDDVDW SH-S202N" , "SB00" },
+ { "TSSTcorp CDDVDW SH-S202N" , "SB01" },
{ NULL , NULL }
};
@@ -756,7 +756,7 @@ int ide_driveid_update(ide_drive_t *drive)
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
- int error;
+ int error = 0;
u8 stat;
// while (HWGROUP(drive)->busy)
@@ -767,6 +767,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
hwif->dma_host_off(drive);
#endif
+ /* Skip setting PIO flow-control modes on pre-EIDE drives */
+ if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08))
+ goto skip;
+
/*
* Don't use ide_wait_cmd here - it will
* attempt to set_geometry and recalibrate,
@@ -814,6 +818,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
+ skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
if (speed >= XFER_SW_DMA_0)
hwif->dma_host_on(drive);
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index af86433baed..1609b8604f5 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -514,6 +514,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
if (drive->addressing == 1) {
__u64 sectors = 0;
u32 low = 0, high = 0;
+ hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
low = ide_read_24(drive);
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
high = ide_read_24(drive);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 56fb0b84342..ee848c70599 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -644,7 +644,7 @@ static void hwif_register (ide_hwif_t *hwif)
static int wait_hwif_ready(ide_hwif_t *hwif)
{
- int rc;
+ int unit, rc;
printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name);
@@ -661,20 +661,26 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
return rc;
/* Now make sure both master & slave are ready */
- SELECT_DRIVE(&hwif->drives[0]);
- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
- mdelay(2);
- rc = ide_wait_not_busy(hwif, 35000);
- if (rc)
- return rc;
- SELECT_DRIVE(&hwif->drives[1]);
- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
- mdelay(2);
- rc = ide_wait_not_busy(hwif, 35000);
+ for (unit = 0; unit < MAX_DRIVES; unit++) {
+ ide_drive_t *drive = &hwif->drives[unit];
+ /* Ignore disks that we will not probe for later. */
+ if (!drive->noprobe || drive->present) {
+ SELECT_DRIVE(drive);
+ hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ mdelay(2);
+ rc = ide_wait_not_busy(hwif, 35000);
+ if (rc)
+ goto out;
+ } else
+ printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n",
+ drive->name);
+ }
+out:
/* Exit function with master reselected (let's be sane) */
- SELECT_DRIVE(&hwif->drives[0]);
-
+ if (unit)
+ SELECT_DRIVE(&hwif->drives[0]);
+
return rc;
}
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
index 10311ecc674..38c3a6d63f3 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/legacy/ali14xx.c
@@ -53,12 +53,13 @@
/* port addresses for auto-detection */
#define ALI_NUM_PORTS 4
-static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
+static const int ports[ALI_NUM_PORTS] __initdata =
+ { 0x074, 0x0f4, 0x034, 0x0e4 };
/* register initialization data */
typedef struct { u8 reg, data; } RegInitializer;
-static RegInitializer initData[] __initdata = {
+static const RegInitializer initData[] __initdata = {
{0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
{0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
@@ -177,7 +178,7 @@ static int __init findPort (void)
* Initialize controller registers with default values.
*/
static int __init initRegisters (void) {
- RegInitializer *p;
+ const RegInitializer *p;
u8 t;
unsigned long flags;
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index e87cd2f1643..5c6aa77c237 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -81,7 +81,7 @@ int macide_ack_intr(ide_hwif_t* hwif)
* Probe for a Macintosh IDE interface
*/
-void macide_init(void)
+void __init macide_init(void)
{
hw_regs_t hw;
ide_hwif_t *hwif;
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index a73db1bd482..6ea46a6723e 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -111,7 +111,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
* Probe for Q40 IDE interfaces
*/
-void q40ide_init(void)
+void __init q40ide_init(void)
{
int i;
ide_hwif_t *hwif;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 19ec421f7b9..44268504ae4 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -260,6 +260,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
{
struct ide_port_info d;
u8 idx = id->driver_data;
+ int err;
+
+ err = pci_enable_device(dev);
+ if (err)
+ return err;
d = aec62xx_chipsets[idx];
@@ -272,7 +277,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
}
}
- return ide_setup_pci_device(dev, &d);
+ err = ide_setup_pci_device(dev, &d);
+ if (err)
+ pci_disable_device(dev);
+
+ return err;
}
static const struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index a607dd31a64..ce293936af4 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -603,6 +603,11 @@ static int ali_cable_override(struct pci_dev *pdev)
pdev->subsystem_device == 0x10AF)
return 1;
+ /* Mitac 8317 (Winbook-A) and relatives */
+ if (pdev->subsystem_vendor == 0x1071 &&
+ pdev->subsystem_device == 0x8317)
+ return 1;
+
/* Systems by DMI */
if (dmi_check_system(cable_dmi_table))
return 1;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index ea0143ef5fe..51fca441c29 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.51 Nov 8, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
@@ -339,7 +339,8 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
u8 mrdmode = inb(hwif->dma_master + 0x01);
/* clear the interrupt bit */
- outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
+ outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
+ hwif->dma_master + 0x01);
return err;
}
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 599408952bd..547690395ee 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -117,8 +117,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
default:
- BUG();
- break;
+ return;
}
basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 5c997543531..99b7d763b6c 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -653,8 +653,7 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
- return 0;
+ return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
}
static const struct pci_device_id it821x_pci_tbl[] = {
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index bdf64d99770..0083eaf89c7 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -139,8 +139,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = {
static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &jmicron_chipset);
- return 0;
+ return ide_setup_pci_device(dev, &jmicron_chipset);
}
/* All JMB PATA controllers have and will continue to have the same
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 63625a0be71..27781d294ce 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -306,6 +306,7 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
+ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
/* end marker */
{ 0, }
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 0a7b3202066..707d5ff66b0 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -186,8 +186,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
}
break;
default:
- BUG();
- break;
+ return;
}
if (unit == 0) { /* are we configuring drive0? */
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 6d99441c605..5709c252543 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007
+ * linux/drivers/ide/pci/siimage.c Version 1.19 Nov 16 2007
*
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
@@ -460,48 +460,6 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
}
/**
- * siimage_reset - reset a device on an siimage controller
- * @drive: drive to reset
- *
- * Perform a controller level reset fo the device. For
- * SATA we must also check the PHY.
- */
-
-static void siimage_reset (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 reset = 0;
- unsigned long addr = siimage_selreg(hwif, 0);
-
- if (hwif->mmio) {
- reset = hwif->INB(addr);
- hwif->OUTB((reset|0x03), addr);
- /* FIXME:posting */
- udelay(25);
- hwif->OUTB(reset, addr);
- (void) hwif->INB(addr);
- } else {
- pci_read_config_byte(hwif->pci_dev, addr, &reset);
- pci_write_config_byte(hwif->pci_dev, addr, reset|0x03);
- udelay(25);
- pci_write_config_byte(hwif->pci_dev, addr, reset);
- pci_read_config_byte(hwif->pci_dev, addr, &reset);
- }
-
- if (SATA_STATUS_REG) {
- /* SATA_STATUS_REG is valid only when in MMIO mode */
- u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG);
- printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n",
- hwif->name, sata_stat, __FUNCTION__);
- if (!(sata_stat)) {
- printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
- hwif->name, sata_stat);
- drive->failures++;
- }
- }
-}
-
-/**
* proc_reports_siimage - add siimage controller to proc
* @dev: PCI device
* @clocking: SCSC value
@@ -857,7 +815,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
{
u8 sata = is_sata(hwif);
- hwif->resetproc = &siimage_reset;
hwif->set_pio_mode = &sil_set_pio_mode;
hwif->set_dma_mode = &sil_set_dma_mode;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 6b7bb53acef..d90b4291777 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -356,7 +356,6 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
sis_program_timings(drive, speed);
break;
default:
- BUG();
break;
}
}
@@ -527,6 +526,7 @@ static const struct sis_laptop sis_laptop[] = {
/* devid, subvendor, subdev */
{ 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
{ 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */
+ { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */
/* end marker */
{ 0, }
};
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 5011ba22e36..0895e753a35 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -240,9 +240,6 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive)
return (status == 0x00ff);
}
-/*
- * Invoked from ide-dma.c at boot time.
- */
static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
{
unsigned int cfgbase = 0;
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 816b5311dad..7f7a5988577 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1138,6 +1138,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->drives[0].autotune = IDE_TUNE_AUTO;
hwif->drives[1].autotune = IDE_TUNE_AUTO;
hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+ IDE_HFLAG_PIO_NO_DOWNGRADE |
IDE_HFLAG_POST_SET_MODE;
hwif->pio_mask = ATA_PIO4;
hwif->set_pio_mode = pmac_ide_set_pio_mode;
@@ -1512,7 +1513,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) {
if (pmif->broken_dma_warn == 0) {
- printk(KERN_WARNING "%s: DMA on non aligned address,"
+ printk(KERN_WARNING "%s: DMA on non aligned address, "
"switching to PIO on Ohare chipset\n", drive->name);
pmif->broken_dma_warn = 1;
}
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 02d14bf85ab..25fd0905322 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -7,11 +7,6 @@
* May be copied or modified under the terms of the GNU General Public License
*/
-/*
- * This module provides support for automatic detection and
- * configuration of all PCI IDE interfaces present in a system.
- */
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c77758937..b5436ca92e6 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1000,6 +1000,7 @@ static int iwch_query_device(struct ib_device *ibdev,
props->max_sge = dev->attr.max_sge_per_wr;
props->max_sge_rd = 1;
props->max_qp_rd_atom = dev->attr.max_rdma_reads_per_qp;
+ props->max_qp_init_rd_atom = dev->attr.max_rdma_reads_per_qp;
props->max_cq = dev->attr.max_cqs;
props->max_cqe = dev->attr.max_cqes_per_cq;
props->max_mr = dev->attr.max_mem_regs;
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
index 97d108634c5..f7782c882ab 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -50,6 +50,42 @@
static struct kmem_cache *av_cache;
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd)
+{
+ int path = ib_rate_to_mult(path_rate);
+ int link, ret;
+ struct ib_port_attr pa;
+
+ if (path_rate == IB_RATE_PORT_CURRENT) {
+ *ipd = 0;
+ return 0;
+ }
+
+ if (unlikely(path < 0)) {
+ ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x",
+ path_rate);
+ return -EINVAL;
+ }
+
+ ret = ehca_query_port(&shca->ib_device, port, &pa);
+ if (unlikely(ret < 0)) {
+ ehca_err(&shca->ib_device, "Failed to query port ret=%i", ret);
+ return ret;
+ }
+
+ link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
+
+ if (path >= link)
+ /* no need to throttle if path faster than link */
+ *ipd = 0;
+ else
+ /* IPD = round((link / path) - 1) */
+ *ipd = ((link + (path >> 1)) / path) - 1;
+
+ return 0;
+}
+
struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
{
int ret;
@@ -69,15 +105,13 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
av->av.slid_path_bits = ah_attr->src_path_bits;
if (ehca_static_rate < 0) {
- int ah_mult = ib_rate_to_mult(ah_attr->static_rate);
- int ehca_mult =
- ib_rate_to_mult(shca->sport[ah_attr->port_num].rate );
-
- if (ah_mult >= ehca_mult)
- av->av.ipd = 0;
- else
- av->av.ipd = (ah_mult > 0) ?
- ((ehca_mult - 1) / ah_mult) : 0;
+ u32 ipd;
+ if (ehca_calc_ipd(shca, ah_attr->port_num,
+ ah_attr->static_rate, &ipd)) {
+ ret = -EINVAL;
+ goto create_ah_exit1;
+ }
+ av->av.ipd = ipd;
} else
av->av.ipd = ehca_static_rate;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 2d660ae189e..87f12d4312a 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -95,7 +95,6 @@ struct ehca_sma_attr {
struct ehca_sport {
struct ib_cq *ibcq_aqp1;
struct ib_qp *ibqp_aqp1;
- enum ib_rate rate;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
};
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 15806d14046..5bd7b591987 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -151,7 +151,6 @@ int ehca_query_port(struct ib_device *ibdev,
}
memset(props, 0, sizeof(struct ib_port_attr));
- props->state = rblock->state;
switch (rblock->max_mtu) {
case 0x1:
@@ -188,11 +187,20 @@ int ehca_query_port(struct ib_device *ibdev,
props->subnet_timeout = rblock->subnet_timeout;
props->init_type_reply = rblock->init_type_reply;
- props->active_width = IB_WIDTH_12X;
- props->active_speed = 0x1;
-
- /* at the moment (logical) link state is always LINK_UP */
- props->phys_state = 0x5;
+ if (rblock->state && rblock->phys_width) {
+ props->phys_state = rblock->phys_pstate;
+ props->state = rblock->phys_state;
+ props->active_width = rblock->phys_width;
+ props->active_speed = rblock->phys_speed;
+ } else {
+ /* old firmware releases don't report physical
+ * port info, so use default values
+ */
+ props->phys_state = 5;
+ props->state = rblock->state;
+ props->active_width = IB_WIDTH_12X;
+ props->active_speed = 0x1;
+ }
query_port1:
ehca_free_fw_ctrlblock(rblock);
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index dce503bb7d6..5485799cdc8 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -189,6 +189,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void ehca_poll_eqs(unsigned long data);
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd);
+
#ifdef CONFIG_PPC_64K_PAGES
void *ehca_alloc_fw_ctrlblock(gfp_t flags);
void ehca_free_fw_ctrlblock(void *ptr);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c6cd38c5321..90d4334179b 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -327,9 +327,6 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
shca->hw_level = ehca_hw_level;
ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
- shca->sport[0].rate = IB_RATE_30_GBPS;
- shca->sport[1].rate = IB_RATE_30_GBPS;
-
shca->hca_cap = rblock->hca_cap_indicators;
ehca_gen_dbg(" ... HCA capabilities:");
for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index de182648b28..dd126681fed 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1196,10 +1196,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1);
}
if (attr_mask & IB_QP_AV) {
- int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate);
- int ehca_mult = ib_rate_to_mult(shca->sport[my_qp->
- init_attr.port_num].rate);
-
mqpcb->dlid = attr->ah_attr.dlid;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1);
mqpcb->source_path_bits = attr->ah_attr.src_path_bits;
@@ -1207,11 +1203,12 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb->service_level = attr->ah_attr.sl;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);
- if (ah_mult < ehca_mult)
- mqpcb->max_static_rate = (ah_mult > 0) ?
- ((ehca_mult - 1) / ah_mult) : 0;
- else
- mqpcb->max_static_rate = 0;
+ if (ehca_calc_ipd(shca, mqpcb->prim_phys_port,
+ attr->ah_attr.static_rate,
+ &mqpcb->max_static_rate)) {
+ ret = -EINVAL;
+ goto modify_qp_exit2;
+ }
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);
/*
@@ -1280,10 +1277,6 @@ static int internal_modify_qp(struct ib_qp *ibqp,
(MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1);
}
if (attr_mask & IB_QP_ALT_PATH) {
- int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate);
- int ehca_mult = ib_rate_to_mult(
- shca->sport[my_qp->init_attr.port_num].rate);
-
if (attr->alt_port_num < 1
|| attr->alt_port_num > shca->num_ports) {
ret = -EINVAL;
@@ -1309,10 +1302,12 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
mqpcb->service_level_al = attr->alt_ah_attr.sl;
- if (ah_mult > 0 && ah_mult < ehca_mult)
- mqpcb->max_static_rate_al = (ehca_mult - 1) / ah_mult;
- else
- mqpcb->max_static_rate_al = 0;
+ if (ehca_calc_ipd(shca, mqpcb->alt_phys_port,
+ attr->alt_ah_attr.static_rate,
+ &mqpcb->max_static_rate_al)) {
+ ret = -EINVAL;
+ goto modify_qp_exit2;
+ }
/* OpenIB doesn't support alternate retry counts - copy them */
mqpcb->retry_count_al = mqpcb->retry_count;
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index d9739e55451..485b8400359 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -402,7 +402,11 @@ struct hipz_query_port {
u64 max_msg_sz;
u32 max_mtu;
u32 vl_cap;
- u8 reserved2[1900];
+ u32 phys_pstate;
+ u32 phys_state;
+ u32 phys_speed;
+ u32 phys_width;
+ u8 reserved2[1884];
u64 guid_entries[255];
} __attribute__ ((packed));
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
index 645ed71fd79..d1380c7a170 100644
--- a/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -395,16 +395,13 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
goto bail;
}
- /*
- * Return the address of the WC as the offset to mmap.
- * See ipath_mmap() for details.
- */
+ /* Check that we can write the offset to mmap. */
if (udata && udata->outlen >= sizeof(__u64)) {
- __u64 offset = (__u64) wc;
+ __u64 offset = 0;
ret = ib_copy_to_udata(udata, &offset, sizeof(offset));
if (ret)
- goto bail;
+ goto bail_free;
}
spin_lock_irq(&cq->lock);
@@ -424,10 +421,8 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
else
n = head - tail;
if (unlikely((u32)cqe < n)) {
- spin_unlock_irq(&cq->lock);
- vfree(wc);
ret = -EOVERFLOW;
- goto bail;
+ goto bail_unlock;
}
for (n = 0; tail != head; n++) {
if (cq->ip)
@@ -452,6 +447,18 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
struct ipath_mmap_info *ip = cq->ip;
ipath_update_mmap_info(dev, ip, sz, wc);
+
+ /*
+ * Return the offset to mmap.
+ * See ipath_mmap() for details.
+ */
+ if (udata && udata->outlen >= sizeof(__u64)) {
+ ret = ib_copy_to_udata(udata, &ip->offset,
+ sizeof(ip->offset));
+ if (ret)
+ goto bail;
+ }
+
spin_lock_irq(&dev->pending_lock);
if (list_empty(&ip->pending_mmaps))
list_add(&ip->pending_mmaps, &dev->pending_mmaps);
@@ -459,7 +466,12 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
}
ret = 0;
+ goto bail;
+bail_unlock:
+ spin_unlock_irq(&cq->lock);
+bail_free:
+ vfree(wc);
bail:
return ret;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
index 6a41fdbc8e5..b997ff88401 100644
--- a/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -835,7 +835,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
init_attr->qp_type);
if (err) {
ret = ERR_PTR(err);
- goto bail_rwq;
+ vfree(qp->r_rq.wq);
+ goto bail_qp;
}
qp->ip = NULL;
ipath_reset_qp(qp);
@@ -863,7 +864,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
sizeof(offset));
if (err) {
ret = ERR_PTR(err);
- goto bail_rwq;
+ goto bail_ip;
}
} else {
u32 s = sizeof(struct ipath_rwq) +
@@ -875,7 +876,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
qp->r_rq.wq);
if (!qp->ip) {
ret = ERR_PTR(-ENOMEM);
- goto bail_rwq;
+ goto bail_ip;
}
err = ib_copy_to_udata(udata, &(qp->ip->offset),
@@ -907,9 +908,11 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
goto bail;
bail_ip:
- kfree(qp->ip);
-bail_rwq:
- vfree(qp->r_rq.wq);
+ if (qp->ip)
+ kref_put(&qp->ip->ref, ipath_release_mmap_info);
+ else
+ vfree(qp->r_rq.wq);
+ ipath_free_qp(&dev->qp_table, qp);
bail_qp:
kfree(qp);
bail_swq:
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index 5c29b2bfea1..120a61b03bc 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -959,8 +959,9 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode,
/* If this is a partial ACK, reset the retransmit timer. */
if (qp->s_last != qp->s_tail) {
spin_lock(&dev->pending_lock);
- list_add_tail(&qp->timerwait,
- &dev->pending[dev->pending_index]);
+ if (list_empty(&qp->timerwait))
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
spin_unlock(&dev->pending_lock);
/*
* If we get a partial ACK for a resent operation,
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
index 40c36ec1901..2fef36f4b67 100644
--- a/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -59,7 +59,7 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
if ((unsigned) wr->num_sge > srq->rq.max_sge) {
*bad_wr = wr;
- ret = -ENOMEM;
+ ret = -EINVAL;
goto bail;
}
@@ -211,11 +211,11 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
struct ib_udata *udata)
{
struct ipath_srq *srq = to_isrq(ibsrq);
+ struct ipath_rwq *wq;
int ret = 0;
if (attr_mask & IB_SRQ_MAX_WR) {
struct ipath_rwq *owq;
- struct ipath_rwq *wq;
struct ipath_rwqe *p;
u32 sz, size, n, head, tail;
@@ -236,27 +236,20 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
goto bail;
}
- /*
- * Return the address of the RWQ as the offset to mmap.
- * See ipath_mmap() for details.
- */
+ /* Check that we can write the offset to mmap. */
if (udata && udata->inlen >= sizeof(__u64)) {
__u64 offset_addr;
- __u64 offset = (__u64) wq;
+ __u64 offset = 0;
ret = ib_copy_from_udata(&offset_addr, udata,
sizeof(offset_addr));
- if (ret) {
- vfree(wq);
- goto bail;
- }
+ if (ret)
+ goto bail_free;
udata->outbuf = (void __user *) offset_addr;
ret = ib_copy_to_udata(udata, &offset,
sizeof(offset));
- if (ret) {
- vfree(wq);
- goto bail;
- }
+ if (ret)
+ goto bail_free;
}
spin_lock_irq(&srq->rq.lock);
@@ -277,10 +270,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
else
n -= tail;
if (size <= n) {
- spin_unlock_irq(&srq->rq.lock);
- vfree(wq);
ret = -EINVAL;
- goto bail;
+ goto bail_unlock;
}
n = 0;
p = wq->wq;
@@ -314,6 +305,18 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
u32 s = sizeof(struct ipath_rwq) + size * sz;
ipath_update_mmap_info(dev, ip, s, wq);
+
+ /*
+ * Return the offset to mmap.
+ * See ipath_mmap() for details.
+ */
+ if (udata && udata->inlen >= sizeof(__u64)) {
+ ret = ib_copy_to_udata(udata, &ip->offset,
+ sizeof(ip->offset));
+ if (ret)
+ goto bail;
+ }
+
spin_lock_irq(&dev->pending_lock);
if (list_empty(&ip->pending_mmaps))
list_add(&ip->pending_mmaps,
@@ -328,7 +331,12 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
srq->limit = attr->srq_limit;
spin_unlock_irq(&srq->rq.lock);
}
+ goto bail;
+bail_unlock:
+ spin_unlock_irq(&srq->rq.lock);
+bail_free:
+ vfree(wq);
bail:
return ret;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 74f77e7c2c1..c4c998446c7 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -302,8 +302,10 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr)
next = qp->s_head + 1;
if (next >= qp->s_size)
next = 0;
- if (next == qp->s_last)
- goto bail_inval;
+ if (next == qp->s_last) {
+ ret = -ENOMEM;
+ goto bail;
+ }
wqe = get_swqe_ptr(qp, qp->s_head);
wqe->wr = *wr;
@@ -404,7 +406,7 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
if ((unsigned) wr->num_sge > qp->r_rq.max_sge) {
*bad_wr = wr;
- ret = -ENOMEM;
+ ret = -EINVAL;
goto bail;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index a03a65ebcf0..c9f6077b615 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -460,6 +460,9 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
+ if (!priv->broadcast)
+ return NULL;
+
path = kzalloc(sizeof *path, GFP_ATOMIC);
if (!path)
return NULL;
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index d6879806179..4a17743a639 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -310,13 +310,15 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data,
if (i + 1 < data->dma_nents) {
next_addr = ib_sg_dma_address(ibdev, sg_next(sg));
/* are i, i+1 fragments of the same page? */
- if (end_addr == next_addr)
+ if (end_addr == next_addr) {
+ cnt++;
continue;
- else if (!IS_4K_ALIGNED(end_addr)) {
+ } else if (!IS_4K_ALIGNED(end_addr)) {
ret_len = cnt + 1;
break;
}
}
+ cnt++;
}
if (i == data->dma_nents)
ret_len = cnt; /* loop ended */
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 2316a018fae..dfa6592c10f 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -286,7 +286,7 @@ config KEYBOARD_MAPLE
config KEYBOARD_BFIN
tristate "Blackfin BF54x keypad support"
- depends on BF54x
+ depends on (BF54x && !BF544)
help
Say Y here if you want to use the BF54x keypad.
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 3eddf52a0bb..6a9ca4bdcb7 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -75,16 +75,32 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
- int irq = gpio_to_irq(button->gpio);
+ int irq;
unsigned int type = button->type ?: EV_KEY;
+ error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
+ if (error < 0) {
+ pr_err("gpio-keys: failed to request GPIO %d,"
+ " error %d\n", button->gpio, error);
+ goto fail;
+ }
+
+ error = gpio_direction_input(button->gpio);
+ if (error < 0) {
+ pr_err("gpio-keys: failed to configure input"
+ " direction for GPIO %d, error %d\n",
+ button->gpio, error);
+ gpio_free(button->gpio);
+ goto fail;
+ }
+
+ irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
- printk(KERN_ERR
- "gpio-keys: "
- "Unable to get irq number for GPIO %d,"
- "error %d\n",
+ pr_err("gpio-keys: Unable to get irq number"
+ " for GPIO %d, error %d\n",
button->gpio, error);
+ gpio_free(button->gpio);
goto fail;
}
@@ -94,9 +110,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
button->desc ? button->desc : "gpio_keys",
pdev);
if (error) {
- printk(KERN_ERR
- "gpio-keys: Unable to claim irq %d; error %d\n",
+ pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
irq, error);
+ gpio_free(button->gpio);
goto fail;
}
@@ -108,8 +124,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
error = input_register_device(input);
if (error) {
- printk(KERN_ERR
- "gpio-keys: Unable to register input device, "
+ pr_err("gpio-keys: Unable to register input device, "
"error: %d\n", error);
goto fail;
}
@@ -119,8 +134,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
return 0;
fail:
- while (--i >= 0)
+ while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+ gpio_free(pdata->buttons[i].gpio);
+ }
platform_set_drvdata(pdev, NULL);
input_free_device(input);
@@ -139,6 +156,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, pdev);
+ gpio_free(pdata->buttons[i].gpio);
}
input_unregister_device(input);
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 5ce632ca681..b88569e21d6 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,7 @@ if SERIO
config SERIO_I8042
tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
default y
- depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BFIN
+ depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN
---help---
i8042 is the chip over which the standard AT keyboard and PS/2
mouse are connected to the computer. If you use these devices,
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index f8fe4214809..c5e68dcd88a 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -110,6 +110,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
},
},
+ {
+ .ident = "Microsoft Virtual Machine",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
+ },
+ },
{ }
};
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 57670dc5034..909d6709ec1 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -118,8 +118,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
case CARD_INIT:
delay = (75*HZ)/100 +1;
- cs->hw.hfcD.timer.expires = jiffies + delay;
- add_timer(&cs->hw.hfcD.timer);
+ mod_timer(&cs->hw.hfcD.timer, jiffies + delay);
spin_lock_irqsave(&cs->lock, flags);
reset_hfcs(cs);
init2bds0(cs);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index c6df2925ebd..d6952959d72 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1515,6 +1515,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (copy_from_user(&iocts, argp,
sizeof(isdn_ioctl_struct)))
return -EFAULT;
+ iocts.drvid[sizeof(iocts.drvid)-1] = 0;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1599,6 +1600,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (copy_from_user(&iocts, argp,
sizeof(isdn_ioctl_struct)))
return -EFAULT;
+ iocts.drvid[sizeof(iocts.drvid)-1] = 0;
if (strlen(iocts.drvid)) {
drvidx = -1;
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1643,7 +1645,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
} else {
p = (char __user *) iocts.arg;
for (i = 0; i < 10; i++) {
- sprintf(bname, "%s%s",
+ snprintf(bname, sizeof(bname), "%s%s",
strlen(dev->drv[drvidx]->msn2eaz[i]) ?
dev->drv[drvidx]->msn2eaz[i] : "_",
(i < 9) ? "," : "\0");
@@ -1673,6 +1675,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
char *p;
if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct)))
return -EFAULT;
+ iocts.drvid[sizeof(iocts.drvid)-1] = 0;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index b39d1f5b378..ced83c202ca 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -2104,7 +2104,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
u_long flags;
isdn_net_dev *p;
isdn_net_phone *n;
- char nr[32];
+ char nr[ISDN_MSNLEN];
char *my_eaz;
/* Search name in netdev-chain */
@@ -2113,7 +2113,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
nr[1] = '\0';
printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
} else
- strcpy(nr, setup->phone);
+ strlcpy(nr, setup->phone, ISDN_MSNLEN);
si1 = (int) setup->si1;
si2 = (int) setup->si2;
if (!setup->eazmsn[0]) {
@@ -2789,7 +2789,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
chidx = -1;
}
}
- strcpy(lp->msn, cfg->eaz);
+ strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn));
lp->pre_device = drvidx;
lp->pre_channel = chidx;
lp->onhtime = cfg->onhtime;
@@ -2936,7 +2936,7 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
if (p) {
if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
return -ENOMEM;
- strcpy(n->num, phone->phone);
+ strlcpy(n->num, phone->phone, sizeof(n->num));
n->next = p->local->phone[phone->outgoing & 1];
p->local->phone[phone->outgoing & 1] = n;
return 0;
diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h
index 5992f63c383..0120bcf8831 100644
--- a/drivers/isdn/sc/card.h
+++ b/drivers/isdn/sc/card.h
@@ -109,7 +109,7 @@ void memcpy_fromshmem(int card, void *dest, const void *src, size_t n);
int get_card_from_id(int driver);
int indicate_status(int card, int event, ulong Channel, char *Data);
irqreturn_t interrupt_handler(int interrupt, void *cardptr);
-int sndpkt(int devId, int channel, struct sk_buff *data);
+int sndpkt(int devId, int channel, int ack, struct sk_buff *data);
void rcvpkt(int card, RspMessage *rcvmsg);
int command(isdn_ctrl *cmd);
int reset(int card);
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 92016a2608e..5ff6ae86844 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -20,7 +20,7 @@
#include "message.h"
#include "card.h"
-int sndpkt(int devId, int channel, struct sk_buff *data)
+int sndpkt(int devId, int channel, int ack, struct sk_buff *data)
{
LLData ReqLnkWrite;
int status;
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index e0331e0094f..712220cef13 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -50,7 +50,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
- memcpy_toio(sc_adapter[card]->rambase + dest_rem, src, n);
+ memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 07ae280e8fe..47c10b8f89b 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1188,8 +1188,7 @@ int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)
int emulate_clts(struct kvm_vcpu *vcpu)
{
- vcpu->cr0 &= ~X86_CR0_TS;
- kvm_x86_ops->set_cr0(vcpu, vcpu->cr0);
+ kvm_x86_ops->set_cr0(vcpu, vcpu->cr0 & ~X86_CR0_TS);
return X86EMUL_CONTINUE;
}
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 729f1cd9360..4e04e49a2f1 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -494,6 +494,7 @@ static void init_vmcb(struct vmcb *vmcb)
*/
/* (1ULL << INTERCEPT_SELECTIVE_CR0) | */
(1ULL << INTERCEPT_CPUID) |
+ (1ULL << INTERCEPT_INVD) |
(1ULL << INTERCEPT_HLT) |
(1ULL << INTERCEPT_INVLPGA) |
(1ULL << INTERCEPT_IOIO_PROT) |
@@ -507,6 +508,7 @@ static void init_vmcb(struct vmcb *vmcb)
(1ULL << INTERCEPT_STGI) |
(1ULL << INTERCEPT_CLGI) |
(1ULL << INTERCEPT_SKINIT) |
+ (1ULL << INTERCEPT_WBINVD) |
(1ULL << INTERCEPT_MONITOR) |
(1ULL << INTERCEPT_MWAIT);
@@ -561,6 +563,12 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu)
struct vcpu_svm *svm = to_svm(vcpu);
init_vmcb(svm->vmcb);
+
+ if (vcpu->vcpu_id != 0) {
+ svm->vmcb->save.rip = 0;
+ svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12;
+ svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8;
+ }
}
static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
@@ -655,6 +663,7 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)
wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
rdtscll(vcpu->host_tsc);
+ kvm_put_guest_fpu(vcpu);
}
static void svm_vcpu_decache(struct kvm_vcpu *vcpu)
@@ -1241,6 +1250,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_VINTR] = interrupt_window_interception,
/* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */
[SVM_EXIT_CPUID] = cpuid_interception,
+ [SVM_EXIT_INVD] = emulate_on_interception,
[SVM_EXIT_HLT] = halt_interception,
[SVM_EXIT_INVLPG] = emulate_on_interception,
[SVM_EXIT_INVLPGA] = invalid_op_interception,
@@ -1255,6 +1265,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_STGI] = invalid_op_interception,
[SVM_EXIT_CLGI] = invalid_op_interception,
[SVM_EXIT_SKINIT] = invalid_op_interception,
+ [SVM_EXIT_WBINVD] = emulate_on_interception,
[SVM_EXIT_MONITOR] = invalid_op_interception,
[SVM_EXIT_MWAIT] = invalid_op_interception,
};
@@ -1579,10 +1590,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
#endif
: "cc", "memory" );
- local_irq_disable();
-
- stgi();
-
if ((svm->vmcb->save.dr7 & 0xff))
load_db_regs(svm->host_db_regs);
@@ -1599,6 +1606,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
reload_tss(vcpu);
+ local_irq_disable();
+
+ stgi();
+
svm->next_rip = 0;
}
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index a6ace302e0c..bd46de6bf89 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -167,7 +167,7 @@ static u8 opcode_table[256] = {
static u16 twobyte_table[256] = {
/* 0x00 - 0x0F */
0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
- 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+ ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
/* 0x10 - 0x1F */
0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 - 0x2F */
@@ -448,8 +448,7 @@ struct operand {
#define JMP_REL(rel) \
do { \
- _eip += (int)(rel); \
- _eip = ((op_bytes == 2) ? (uint16_t)_eip : (uint32_t)_eip); \
+ register_address_increment(_eip, rel); \
} while (0)
/*
@@ -980,17 +979,6 @@ done_prefixes:
goto cannot_emulate;
dst.val = (s32) src.val;
break;
- case 0x6a: /* push imm8 */
- src.val = 0L;
- src.val = insn_fetch(s8, 1, _eip);
-push:
- dst.type = OP_MEM;
- dst.bytes = op_bytes;
- dst.val = src.val;
- register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
- dst.ptr = (void *) register_address(ctxt->ss_base,
- _regs[VCPU_REGS_RSP]);
- break;
case 0x80 ... 0x83: /* Grp1 */
switch (modrm_reg) {
case 0:
@@ -1158,7 +1146,7 @@ push:
}
register_address_increment(_regs[VCPU_REGS_RSP],
-dst.bytes);
- if ((rc = ops->write_std(
+ if ((rc = ops->write_emulated(
register_address(ctxt->ss_base,
_regs[VCPU_REGS_RSP]),
&dst.val, dst.bytes, ctxt->vcpu)) != 0)
@@ -1243,6 +1231,17 @@ special_insn:
register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
no_wb = 1; /* Disable writeback. */
break;
+ case 0x6a: /* push imm8 */
+ src.val = 0L;
+ src.val = insn_fetch(s8, 1, _eip);
+ push:
+ dst.type = OP_MEM;
+ dst.bytes = op_bytes;
+ dst.val = src.val;
+ register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
+ dst.ptr = (void *) register_address(ctxt->ss_base,
+ _regs[VCPU_REGS_RSP]);
+ break;
case 0x6c: /* insb */
case 0x6d: /* insw/insd */
if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
@@ -1359,6 +1358,7 @@ special_insn:
}
src.val = (unsigned long) _eip;
JMP_REL(rel);
+ op_bytes = ad_bytes;
goto push;
}
case 0xe9: /* jmp rel */
@@ -1532,6 +1532,8 @@ twobyte_special_insn:
case 0x06:
emulate_clts(ctxt->vcpu);
break;
+ case 0x08: /* invd */
+ break;
case 0x09: /* wbinvd */
break;
case 0x0d: /* GrpP (prefetch) */
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 8904f72f97c..e2eec38c83c 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -200,7 +200,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
/* Figure out how many pages the ring will take, and map that memory */
lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT,
- DIV_ROUND_UP(vring_size(lvq->config.num),
+ DIV_ROUND_UP(vring_size(lvq->config.num,
+ PAGE_SIZE),
PAGE_SIZE));
if (!lvq->pages) {
err = -ENOMEM;
@@ -246,6 +247,8 @@ static void lg_del_vq(struct virtqueue *vq)
{
struct lguest_vq_info *lvq = vq->priv;
+ /* Release the interrupt */
+ free_irq(lvq->config.irq, vq);
/* Tell virtio_ring.c to free the virtqueue. */
vring_del_virtqueue(vq);
/* Unmap the pages containing the ring. */
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 9d716fa42ca..3b92a61ba8d 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -184,7 +184,7 @@ static int initialize(struct file *file, const unsigned long __user *input)
free_regs:
free_page(lg->regs_page);
release_guest:
- memset(lg, 0, sizeof(*lg));
+ kfree(lg);
unlock:
mutex_unlock(&lguest_lock);
return err;
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 516d943227e..075b4d99e35 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -94,7 +94,9 @@ static int wf_thread_func(void *data)
DBG("wf: thread started\n");
set_freezable();
- while(!kthread_should_stop()) {
+ while (!kthread_should_stop()) {
+ try_to_freeze();
+
if (time_after_eq(jiffies, next)) {
wf_notify(WF_EVENT_TICK, NULL);
if (wf_overtemp) {
@@ -116,12 +118,6 @@ static int wf_thread_func(void *data)
delay = next - jiffies;
if (delay <= HZ)
schedule_timeout_interruptible(delay);
-
- /* there should be no non-suspend signal, but oh well */
- if (signal_pending(current) && !try_to_freeze()) {
- printk(KERN_WARNING "windfarm: thread got sigl !\n");
- break;
- }
}
DBG("wf: thread stopped\n");
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 7c426d07a55..1b1ef3130e6 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1207,8 +1207,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
prepare_to_wait(&bitmap->overflow_wait, &__wait,
TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&bitmap->lock);
- bitmap->mddev->queue
- ->unplug_fn(bitmap->mddev->queue);
+ blk_unplug(bitmap->mddev->queue);
schedule();
finish_wait(&bitmap->overflow_wait, &__wait);
continue;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 5a7eb650181..e298d8d11f2 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1000,8 +1000,7 @@ void dm_table_unplug_all(struct dm_table *t)
struct dm_dev *dd = list_entry(d, struct dm_dev, list);
struct request_queue *q = bdev_get_queue(dd->bdev);
- if (q->unplug_fn)
- q->unplug_fn(q);
+ blk_unplug(q);
}
}
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 56a11f6c127..3dac1cfb818 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -87,8 +87,7 @@ static void linear_unplug(struct request_queue *q)
for (i=0; i < mddev->raid_disks; i++) {
struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
}
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 808cd954945..cef9ebd5a04 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5445,7 +5445,7 @@ void md_do_sync(mddev_t *mddev)
* about not overloading the IO subsystem. (things like an
* e2fsck being done on the RAID array should execute fast)
*/
- mddev->queue->unplug_fn(mddev->queue);
+ blk_unplug(mddev->queue);
cond_resched();
currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
@@ -5464,7 +5464,7 @@ void md_do_sync(mddev_t *mddev)
* this also signals 'finished resyncing' to md_stop
*/
out:
- mddev->queue->unplug_fn(mddev->queue);
+ blk_unplug(mddev->queue);
wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index b35731cceac..eb631ebed68 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -125,8 +125,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index c111105fc2d..f8e591708d1 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -35,8 +35,7 @@ static void raid0_unplug(struct request_queue *q)
for (i=0; i<mddev->raid_disks; i++) {
struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev);
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
}
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 85478d6a9c1..4a69c416e04 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -549,8 +549,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index fc6607acb6e..5cdcc938620 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -593,8 +593,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 82af3465a90..a5aad8cad84 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -688,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
}
static struct dma_async_tx_descriptor *
-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long pending)
{
int disks = sh->disks;
int pd_idx = sh->pd_idx, i;
@@ -696,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
/* check if prexor is active which means only process blocks
* that are part of a read-modify-write (Wantprexor)
*/
- int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
pr_debug("%s: stripe %llu\n", __FUNCTION__,
(unsigned long long)sh->sector);
@@ -773,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref)
}
static void
-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long pending)
{
/* kernel stack size limits the total number of disks */
int disks = sh->disks;
@@ -781,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
int count = 0, pd_idx = sh->pd_idx, i;
struct page *xor_dest;
- int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
unsigned long flags;
dma_async_tx_callback callback;
@@ -808,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
}
/* check whether this postxor is part of a write */
- callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+ callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
ops_complete_write : ops_complete_postxor;
/* 1/ if we prexor'd then the dest is reused as a source
@@ -896,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
tx = ops_run_prexor(sh, tx);
if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
- tx = ops_run_biodrain(sh, tx);
+ tx = ops_run_biodrain(sh, tx, pending);
overlap_clear++;
}
if (test_bit(STRIPE_OP_POSTXOR, &pending))
- ops_run_postxor(sh, tx);
+ ops_run_postxor(sh, tx, pending);
if (test_bit(STRIPE_OP_CHECK, &pending))
ops_run_check(sh);
@@ -3186,8 +3188,7 @@ static void unplug_slaves(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- if (r_queue->unplug_fn)
- r_queue->unplug_fn(r_queue);
+ blk_unplug(r_queue);
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 8135e4c3bf4..afd82966f9a 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -156,7 +156,7 @@ static void sm501_dump_clk(struct sm501_devdata *sm)
dev_dbg(sm->dev, "PM0[%c]: "
"P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
-x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
+ "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
(pmc & 3 ) == 0 ? '*' : '-',
fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31, px_div)),
fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15, misc_div)),
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 6a5a05d1f39..05172d2613d 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -244,10 +244,11 @@ ioc4_variant(struct ioc4_driver_data *idd)
idd->idd_pdev->bus->number == pdev->bus->number &&
3 == PCI_SLOT(pdev->devfn))
found = 1;
- pci_dev_put(pdev);
} while (pdev && !found);
- if (NULL != pdev)
+ if (NULL != pdev) {
+ pci_dev_put(pdev);
return IOC4_VARIANT_IO9;
+ }
/* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
pdev = NULL;
@@ -258,10 +259,11 @@ ioc4_variant(struct ioc4_driver_data *idd)
idd->idd_pdev->bus->number == pdev->bus->number &&
3 == PCI_SLOT(pdev->devfn))
found = 1;
- pci_dev_put(pdev);
} while (pdev && !found);
- if (NULL != pdev)
+ if (NULL != pdev) {
+ pci_dev_put(pdev);
return IOC4_VARIANT_IO10;
+ }
/* PCI-RT: No SCSI/SATA controller will be present */
return IOC4_VARIANT_PCI_RT;
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index bb13858f60a..b0f68031b49 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -338,7 +338,7 @@ static void sony_laptop_report_input_event(u8 event)
dprintk("unknown input event %.2x\n", event);
}
-static int sony_laptop_setup_input(void)
+static int sony_laptop_setup_input(struct acpi_device *acpi_device)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
@@ -379,6 +379,7 @@ static int sony_laptop_setup_input(void)
key_dev->name = "Sony Vaio Keys";
key_dev->id.bustype = BUS_ISA;
key_dev->id.vendor = PCI_VENDOR_ID_SONY;
+ key_dev->dev.parent = &acpi_device->dev;
/* Initialize the Input Drivers: special keys */
set_bit(EV_KEY, key_dev->evbit);
@@ -410,6 +411,7 @@ static int sony_laptop_setup_input(void)
jog_dev->name = "Sony Vaio Jogdial";
jog_dev->id.bustype = BUS_ISA;
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
+ key_dev->dev.parent = &acpi_device->dev;
jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
@@ -1006,7 +1008,7 @@ static int sony_nc_add(struct acpi_device *device)
}
/* setup input devices and helper fifo */
- result = sony_laptop_setup_input();
+ result = sony_laptop_setup_input(device);
if (result) {
printk(KERN_ERR DRV_PFX
"Unabe to create input devices.\n");
@@ -1034,7 +1036,7 @@ static int sony_nc_add(struct acpi_device *device)
sony_backlight_device->props.brightness =
sony_backlight_get_brightness
(sony_backlight_device);
- sony_backlight_device->props.max_brightness =
+ sony_backlight_device->props.max_brightness =
SONY_MAX_BRIGHTNESS - 1;
}
@@ -2453,7 +2455,7 @@ static int sony_pic_add(struct acpi_device *device)
}
/* setup input devices and helper fifo */
- result = sony_laptop_setup_input();
+ result = sony_laptop_setup_input(device);
if (result) {
printk(KERN_ERR DRV_PFX
"Unabe to create input devices.\n");
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index e953276664a..ab23a322158 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -21,7 +21,7 @@
* 02110-1301, USA.
*/
-#define IBM_VERSION "0.16"
+#define IBM_VERSION "0.17"
#define TPACPI_SYSFS_VERSION 0x020000
/*
@@ -964,15 +964,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
KEY_UNKNOWN, /* 0x0D: FN+INSERT */
KEY_UNKNOWN, /* 0x0E: FN+DELETE */
- KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
+ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
/* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
- KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
+ KEY_RESERVED, /* 0x10: FN+END (brightness down) */
KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
- KEY_VOLUMEUP, /* 0x14: VOLUME UP */
- KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */
- KEY_MUTE, /* 0x16: MUTE */
+ KEY_RESERVED, /* 0x14: VOLUME UP */
+ KEY_RESERVED, /* 0x15: VOLUME DOWN */
+ KEY_RESERVED, /* 0x16: MUTE */
KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
/* (assignments unknown, please report if found) */
KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -993,9 +993,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
- KEY_VOLUMEUP, /* 0x14: VOLUME UP */
- KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */
- KEY_MUTE, /* 0x16: MUTE */
+ KEY_RESERVED, /* 0x14: VOLUME UP */
+ KEY_RESERVED, /* 0x15: VOLUME DOWN */
+ KEY_RESERVED, /* 0x16: MUTE */
KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
/* (assignments unknown, please report if found) */
KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -1342,9 +1342,8 @@ static int hotkey_read(char *p)
return len;
}
- res = mutex_lock_interruptible(&hotkey_mutex);
- if (res < 0)
- return res;
+ if (mutex_lock_interruptible(&hotkey_mutex))
+ return -ERESTARTSYS;
res = hotkey_get(&status, &mask);
mutex_unlock(&hotkey_mutex);
if (res)
@@ -1373,9 +1372,8 @@ static int hotkey_write(char *buf)
if (!tp_features.hotkey)
return -ENODEV;
- res = mutex_lock_interruptible(&hotkey_mutex);
- if (res < 0)
- return res;
+ if (mutex_lock_interruptible(&hotkey_mutex))
+ return -ERESTARTSYS;
res = hotkey_get(&status, &mask);
if (res)
@@ -3114,6 +3112,99 @@ static struct backlight_ops ibm_backlight_data = {
static struct mutex brightness_mutex;
+static int __init tpacpi_query_bcll_levels(acpi_handle handle)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ int rc;
+
+ if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
+ obj = (union acpi_object *)buffer.pointer;
+ if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
+ printk(IBM_ERR "Unknown BCLL data, "
+ "please report this to %s\n", IBM_MAIL);
+ rc = 0;
+ } else {
+ rc = obj->package.count;
+ }
+ } else {
+ return 0;
+ }
+
+ kfree(buffer.pointer);
+ return rc;
+}
+
+static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl,
+ void *context, void **rv)
+{
+ char name[ACPI_PATH_SEGMENT_LENGTH];
+ struct acpi_buffer buffer = { sizeof(name), &name };
+
+ if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
+ !strncmp("BCLL", name, sizeof(name) - 1)) {
+ if (tpacpi_query_bcll_levels(handle) == 16) {
+ *rv = handle;
+ return AE_CTRL_TERMINATE;
+ } else {
+ return AE_OK;
+ }
+ } else {
+ return AE_OK;
+ }
+}
+
+static int __init brightness_check_levels(void)
+{
+ int status;
+ void *found_node = NULL;
+
+ if (!vid_handle) {
+ IBM_ACPIHANDLE_INIT(vid);
+ }
+ if (!vid_handle)
+ return 0;
+
+ /* Search for a BCLL package with 16 levels */
+ status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3,
+ brightness_find_bcll, NULL, &found_node);
+
+ return (ACPI_SUCCESS(status) && found_node != NULL);
+}
+
+static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl,
+ void *context, void **rv)
+{
+ char name[ACPI_PATH_SEGMENT_LENGTH];
+ struct acpi_buffer buffer = { sizeof(name), &name };
+
+ if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
+ !strncmp("_BCL", name, sizeof(name) - 1)) {
+ *rv = handle;
+ return AE_CTRL_TERMINATE;
+ } else {
+ return AE_OK;
+ }
+}
+
+static int __init brightness_check_std_acpi_support(void)
+{
+ int status;
+ void *found_node = NULL;
+
+ if (!vid_handle) {
+ IBM_ACPIHANDLE_INIT(vid);
+ }
+ if (!vid_handle)
+ return 0;
+
+ /* Search for a _BCL method, but don't execute it */
+ status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
+ brightness_find_bcl, NULL, &found_node);
+
+ return (ACPI_SUCCESS(status) && found_node != NULL);
+}
+
static int __init brightness_init(struct ibm_init_struct *iibm)
{
int b;
@@ -3122,6 +3213,18 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
mutex_init(&brightness_mutex);
+ if (!brightness_enable) {
+ dbg_printk(TPACPI_DBG_INIT,
+ "brightness support disabled by module parameter\n");
+ return 1;
+ } else if (brightness_enable > 1) {
+ if (brightness_check_std_acpi_support()) {
+ printk(IBM_NOTICE
+ "standard ACPI backlight interface available, not loading native one...\n");
+ return 1;
+ }
+ }
+
if (!brightness_mode) {
if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
brightness_mode = 2;
@@ -3135,10 +3238,17 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
if (brightness_mode > 3)
return -EINVAL;
+ tp_features.bright_16levels =
+ thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO &&
+ brightness_check_levels();
+
b = brightness_get(NULL);
if (b < 0)
return 1;
+ if (tp_features.bright_16levels)
+ printk(IBM_INFO "detected a 16-level brightness capable ThinkPad\n");
+
ibm_backlight_device = backlight_device_register(
TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
&ibm_backlight_data);
@@ -3148,7 +3258,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
}
vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n");
- ibm_backlight_device->props.max_brightness = 7;
+ ibm_backlight_device->props.max_brightness =
+ (tp_features.bright_16levels)? 15 : 7;
ibm_backlight_device->props.brightness = b;
backlight_update_status(ibm_backlight_device);
@@ -3167,6 +3278,8 @@ static void brightness_exit(void)
static int brightness_update_status(struct backlight_device *bd)
{
+ /* it is the backlight class's job (caller) to handle
+ * EINTR and other errors properly */
return brightness_set(
(bd->props.fb_blank == FB_BLANK_UNBLANK &&
bd->props.power == FB_BLANK_UNBLANK) ?
@@ -3184,13 +3297,14 @@ static int brightness_get(struct backlight_device *bd)
if (brightness_mode & 1) {
if (!acpi_ec_read(brightness_offset, &lec))
return -EIO;
- lec &= 7;
+ lec &= (tp_features.bright_16levels)? 0x0f : 0x07;
level = lec;
};
if (brightness_mode & 2) {
lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
& TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
>> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
+ lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07;
level = lcmos;
}
@@ -3206,12 +3320,13 @@ static int brightness_get(struct backlight_device *bd)
return level;
}
+/* May return EINTR which can always be mapped to ERESTARTSYS */
static int brightness_set(int value)
{
int cmos_cmd, inc, i, res;
int current_value;
- if (value > 7)
+ if (value > ((tp_features.bright_16levels)? 15 : 7))
return -EINVAL;
res = mutex_lock_interruptible(&brightness_mutex);
@@ -3227,7 +3342,7 @@ static int brightness_set(int value)
cmos_cmd = value > current_value ?
TP_CMOS_BRIGHTNESS_UP :
TP_CMOS_BRIGHTNESS_DOWN;
- inc = value > current_value ? 1 : -1;
+ inc = (value > current_value)? 1 : -1;
res = 0;
for (i = current_value; i != value; i += inc) {
@@ -3256,10 +3371,11 @@ static int brightness_read(char *p)
if ((level = brightness_get(NULL)) < 0) {
len += sprintf(p + len, "level:\t\tunreadable\n");
} else {
- len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
+ len += sprintf(p + len, "level:\t\t%d\n", level);
len += sprintf(p + len, "commands:\tup, down\n");
len += sprintf(p + len, "commands:\tlevel <level>"
- " (<level> is 0-7)\n");
+ " (<level> is 0-%d)\n",
+ (tp_features.bright_16levels) ? 15 : 7);
}
return len;
@@ -3268,28 +3384,34 @@ static int brightness_read(char *p)
static int brightness_write(char *buf)
{
int level;
- int new_level;
+ int rc;
char *cmd;
+ int max_level = (tp_features.bright_16levels) ? 15 : 7;
- while ((cmd = next_cmd(&buf))) {
- if ((level = brightness_get(NULL)) < 0)
- return level;
- level &= 7;
+ level = brightness_get(NULL);
+ if (level < 0)
+ return level;
+ while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "up") == 0) {
- new_level = level == 7 ? 7 : level + 1;
+ if (level < max_level)
+ level++;
} else if (strlencmp(cmd, "down") == 0) {
- new_level = level == 0 ? 0 : level - 1;
- } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
- new_level >= 0 && new_level <= 7) {
- /* new_level set */
+ if (level > 0)
+ level--;
+ } else if (sscanf(cmd, "level %d", &level) == 1 &&
+ level >= 0 && level <= max_level) {
+ /* new level set */
} else
return -EINVAL;
-
- brightness_set(new_level);
}
- return 0;
+ /*
+ * Now we know what the final level should be, so we try to set it.
+ * Doing it this way makes the syscall restartable in case of EINTR
+ */
+ rc = brightness_set(level);
+ return (rc == -EINTR)? ERESTARTSYS : rc;
}
static struct ibm_struct brightness_driver_data = {
@@ -3652,9 +3774,8 @@ static ssize_t fan_pwm1_store(struct device *dev,
/* scale down from 0-255 to 0-7 */
newlevel = (s >> 5) & 0x07;
- rc = mutex_lock_interruptible(&fan_mutex);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&fan_mutex))
+ return -ERESTARTSYS;
rc = fan_get_status(&status);
if (!rc && (status &
@@ -3904,9 +4025,8 @@ static int fan_get_status_safe(u8 *status)
int rc;
u8 s;
- rc = mutex_lock_interruptible(&fan_mutex);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&fan_mutex))
+ return -ERESTARTSYS;
rc = fan_get_status(&s);
if (!rc)
fan_update_desired_level(s);
@@ -4040,9 +4160,8 @@ static int fan_set_level_safe(int level)
if (!fan_control_allowed)
return -EPERM;
- rc = mutex_lock_interruptible(&fan_mutex);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&fan_mutex))
+ return -ERESTARTSYS;
if (level == TPACPI_FAN_LAST_LEVEL)
level = fan_control_desired_level;
@@ -4063,9 +4182,8 @@ static int fan_set_enable(void)
if (!fan_control_allowed)
return -EPERM;
- rc = mutex_lock_interruptible(&fan_mutex);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&fan_mutex))
+ return -ERESTARTSYS;
switch (fan_control_access_mode) {
case TPACPI_FAN_WR_ACPI_FANS:
@@ -4119,9 +4237,8 @@ static int fan_set_disable(void)
if (!fan_control_allowed)
return -EPERM;
- rc = mutex_lock_interruptible(&fan_mutex);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&fan_mutex))
+ return -ERESTARTSYS;
rc = 0;
switch (fan_control_access_mode) {
@@ -4158,9 +4275,8 @@ static int fan_set_speed(int speed)
if (!fan_control_allowed)
return -EPERM;
- rc = mutex_lock_interruptible(&fan_mutex);
- if (rc < 0)
- return rc;
+ if (mutex_lock_interruptible(&fan_mutex))
+ return -ERESTARTSYS;
rc = 0;
switch (fan_control_access_mode) {
@@ -4701,9 +4817,15 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
unsigned int i;
struct ibm_struct *ibm;
+ if (!kp || !kp->name || !val)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
ibm = ibms_init[i].data;
- BUG_ON(ibm == NULL);
+ WARN_ON(ibm == NULL);
+
+ if (!ibm || !ibm->name)
+ continue;
if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
if (strlen(val) > sizeof(ibms_init[i].param) - 2)
@@ -4732,6 +4854,9 @@ module_param_named(fan_control, fan_control_allowed, bool, 0);
static int brightness_mode;
module_param_named(brightness_mode, brightness_mode, int, 0);
+static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
+module_param(brightness_enable, uint, 0);
+
static unsigned int hotkey_report_mode;
module_param(hotkey_report_mode, uint, 0);
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 3abcc812063..8fba2bbe345 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -84,7 +84,7 @@
/* ThinkPad CMOS NVRAM constants */
#define TP_NVRAM_ADDR_BRIGHTNESS 0x5e
-#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07
+#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x0f
#define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0
#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
@@ -246,6 +246,7 @@ static struct {
u32 hotkey_wlsw:1;
u32 light:1;
u32 light_status:1;
+ u32 bright_16levels:1;
u32 wan:1;
u32 fan_ctrl_status_undef:1;
u32 input_device_registered:1;
@@ -338,6 +339,7 @@ static int bluetooth_write(char *buf);
static struct backlight_device *ibm_backlight_device;
static int brightness_offset = 0x31;
static int brightness_mode;
+static unsigned int brightness_enable; /* 0 = no, 1 = yes, 2 = auto */
static int brightness_init(struct ibm_init_struct *iibm);
static void brightness_exit(void);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e38d5a3b2a8..aeb32a93f6a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -44,6 +44,9 @@
* max 8 partitions per card
*/
#define MMC_SHIFT 3
+#define MMC_NUM_MINORS (256 >> MMC_SHIFT)
+
+static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
/*
* There is one mmc_blk_data per slot.
@@ -80,6 +83,9 @@ static void mmc_blk_put(struct mmc_blk_data *md)
mutex_lock(&open_lock);
md->usage--;
if (md->usage == 0) {
+ int devidx = md->disk->first_minor >> MMC_SHIFT;
+ __clear_bit(devidx, dev_use);
+
put_disk(md->disk);
kfree(md);
}
@@ -321,7 +327,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
req->rq_disk->disk_name, err);
goto cmd_err;
}
- } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+ /*
+ * Some cards mishandle the status bits,
+ * so make sure to check both the busy
+ * indication and the card state.
+ */
+ } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
+ (R1_CURRENT_STATE(cmd.resp[0]) == 7));
#if 0
if (cmd.resp[0] & ~0x00000900)
@@ -400,9 +412,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
return 0;
}
-#define MMC_NUM_MINORS (256 >> MMC_SHIFT)
-
-static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
static inline int mmc_blk_readonly(struct mmc_card *card)
{
@@ -568,17 +577,12 @@ static void mmc_blk_remove(struct mmc_card *card)
struct mmc_blk_data *md = mmc_get_drvdata(card);
if (md) {
- int devidx;
-
/* Stop new requests from getting into the queue */
del_gendisk(md->disk);
/* Then flush out any already in there */
mmc_cleanup_queue(&md->queue);
- devidx = md->disk->first_minor >> MMC_SHIFT;
- __clear_bit(devidx, dev_use);
-
mmc_blk_put(md);
}
mmc_set_drvdata(card, NULL);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 9203a0b221b..30cd13b13ac 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -180,12 +180,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
- mq->sg = kzalloc(sizeof(struct scatterlist) *
+ mq->sg = kmalloc(sizeof(struct scatterlist) *
host->max_phys_segs, GFP_KERNEL);
if (!mq->sg) {
ret = -ENOMEM;
goto cleanup_queue;
}
+ sg_init_table(mq->sg, host->max_phys_segs);
}
init_MUTEX(&mq->thread_sem);
@@ -310,7 +311,7 @@ static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
}
if (src_size == 0) {
- src_buf = sg_virt(dst);
+ src_buf = sg_virt(src);
src_size = src->length;
}
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index d552de68311..eeea84c309e 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -386,7 +386,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port)
sdio_out(port, UART_IER, port->ier);
}
-static void sdio_uart_receive_chars(struct sdio_uart_port *port, int *status)
+static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status)
{
struct tty_struct *tty = port->tty;
unsigned int ch, flag;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 6b80bf77a4e..ff59d2e0475 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1301,7 +1301,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
if ((chip->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
(host->flags & SDHCI_USE_DMA)) {
- DBG("Disabling DMA as it is marked broken");
+ DBG("Disabling DMA as it is marked broken\n");
host->flags &= ~SDHCI_USE_DMA;
}
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index c11a3d25605..20d5c7bd940 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -16,7 +16,6 @@
#include <linux/mmc/host.h>
#include <linux/highmem.h>
#include <linux/scatterlist.h>
-#include <linux/log2.h>
#include <asm/io.h>
#define DRIVER_NAME "tifm_sd"
@@ -638,17 +637,15 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
goto err_out;
}
- if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
- printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n",
- sock->dev.bus_id, mrq->data->blksz);
- mrq->cmd->error = -EINVAL;
- goto err_out;
- }
-
host->cmd_flags = 0;
host->block_pos = 0;
host->sg_pos = 0;
+ if (mrq->data && !is_power_of_2(mrq->data->blksz))
+ host->no_dma = 1;
+ else
+ host->no_dma = no_dma ? 1 : 0;
+
if (r_data) {
tifm_sd_set_data_timeout(host, r_data);
@@ -676,7 +673,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
: PCI_DMA_FROMDEVICE)) {
printk(KERN_ERR "%s : scatterlist map failed\n",
sock->dev.bus_id);
- spin_unlock_irqrestore(&sock->lock, flags);
+ mrq->cmd->error = -ENOMEM;
goto err_out;
}
host->sg_len = tifm_map_sg(sock, r_data->sg,
@@ -692,7 +689,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
r_data->flags & MMC_DATA_WRITE
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE);
- spin_unlock_irqrestore(&sock->lock, flags);
+ mrq->cmd->error = -ENOMEM;
goto err_out;
}
@@ -966,7 +963,6 @@ static int tifm_sd_probe(struct tifm_dev *sock)
return -ENOMEM;
host = mmc_priv(mmc);
- host->no_dma = no_dma;
tifm_set_drvdata(sock, mmc);
host->dev = sock;
host->timeout_jiffies = msecs_to_jiffies(1000);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f800a6dd97..d9107e542df 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -136,10 +136,11 @@ config TUN
If you don't know what to use this for, you don't need it.
config VETH
- tristate "Virtual ethernet device"
+ tristate "Virtual ethernet pair device"
---help---
- The device is an ethernet tunnel. Devices are created in pairs. When
- one end receives the packet it appears on its pair and vice versa.
+ This device is a local ethernet tunnel. Devices are created in pairs.
+ When one end receives the packet it appears on its pair and vice
+ versa.
config NET_SB1000
tristate "General Instruments Surfboard 1000"
@@ -234,7 +235,7 @@ source "drivers/net/arm/Kconfig"
config AX88796
tristate "ASIX AX88796 NE2000 clone support"
- depends on ARM || MIPS
+ depends on ARM || MIPS || SUPERH
select CRC32
select MII
help
@@ -365,8 +366,7 @@ config MAC89x0
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. This module will
+ To compile this driver as a module, choose M here. This module will
be called mac89x0.
config MACSONIC
@@ -379,8 +379,7 @@ config MACSONIC
one of these say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. This module will
+ To compile this driver as a module, choose M here. This module will
be called macsonic.
config MACMACE
@@ -618,8 +617,7 @@ config EL1
have problems. Some people suggest to ping ("man ping") a nearby
machine every minute ("man cron") when using this card.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c501.
config EL2
@@ -631,8 +629,7 @@ config EL2
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c503.
config ELPLUS
@@ -644,8 +641,7 @@ config ELPLUS
this type, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c505.
config EL16
@@ -656,8 +652,7 @@ config EL16
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c507.
config EL3
@@ -672,8 +667,7 @@ config EL3
setup disk to disable Plug & Play mode, and to select the default
media type.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c509.
config 3C515
@@ -684,8 +678,7 @@ config 3C515
network card, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c515.
config ELMC
@@ -696,8 +689,7 @@ config ELMC
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c523.
config ELMC_II
@@ -708,8 +700,7 @@ config ELMC_II
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c527.
config VORTEX
@@ -732,8 +723,7 @@ config VORTEX
<file:Documentation/networking/vortex.txt> and in the comments at
the beginning of <file:drivers/net/3c59x.c>.
- To compile this support as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>.
+ To compile this support as a module, choose M here.
config TYPHOON
tristate "3cr990 series \"Typhoon\" support"
@@ -750,8 +740,7 @@ config TYPHOON
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called typhoon.
config LANCE
@@ -788,8 +777,7 @@ config WD80x3
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called wd.
config ULTRAMCA
@@ -801,8 +789,7 @@ config ULTRAMCA
an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-mca.
config ULTRA
@@ -821,8 +808,7 @@ config ULTRA
this but keep it in mind if you have such a SCSI card and have
problems.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-ultra.
config ULTRA32
@@ -834,8 +820,7 @@ config ULTRA32
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-ultra32.
config BFIN_MAC
@@ -896,15 +881,14 @@ config SMC9194
<file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc9194.
config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
- depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
+ depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BLACKFIN
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -915,8 +899,7 @@ config SMC91X
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called smc91x. If you want to compile it as a
- module, say M here and read <file:Documentation/kbuild/modules.txt>
- as well as <file:Documentation/networking/net-modules.txt>.
+ module, say M here and read <file:Documentation/kbuild/modules.txt>.
config NET_NETX
tristate "NetX Ethernet support"
@@ -925,8 +908,7 @@ config NET_NETX
help
This is support for the Hilscher netX builtin Ethernet ports
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called netx-eth.
config DM9000
@@ -937,15 +919,14 @@ config DM9000
---help---
Support for DM9000 chipset.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called dm9000.
+ To compile this driver as a module, choose M here. The module
+ will be called dm9000.
config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
select MII
- depends on ARCH_PXA || SUPERH
+ depends on ARCH_PXA || SH_MAGIC_PANEL_R2
help
This is a driver for SMSC's LAN911x series of Ethernet chipsets
including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -979,8 +960,7 @@ config NI5010
<http://www.tldp.org/docs.html#howto>. Note that this is still
experimental code.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni5010.
config NI52
@@ -991,8 +971,7 @@ config NI52
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni52.
config NI65
@@ -1003,8 +982,7 @@ config NI65
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni65.
source "drivers/net/tulip/Kconfig"
@@ -1018,8 +996,7 @@ config AT1700
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called at1700.
config DEPCA
@@ -1032,8 +1009,7 @@ config DEPCA
<http://www.tldp.org/docs.html#howto> as well as
<file:drivers/net/depca.c>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called depca.
config HP100
@@ -1044,8 +1020,7 @@ config HP100
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp100.
config NET_ISA
@@ -1074,8 +1049,7 @@ config E2100
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e2100.
config EWRK3
@@ -1089,8 +1063,7 @@ config EWRK3
well as the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ewrk3.
config EEXPRESS
@@ -1104,8 +1077,7 @@ config EEXPRESS
because the driver was very unreliable. We now have a new driver
that should do better.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eexpress.
config EEXPRESS_PRO
@@ -1118,8 +1090,7 @@ config EEXPRESS_PRO
driver. Please read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eepro.
config HPLAN_PLUS
@@ -1131,8 +1102,7 @@ config HPLAN_PLUS
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp-plus.
config HPLAN
@@ -1144,8 +1114,7 @@ config HPLAN
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp.
config LP486E
@@ -1164,8 +1133,7 @@ config ETH16I
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eth16i.
config NE2000
@@ -1185,8 +1153,7 @@ config NE2000
laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
below.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne.
config ZNET
@@ -1207,8 +1174,7 @@ config SEEQ8005
is for you, read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called seeq8005.
config NE2_MCA
@@ -1220,8 +1186,7 @@ config NE2_MCA
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne2.
config IBMLANA
@@ -1232,8 +1197,7 @@ config IBMLANA
CONFIG_MCA to use this driver. It is both available as an in-kernel
driver and as a module.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The only
+ To compile this driver as a module, choose M here. The only
currently supported card is the IBM LAN Adapter/A for Ethernet. It
will both support 16K and 32K memory windows, however a 32K window
gives a better security against packet losses. Usage of multiple
@@ -1247,8 +1211,7 @@ config IBMVETH
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called ibmveth.
source "drivers/net/ibm_emac/Kconfig"
@@ -1278,8 +1241,7 @@ config PCNET32
answer Y here and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called pcnet32.
config PCNET32_NAPI
@@ -1306,8 +1268,7 @@ config AMD8111_ETH
answer Y here and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called amd8111e.
config AMD8111E_NAPI
@@ -1361,8 +1322,7 @@ config AC3200
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ac3200.
config APRICOT
@@ -1373,9 +1333,8 @@ config APRICOT
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called apricot.
+ To compile this driver as a module, choose M here. The module
+ will be called apricot.
config B44
tristate "Broadcom 440x/47xx ethernet support"
@@ -1387,9 +1346,8 @@ config B44
or M and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called b44.
+ To compile this driver as a module, choose M here. The module
+ will be called b44.
# Auto-select SSB PCI-HOST support, if possible
config B44_PCI_AUTOSELECT
@@ -1418,9 +1376,8 @@ config FORCEDETH
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called forcedeth.
+ To compile this driver as a module, choose M here. The module
+ will be called forcedeth.
config FORCEDETH_NAPI
bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
@@ -1446,9 +1403,8 @@ config CS89x0
<http://www.tldp.org/docs.html#howto> as well as
<file:Documentation/networking/cs89x0.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called cs89x0.
+ To compile this driver as a module, choose M here. The module
+ will be called cs89x0.
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
@@ -1464,8 +1420,7 @@ config EEPRO100
card, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eepro100.
@@ -1492,8 +1447,7 @@ config E100
More specific information on configuring the driver is in
<file:Documentation/networking/e100.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e100.
config LNE390
@@ -1505,8 +1459,7 @@ config LNE390
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called lne390.
config FEALNX
@@ -1546,8 +1499,7 @@ config NE2K_PCI
NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
Holtek HT80232 Holtek HT80229
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne2k-pci.
config NE3210
@@ -1560,8 +1512,7 @@ config NE3210
<http://www.tldp.org/docs.html#howto>. Note that this driver
will NOT WORK for NE3200 cards as they are completely different.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne3210.
config ES3210
@@ -1573,8 +1524,7 @@ config ES3210
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called es3210.
config 8139CP
@@ -1704,8 +1654,7 @@ config TLAN
Compaq NetFlex and Olicom cards. Please read the file
<file:Documentation/networking/tlan.txt> for more details.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called tlan.
Please email feedback to <torben.mathiasen@compaq.com>.
@@ -1995,8 +1944,7 @@ config E1000
More specific information on configuring the driver is in
<file:Documentation/networking/e1000.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e1000.
config E1000_NAPI
@@ -2041,8 +1989,7 @@ config E1000E
More specific information on configuring the driver is in
<file:Documentation/networking/e1000e.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e1000e.
source "drivers/net/ixp2000/Kconfig"
@@ -2075,8 +2022,7 @@ config HAMACHI
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
+ To compile this driver as a module, choose M here. The module will be
called hamachi.
config YELLOWFIN
@@ -2525,8 +2471,7 @@ config IXGBE
More specific information on configuring the driver is in
<file:Documentation/networking/ixgbe.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ixgbe.
config IXGB
@@ -2548,8 +2493,7 @@ config IXGB
More specific information on configuring the driver is in
<file:Documentation/networking/ixgb.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ixgb.
config IXGB_NAPI
@@ -2602,8 +2546,7 @@ config MYRI10GE
<http://www.myri.com/scs/download-Myri10GE.html>
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called myri10ge.
config NETXEN_NIC
@@ -2827,10 +2770,9 @@ config PLIP
with the PLIP support in Linux versions 1.0.x. This option enlarges
your kernel by about 8 KB.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called plip. If unsure, say Y or M, in case you buy a laptop
- later.
+ To compile this driver as a module, choose M here. The module
+ will be called plip. If unsure, say Y or M, in case you buy
+ a laptop later.
config PPP
tristate "PPP (point-to-point protocol) support"
@@ -2860,8 +2802,7 @@ config PPP
If you said Y to "Version information on all symbols" above, then
you cannot compile the PPP driver into the kernel; you can then only
compile it as a module. To compile this driver as a module, choose M
- here and read <file:Documentation/networking/net-modules.txt>.
- The module will be called ppp_generic.
+ here. The module will be called ppp_generic.
config PPP_MULTILINK
bool "PPP multilink support (EXPERIMENTAL)"
@@ -3022,9 +2963,8 @@ config SLIP
<http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
support will enlarge your kernel by about 4 KB. If unsure, say N.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called slip.
+ To compile this driver as a module, choose M here. The module
+ will be called slip.
config SLIP_COMPRESSED
bool "CSLIP compressed headers"
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index eebf5bb2b03..e7fdd81919b 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1340,7 +1340,9 @@ static int amd8111e_close(struct net_device * dev)
struct amd8111e_priv *lp = netdev_priv(dev);
netif_stop_queue(dev);
+#ifdef CONFIG_AMD8111E_NAPI
napi_disable(&lp->napi);
+#endif
spin_lock_irq(&lp->lock);
@@ -1372,7 +1374,9 @@ static int amd8111e_open(struct net_device * dev )
dev->name, dev))
return -EAGAIN;
+#ifdef CONFIG_AMD8111E_NAPI
napi_enable(&lp->napi);
+#endif
spin_lock_irq(&lp->lock);
@@ -1380,7 +1384,9 @@ static int amd8111e_open(struct net_device * dev )
if(amd8111e_restart(dev)){
spin_unlock_irq(&lp->lock);
+#ifdef CONFIG_AMD8111E_NAPI
napi_disable(&lp->napi);
+#endif
if (dev->irq)
free_irq(dev->irq, dev);
return -ENOMEM;
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 4030274fe78..3b2f7f11546 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -19,8 +19,7 @@ menuconfig ARCNET
from <http://www.tldp.org/docs.html#howto>(even though ARCnet
is not really Ethernet).
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called arcnet.
if ARCNET
@@ -81,8 +80,7 @@ config ARCNET_COM90xx
have always used the old ARCnet driver without knowing what type of
card you had, this is probably the one for you.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com90xx.
config ARCNET_COM90xxIO
@@ -93,8 +91,7 @@ config ARCNET_COM90xxIO
the normal driver. Only use it if your card doesn't support shared
memory.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com90io.
config ARCNET_RIM_I
@@ -105,8 +102,7 @@ config ARCNET_RIM_I
driver is completely untested, so if you have one of these cards,
please mail <dwmw2@infradead.org>, especially if it works!
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called arc-rimi.
config ARCNET_COM20020
@@ -116,8 +112,7 @@ config ARCNET_COM20020
things as promiscuous mode, so packet sniffing is possible, and
extra diagnostic information.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com20020.
config ARCNET_COM20020_ISA
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 7f016f3d5bf..91a6590d107 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -417,7 +417,7 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)
if (status & REG_INTSTS_RX) {
spin_lock(&ep->rx_lock);
- if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) {
+ if (likely(netif_rx_schedule_prep(dev, &ep->napi))) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
__netif_rx_schedule(dev, &ep->napi);
}
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 084acfd6fc5..eb971755a3f 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -676,7 +676,7 @@ static void bf537mac_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb, dev);
#if defined(BFIN_MAC_CSUM_OFFLOAD)
skb->csum = current_rx_ptr->status.ip_payload_csum;
- skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->ip_summed = CHECKSUM_COMPLETE;
#endif
netif_rx(skb);
@@ -924,7 +924,7 @@ static int __init bf537mac_probe(struct net_device *dev)
if (!is_valid_ether_addr(dev->dev_addr)) {
/* Grab the MAC from the board somehow - this is done in the
arch/blackfin/mach-bf537/boards/eth_mac.c */
- get_bf537_ether_addr(dev->dev_addr);
+ bfin_get_ether_addr(dev->dev_addr);
}
/* If still not valid, get a random one */
diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h
index 3a107ad7538..5970ea7142c 100644
--- a/drivers/net/bfin_mac.h
+++ b/drivers/net/bfin_mac.h
@@ -92,4 +92,4 @@ struct bf537mac_local {
struct mii_bus mii_bus;
};
-extern void get_bf537_ether_addr(char *addr);
+extern void bfin_get_ether_addr(char *addr);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6937ef0e727..423298c84a1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1847,9 +1847,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
*/
void bond_destroy(struct bonding *bond)
{
- unregister_netdevice(bond->dev);
bond_deinit(bond->dev);
bond_destroy_sysfs_entry(bond);
+ unregister_netdevice(bond->dev);
}
/*
@@ -4405,6 +4405,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond_dev->set_multicast_list = bond_set_multicast_list;
bond_dev->change_mtu = bond_change_mtu;
bond_dev->set_mac_address = bond_set_mac_address;
+ bond_dev->validate_addr = NULL;
bond_set_mode_ops(bond, bond->params.mode);
@@ -4474,8 +4475,8 @@ static void bond_free_all(void)
bond_mc_list_destroy(bond);
/* Release the bonded slaves */
bond_release_all(bond_dev);
- unregister_netdevice(bond_dev);
bond_deinit(bond_dev);
+ unregister_netdevice(bond_dev);
}
#ifdef CONFIG_PROC_FS
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 7a06ade85b0..b29330d8e30 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1193,8 +1193,6 @@ static ssize_t bonding_show_active_slave(struct device *d,
struct bonding *bond = to_bond(d);
int count;
- rtnl_lock();
-
read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
@@ -1216,7 +1214,9 @@ static ssize_t bonding_store_active_slave(struct device *d,
struct slave *new_active = NULL;
struct bonding *bond = to_bond(d);
+ rtnl_lock();
write_lock_bh(&bond->lock);
+
if (!USES_PRIMARY(bond->params.mode)) {
printk(KERN_INFO DRV_NAME
": %s: Unable to change active slave; %s is in mode %d\n",
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 2dbf8dc116c..c5975047c89 100644..100755
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -374,7 +374,9 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
"TxInternalMACXmitError",
"TxFramesWithExcessiveDeferral",
"TxFCSErrors",
-
+ "TxJumboFramesOk",
+ "TxJumboOctetsOk",
+
"RxOctetsOK",
"RxOctetsBad",
"RxUnicastFramesOK",
@@ -392,16 +394,17 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
"RxInRangeLengthErrors",
"RxOutOfRangeLengthField",
"RxFrameTooLongErrors",
+ "RxJumboFramesOk",
+ "RxJumboOctetsOk",
/* Port stats */
- "RxPackets",
"RxCsumGood",
- "TxPackets",
"TxCsumOffload",
"TxTso",
"RxVlan",
"TxVlan",
-
+ "TxNeedHeadroom",
+
/* Interrupt stats */
"rx drops",
"pure_rsps",
@@ -463,23 +466,56 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
const struct cmac_statistics *s;
const struct sge_intr_counts *t;
struct sge_port_stats ss;
- unsigned int len;
s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
-
- len = sizeof(u64)*(&s->TxFCSErrors + 1 - &s->TxOctetsOK);
- memcpy(data, &s->TxOctetsOK, len);
- data += len;
-
- len = sizeof(u64)*(&s->RxFrameTooLongErrors + 1 - &s->RxOctetsOK);
- memcpy(data, &s->RxOctetsOK, len);
- data += len;
-
+ t = t1_sge_get_intr_counts(adapter->sge);
t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss);
- memcpy(data, &ss, sizeof(ss));
- data += sizeof(ss);
- t = t1_sge_get_intr_counts(adapter->sge);
+ *data++ = s->TxOctetsOK;
+ *data++ = s->TxOctetsBad;
+ *data++ = s->TxUnicastFramesOK;
+ *data++ = s->TxMulticastFramesOK;
+ *data++ = s->TxBroadcastFramesOK;
+ *data++ = s->TxPauseFrames;
+ *data++ = s->TxFramesWithDeferredXmissions;
+ *data++ = s->TxLateCollisions;
+ *data++ = s->TxTotalCollisions;
+ *data++ = s->TxFramesAbortedDueToXSCollisions;
+ *data++ = s->TxUnderrun;
+ *data++ = s->TxLengthErrors;
+ *data++ = s->TxInternalMACXmitError;
+ *data++ = s->TxFramesWithExcessiveDeferral;
+ *data++ = s->TxFCSErrors;
+ *data++ = s->TxJumboFramesOK;
+ *data++ = s->TxJumboOctetsOK;
+
+ *data++ = s->RxOctetsOK;
+ *data++ = s->RxOctetsBad;
+ *data++ = s->RxUnicastFramesOK;
+ *data++ = s->RxMulticastFramesOK;
+ *data++ = s->RxBroadcastFramesOK;
+ *data++ = s->RxPauseFrames;
+ *data++ = s->RxFCSErrors;
+ *data++ = s->RxAlignErrors;
+ *data++ = s->RxSymbolErrors;
+ *data++ = s->RxDataErrors;
+ *data++ = s->RxSequenceErrors;
+ *data++ = s->RxRuntErrors;
+ *data++ = s->RxJabberErrors;
+ *data++ = s->RxInternalMACRcvError;
+ *data++ = s->RxInRangeLengthErrors;
+ *data++ = s->RxOutOfRangeLengthField;
+ *data++ = s->RxFrameTooLongErrors;
+ *data++ = s->RxJumboFramesOK;
+ *data++ = s->RxJumboOctetsOK;
+
+ *data++ = ss.rx_cso_good;
+ *data++ = ss.tx_cso;
+ *data++ = ss.tx_tso;
+ *data++ = ss.vlan_xtract;
+ *data++ = ss.vlan_insert;
+ *data++ = ss.tx_need_hdrroom;
+
*data++ = t->rx_drops;
*data++ = t->pure_rsps;
*data++ = t->unhandled_irqs;
diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c
index 678778a8d13..2117c4fbb10 100644..100755
--- a/drivers/net/chelsio/pm3393.c
+++ b/drivers/net/chelsio/pm3393.c
@@ -45,7 +45,7 @@
#include <linux/crc32.h>
-#define OFFSET(REG_ADDR) (REG_ADDR << 2)
+#define OFFSET(REG_ADDR) ((REG_ADDR) << 2)
/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
#define MAX_FRAME_SIZE 9600
@@ -428,69 +428,26 @@ static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
return 0;
}
-static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val,
- int over)
-{
- u32 val0, val1, val2;
-
- t1_tpi_read(adapter, offs, &val0);
- t1_tpi_read(adapter, offs + 4, &val1);
- t1_tpi_read(adapter, offs + 8, &val2);
-
- *val &= ~0ull << 40;
- *val |= val0 & 0xffff;
- *val |= (val1 & 0xffff) << 16;
- *val |= (u64)(val2 & 0xff) << 32;
-
- if (over)
- *val += 1ull << 40;
+#define RMON_UPDATE(mac, name, stat_name) \
+{ \
+ t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
+ t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \
+ t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \
+ (mac)->stats.stat_name = (u64)(val0 & 0xffff) | \
+ ((u64)(val1 & 0xffff) << 16) | \
+ ((u64)(val2 & 0xff) << 32) | \
+ ((mac)->stats.stat_name & \
+ 0xffffff0000000000ULL); \
+ if (ro & \
+ (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \
+ (mac)->stats.stat_name += 1ULL << 40; \
}
static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
int flag)
{
- static struct {
- unsigned int reg;
- unsigned int offset;
- } hw_stats [] = {
-
-#define HW_STAT(name, stat_name) \
- { name, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
-
- /* Rx stats */
- HW_STAT(RxOctetsReceivedOK, RxOctetsOK),
- HW_STAT(RxUnicastFramesReceivedOK, RxUnicastFramesOK),
- HW_STAT(RxMulticastFramesReceivedOK, RxMulticastFramesOK),
- HW_STAT(RxBroadcastFramesReceivedOK, RxBroadcastFramesOK),
- HW_STAT(RxPAUSEMACCtrlFramesReceived, RxPauseFrames),
- HW_STAT(RxFrameCheckSequenceErrors, RxFCSErrors),
- HW_STAT(RxFramesLostDueToInternalMACErrors,
- RxInternalMACRcvError),
- HW_STAT(RxSymbolErrors, RxSymbolErrors),
- HW_STAT(RxInRangeLengthErrors, RxInRangeLengthErrors),
- HW_STAT(RxFramesTooLongErrors , RxFrameTooLongErrors),
- HW_STAT(RxJabbers, RxJabberErrors),
- HW_STAT(RxFragments, RxRuntErrors),
- HW_STAT(RxUndersizedFrames, RxRuntErrors),
- HW_STAT(RxJumboFramesReceivedOK, RxJumboFramesOK),
- HW_STAT(RxJumboOctetsReceivedOK, RxJumboOctetsOK),
-
- /* Tx stats */
- HW_STAT(TxOctetsTransmittedOK, TxOctetsOK),
- HW_STAT(TxFramesLostDueToInternalMACTransmissionError,
- TxInternalMACXmitError),
- HW_STAT(TxTransmitSystemError, TxFCSErrors),
- HW_STAT(TxUnicastFramesTransmittedOK, TxUnicastFramesOK),
- HW_STAT(TxMulticastFramesTransmittedOK, TxMulticastFramesOK),
- HW_STAT(TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK),
- HW_STAT(TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames),
- HW_STAT(TxJumboFramesReceivedOK, TxJumboFramesOK),
- HW_STAT(TxJumboOctetsReceivedOK, TxJumboOctetsOK)
- }, *p = hw_stats;
- u64 ro;
- u32 val0, val1, val2, val3;
- u64 *stats = (u64 *) &mac->stats;
- unsigned int i;
+ u64 ro;
+ u32 val0, val1, val2, val3;
/* Snap the counters */
pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
@@ -504,14 +461,35 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
(((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
- for (i = 0; i < ARRAY_SIZE(hw_stats); i++) {
- unsigned reg = p->reg - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW;
-
- pm3393_rmon_update((mac)->adapter, OFFSET(p->reg),
- stats + p->offset, ro & (reg >> 2));
- }
-
-
+ /* Rx stats */
+ RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
+ RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
+ RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
+ RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
+ RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
+ RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
+ RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
+ RxInternalMACRcvError);
+ RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
+ RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
+ RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
+ RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
+ RMON_UPDATE(mac, RxFragments, RxRuntErrors);
+ RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
+ RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
+ RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
+
+ /* Tx stats */
+ RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
+ RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
+ TxInternalMACXmitError);
+ RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
+ RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
+ RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
+ RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
+ RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
+ RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
+ RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
return &mac->stats;
}
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index ffa7e649a6e..b301c0428ae 100644..100755
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -986,11 +986,10 @@ void t1_sge_get_port_stats(const struct sge *sge, int port,
for_each_possible_cpu(cpu) {
struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu);
- ss->rx_packets += st->rx_packets;
ss->rx_cso_good += st->rx_cso_good;
- ss->tx_packets += st->tx_packets;
ss->tx_cso += st->tx_cso;
ss->tx_tso += st->tx_tso;
+ ss->tx_need_hdrroom += st->tx_need_hdrroom;
ss->vlan_xtract += st->vlan_xtract;
ss->vlan_insert += st->vlan_insert;
}
@@ -1379,11 +1378,10 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
}
__skb_pull(skb, sizeof(*p));
- skb->dev->last_rx = jiffies;
st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
- st->rx_packets++;
skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
+ skb->dev->last_rx = jiffies;
if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
skb->protocol == htons(ETH_P_IP) &&
(skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
@@ -1624,11 +1622,9 @@ int t1_poll(struct napi_struct *napi, int budget)
{
struct adapter *adapter = container_of(napi, struct adapter, napi);
struct net_device *dev = adapter->port[0].dev;
- int work_done;
-
- work_done = process_responses(adapter, budget);
+ int work_done = process_responses(adapter, budget);
- if (likely(!responses_pending(adapter))) {
+ if (likely(work_done < budget)) {
netif_rx_complete(dev, napi);
writel(adapter->sge->respQ.cidx,
adapter->regs + A_SG_SLEEPING);
@@ -1848,7 +1844,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct adapter *adapter = dev->priv;
struct sge *sge = adapter->sge;
- struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id());
+ struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port],
+ smp_processor_id());
struct cpl_tx_pkt *cpl;
struct sk_buff *orig_skb = skb;
int ret;
@@ -1856,6 +1853,18 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->protocol == htons(ETH_P_CPL5))
goto send;
+ /*
+ * We are using a non-standard hard_header_len.
+ * Allocate more header room in the rare cases it is not big enough.
+ */
+ if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
+ skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso));
+ ++st->tx_need_hdrroom;
+ dev_kfree_skb_any(orig_skb);
+ if (!skb)
+ return NETDEV_TX_OK;
+ }
+
if (skb_shinfo(skb)->gso_size) {
int eth_type;
struct cpl_tx_pkt_lso *hdr;
@@ -1889,24 +1898,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
- /*
- * We are using a non-standard hard_header_len and some kernel
- * components, such as pktgen, do not handle it right.
- * Complain when this happens but try to fix things up.
- */
- if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
- pr_debug("%s: headroom %d header_len %d\n", dev->name,
- skb_headroom(skb), dev->hard_header_len);
-
- if (net_ratelimit())
- printk(KERN_ERR "%s: inadequate headroom in "
- "Tx packet\n", dev->name);
- skb = skb_realloc_headroom(skb, sizeof(*cpl));
- dev_kfree_skb_any(orig_skb);
- if (!skb)
- return NETDEV_TX_OK;
- }
-
if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
skb->ip_summed == CHECKSUM_PARTIAL &&
ip_hdr(skb)->protocol == IPPROTO_UDP) {
@@ -1952,7 +1943,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
cpl->vlan_valid = 0;
send:
- st->tx_packets++;
dev->trans_start = jiffies;
ret = t1_sge_tx(skb, adapter, 0, dev);
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 713d9c55f24..cced9dff91c 100644..100755
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -57,13 +57,12 @@ struct sge_intr_counts {
};
struct sge_port_stats {
- u64 rx_packets; /* # of Ethernet packets received */
u64 rx_cso_good; /* # of successful RX csum offloads */
- u64 tx_packets; /* # of TX packets */
u64 tx_cso; /* # of TX checksum offloads */
u64 tx_tso; /* # of TSO requests */
u64 vlan_xtract; /* # of VLAN tag extractions */
u64 vlan_insert; /* # of VLAN tag insertions */
+ u64 tx_need_hdrroom; /* # of TX skbs in need of more header room */
};
struct sk_buff;
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index edd6828f0a7..917b7b46f1a 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -250,6 +250,7 @@
#include <asm/system.h>
#include <asm/ethernet.h>
#include <asm/cache.h>
+#include <asm/arch/io_interface_mux.h>
//#define ETHDEBUG
#define D(x)
@@ -279,6 +280,9 @@ struct net_local {
* by this lock as well.
*/
spinlock_t lock;
+
+ spinlock_t led_lock; /* Protect LED state */
+ spinlock_t transceiver_lock; /* Protect transceiver state. */
};
typedef struct etrax_eth_descr
@@ -295,8 +299,6 @@ struct transceiver_ops
void (*check_duplex)(struct net_device* dev);
};
-struct transceiver_ops* transceiver;
-
/* Duplex settings */
enum duplex
{
@@ -307,7 +309,7 @@ enum duplex
/* Dma descriptors etc. */
-#define MAX_MEDIA_DATA_SIZE 1518
+#define MAX_MEDIA_DATA_SIZE 1522
#define MIN_PACKET_LEN 46
#define ETHER_HEAD_LEN 14
@@ -332,8 +334,8 @@ enum duplex
/*Intel LXT972A specific*/
#define MDIO_INT_STATUS_REG_2 0x0011
-#define MDIO_INT_FULL_DUPLEX_IND ( 1 << 9 )
-#define MDIO_INT_SPEED ( 1 << 14 )
+#define MDIO_INT_FULL_DUPLEX_IND (1 << 9)
+#define MDIO_INT_SPEED (1 << 14)
/* Network flash constants */
#define NET_FLASH_TIME (HZ/50) /* 20 ms */
@@ -344,8 +346,8 @@ enum duplex
#define NO_NETWORK_ACTIVITY 0
#define NETWORK_ACTIVITY 1
-#define NBR_OF_RX_DESC 64
-#define NBR_OF_TX_DESC 256
+#define NBR_OF_RX_DESC 32
+#define NBR_OF_TX_DESC 16
/* Large packets are sent directly to upper layers while small packets are */
/* copied (to reduce memory waste). The following constant decides the breakpoint */
@@ -367,7 +369,6 @@ enum duplex
static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to
to be processed */
static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */
-static etrax_eth_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */
static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32)));
@@ -377,7 +378,6 @@ static etrax_eth_descr* myNextTxDesc; /* Next descriptor to use */
static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32)));
static unsigned int network_rec_config_shadow = 0;
-static unsigned int mdio_phy_addr; /* Transciever address */
static unsigned int network_tr_ctrl_shadow = 0;
@@ -411,7 +411,7 @@ static int e100_set_config(struct net_device* dev, struct ifmap* map);
static void e100_tx_timeout(struct net_device *dev);
static struct net_device_stats *e100_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
-static void e100_hardware_send_packet(char *buf, int length);
+static void e100_hardware_send_packet(struct net_local* np, char *buf, int length);
static void update_rx_stats(struct net_device_stats *);
static void update_tx_stats(struct net_device_stats *);
static int e100_probe_transceiver(struct net_device* dev);
@@ -434,7 +434,10 @@ static void e100_clear_network_leds(unsigned long dummy);
static void e100_set_network_leds(int active);
static const struct ethtool_ops e100_ethtool_ops;
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void dummy_check_speed(struct net_device* dev);
+static void dummy_check_duplex(struct net_device* dev);
+#else
static void broadcom_check_speed(struct net_device* dev);
static void broadcom_check_duplex(struct net_device* dev);
static void tdk_check_speed(struct net_device* dev);
@@ -443,16 +446,28 @@ static void intel_check_speed(struct net_device* dev);
static void intel_check_duplex(struct net_device* dev);
static void generic_check_speed(struct net_device* dev);
static void generic_check_duplex(struct net_device* dev);
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void e100_netpoll(struct net_device* dev);
+#endif
+
+static int autoneg_normal = 1;
struct transceiver_ops transceivers[] =
{
+#if defined(CONFIG_ETRAX_NO_PHY)
+ {0x0000, dummy_check_speed, dummy_check_duplex} /* Dummy */
+#else
{0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */
{0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */
{0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */
{0x04de, intel_check_speed, intel_check_duplex}, /* Intel LXT972A*/
{0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */
+#endif
};
+struct transceiver_ops* transceiver = &transceivers[0];
+
#define tx_done(dev) (*R_DMA_CH0_CMD == 0)
/*
@@ -471,14 +486,22 @@ etrax_ethernet_init(void)
int i, err;
printk(KERN_INFO
- "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n");
+ "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 1998-2007 Axis Communications AB\n");
- dev = alloc_etherdev(sizeof(struct net_local));
- np = dev->priv;
+ if (cris_request_io_interface(if_eth, cardname)) {
+ printk(KERN_CRIT "etrax_ethernet_init failed to get IO interface\n");
+ return -EBUSY;
+ }
+ dev = alloc_etherdev(sizeof(struct net_local));
if (!dev)
return -ENOMEM;
+ np = netdev_priv(dev);
+
+ /* we do our own locking */
+ dev->features |= NETIF_F_LLTX;
+
dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
/* now setup our etrax specific stuff */
@@ -498,14 +521,22 @@ etrax_ethernet_init(void)
dev->do_ioctl = e100_ioctl;
dev->set_config = e100_set_config;
dev->tx_timeout = e100_tx_timeout;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = e100_netpoll;
+#endif
+
+ spin_lock_init(&np->lock);
+ spin_lock_init(&np->led_lock);
+ spin_lock_init(&np->transceiver_lock);
/* Initialise the list of Etrax DMA-descriptors */
/* Initialise receive descriptors */
for (i = 0; i < NBR_OF_RX_DESC; i++) {
- /* Allocate two extra cachelines to make sure that buffer used by DMA
- * does not share cacheline with any other data (to avoid cache bug)
+ /* Allocate two extra cachelines to make sure that buffer used
+ * by DMA does not share cacheline with any other data (to
+ * avoid cache bug)
*/
RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
if (!RxDescList[i].skb)
@@ -541,7 +572,6 @@ etrax_ethernet_init(void)
myNextRxDesc = &RxDescList[0];
myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
myFirstTxDesc = &TxDescList[0];
myNextTxDesc = &TxDescList[0];
myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1];
@@ -562,10 +592,11 @@ etrax_ethernet_init(void)
current_speed = 10;
current_speed_selection = 0; /* Auto */
speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
- duplex_timer.data = (unsigned long)dev;
+ speed_timer.data = (unsigned long)dev;
speed_timer.function = e100_check_speed;
clear_led_timer.function = e100_clear_network_leds;
+ clear_led_timer.data = (unsigned long)dev;
full_duplex = 0;
current_duplex = autoneg;
@@ -574,7 +605,6 @@ etrax_ethernet_init(void)
duplex_timer.function = e100_check_duplex;
/* Initialize mii interface */
- np->mii_if.phy_id = mdio_phy_addr;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
np->mii_if.dev = dev;
@@ -585,6 +615,9 @@ etrax_ethernet_init(void)
/* unwanted addresses are matched */
*R_NETWORK_GA_0 = 0x00000000;
*R_NETWORK_GA_1 = 0x00000000;
+
+ /* Initialize next time the led can flash */
+ led_next_time = jiffies;
return 0;
}
@@ -595,9 +628,9 @@ etrax_ethernet_init(void)
static int
e100_set_mac_address(struct net_device *dev, void *p)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
struct sockaddr *addr = p;
- int i;
+ DECLARE_MAC_BUF(mac);
spin_lock(&np->lock); /* preemption protection */
@@ -686,6 +719,25 @@ e100_open(struct net_device *dev)
goto grace_exit2;
}
+ /*
+ * Always allocate the DMA channels after the IRQ,
+ * and clean up on failure.
+ */
+
+ if (cris_request_dma(NETWORK_TX_DMA_NBR,
+ cardname,
+ DMA_VERBOSE_ON_ERROR,
+ dma_eth)) {
+ goto grace_exit3;
+ }
+
+ if (cris_request_dma(NETWORK_RX_DMA_NBR,
+ cardname,
+ DMA_VERBOSE_ON_ERROR,
+ dma_eth)) {
+ goto grace_exit4;
+ }
+
/* give the HW an idea of what MAC address we want */
*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |
@@ -700,6 +752,7 @@ e100_open(struct net_device *dev)
*R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */
#else
+ SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, max_size, size1522);
SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive);
SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable);
SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex);
@@ -719,8 +772,7 @@ e100_open(struct net_device *dev)
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable);
*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* enable the irq's for ethernet DMA */
@@ -752,12 +804,13 @@ e100_open(struct net_device *dev)
*R_DMA_CH0_FIRST = 0;
*R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc);
+ netif_start_queue(dev);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Probe for transceiver */
if (e100_probe_transceiver(dev))
- goto grace_exit3;
+ goto grace_exit5;
/* Start duplex/speed timers */
add_timer(&speed_timer);
@@ -766,10 +819,14 @@ e100_open(struct net_device *dev)
/* We are now ready to accept transmit requeusts from
* the queueing layer of the networking.
*/
- netif_start_queue(dev);
+ netif_carrier_on(dev);
return 0;
+grace_exit5:
+ cris_free_dma(NETWORK_RX_DMA_NBR, cardname);
+grace_exit4:
+ cris_free_dma(NETWORK_TX_DMA_NBR, cardname);
grace_exit3:
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
grace_exit2:
@@ -780,12 +837,20 @@ grace_exit0:
return -EAGAIN;
}
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void
+dummy_check_speed(struct net_device* dev)
+{
+ current_speed = 100;
+}
+#else
static void
generic_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE);
if ((data & ADVERTISE_100FULL) ||
(data & ADVERTISE_100HALF))
current_speed = 100;
@@ -797,7 +862,10 @@ static void
tdk_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_TDK_DIAGNOSTIC_REG);
current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10);
}
@@ -805,7 +873,10 @@ static void
broadcom_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_AUX_CTRL_STATUS_REG);
current_speed = (data & MDIO_BC_SPEED ? 100 : 10);
}
@@ -813,46 +884,62 @@ static void
intel_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_INT_STATUS_REG_2);
current_speed = (data & MDIO_INT_SPEED ? 100 : 10);
}
-
+#endif
static void
e100_check_speed(unsigned long priv)
{
struct net_device* dev = (struct net_device*)priv;
+ struct net_local *np = netdev_priv(dev);
static int led_initiated = 0;
unsigned long data;
int old_speed = current_speed;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR);
+ spin_lock(&np->transceiver_lock);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMSR);
if (!(data & BMSR_LSTATUS)) {
current_speed = 0;
} else {
transceiver->check_speed(dev);
}
+ spin_lock(&np->led_lock);
if ((old_speed != current_speed) || !led_initiated) {
led_initiated = 1;
e100_set_network_leds(NO_NETWORK_ACTIVITY);
+ if (current_speed)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
}
+ spin_unlock(&np->led_lock);
/* Reinitialize the timer. */
speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
add_timer(&speed_timer);
+
+ spin_unlock(&np->transceiver_lock);
}
static void
e100_negotiate(struct net_device* dev)
{
- unsigned short data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+ unsigned short data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MII_ADVERTISE);
/* Discard old speed and duplex settings */
data &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL |
ADVERTISE_10HALF | ADVERTISE_10FULL);
switch (current_speed_selection) {
- case 10 :
+ case 10:
if (current_duplex == full)
data |= ADVERTISE_10FULL;
else if (current_duplex == half)
@@ -861,7 +948,7 @@ e100_negotiate(struct net_device* dev)
data |= ADVERTISE_10HALF | ADVERTISE_10FULL;
break;
- case 100 :
+ case 100:
if (current_duplex == full)
data |= ADVERTISE_100FULL;
else if (current_duplex == half)
@@ -870,7 +957,7 @@ e100_negotiate(struct net_device* dev)
data |= ADVERTISE_100HALF | ADVERTISE_100FULL;
break;
- case 0 : /* Auto */
+ case 0: /* Auto */
if (current_duplex == full)
data |= ADVERTISE_100FULL | ADVERTISE_10FULL;
else if (current_duplex == half)
@@ -880,35 +967,44 @@ e100_negotiate(struct net_device* dev)
ADVERTISE_100HALF | ADVERTISE_100FULL;
break;
- default : /* assume autoneg speed and duplex */
+ default: /* assume autoneg speed and duplex */
data |= ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL;
+ break;
}
- e100_set_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE, data);
+ e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE, data);
/* Renegotiate with link partner */
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR);
+ if (autoneg_normal) {
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR);
data |= BMCR_ANENABLE | BMCR_ANRESTART;
-
- e100_set_mdio_reg(dev, mdio_phy_addr, MII_BMCR, data);
+ }
+ e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR, data);
}
static void
e100_set_speed(struct net_device* dev, unsigned long speed)
{
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
if (speed != current_speed_selection) {
current_speed_selection = speed;
e100_negotiate(dev);
}
+ spin_unlock(&np->transceiver_lock);
}
static void
e100_check_duplex(unsigned long priv)
{
struct net_device *dev = (struct net_device *)priv;
- struct net_local *np = (struct net_local *)dev->priv;
- int old_duplex = full_duplex;
+ struct net_local *np = netdev_priv(dev);
+ int old_duplex;
+
+ spin_lock(&np->transceiver_lock);
+ old_duplex = full_duplex;
transceiver->check_duplex(dev);
if (old_duplex != full_duplex) {
/* Duplex changed */
@@ -920,13 +1016,22 @@ e100_check_duplex(unsigned long priv)
duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL;
add_timer(&duplex_timer);
np->mii_if.full_duplex = full_duplex;
+ spin_unlock(&np->transceiver_lock);
}
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void
+dummy_check_duplex(struct net_device* dev)
+{
+ full_duplex = 1;
+}
+#else
static void
generic_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE);
if ((data & ADVERTISE_10FULL) ||
(data & ADVERTISE_100FULL))
full_duplex = 1;
@@ -938,7 +1043,10 @@ static void
tdk_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_TDK_DIAGNOSTIC_REG);
full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0;
}
@@ -946,7 +1054,10 @@ static void
broadcom_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_AUX_CTRL_STATUS_REG);
full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0;
}
@@ -954,38 +1065,55 @@ static void
intel_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_INT_STATUS_REG_2);
full_duplex = (data & MDIO_INT_FULL_DUPLEX_IND) ? 1 : 0;
}
-
+#endif
static void
e100_set_duplex(struct net_device* dev, enum duplex new_duplex)
{
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
if (new_duplex != current_duplex) {
current_duplex = new_duplex;
e100_negotiate(dev);
}
+ spin_unlock(&np->transceiver_lock);
}
static int
e100_probe_transceiver(struct net_device* dev)
{
+ int ret = 0;
+
+#if !defined(CONFIG_ETRAX_NO_PHY)
unsigned int phyid_high;
unsigned int phyid_low;
unsigned int oui;
struct transceiver_ops* ops = NULL;
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
/* Probe MDIO physical address */
- for (mdio_phy_addr = 0; mdio_phy_addr <= 31; mdio_phy_addr++) {
- if (e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR) != 0xffff)
+ for (np->mii_if.phy_id = 0; np->mii_if.phy_id <= 31;
+ np->mii_if.phy_id++) {
+ if (e100_get_mdio_reg(dev,
+ np->mii_if.phy_id, MII_BMSR) != 0xffff)
break;
}
- if (mdio_phy_addr == 32)
- return -ENODEV;
+ if (np->mii_if.phy_id == 32) {
+ ret = -ENODEV;
+ goto out;
+ }
/* Get manufacturer */
- phyid_high = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID1);
- phyid_low = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID2);
+ phyid_high = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID1);
+ phyid_low = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID2);
oui = (phyid_high << 6) | (phyid_low >> 10);
for (ops = &transceivers[0]; ops->oui; ops++) {
@@ -993,8 +1121,10 @@ e100_probe_transceiver(struct net_device* dev)
break;
}
transceiver = ops;
-
- return 0;
+out:
+ spin_unlock(&np->transceiver_lock);
+#endif
+ return ret;
}
static int
@@ -1088,13 +1218,14 @@ e100_receive_mdio_bit()
static void
e100_reset_transceiver(struct net_device* dev)
{
+ struct net_local *np = netdev_priv(dev);
unsigned short cmd;
unsigned short data;
int bitCounter;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR);
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR);
- cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (MII_BMCR << 2);
+ cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (np->mii_if.phy_id << 7) | (MII_BMCR << 2);
e100_send_mdio_cmd(cmd, 1);
@@ -1112,7 +1243,7 @@ e100_reset_transceiver(struct net_device* dev)
static void
e100_tx_timeout(struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&np->lock, flags);
@@ -1134,8 +1265,7 @@ e100_tx_timeout(struct net_device *dev)
e100_reset_transceiver(dev);
/* and get rid of the packets that never got an interrupt */
- while (myFirstTxDesc != myNextTxDesc)
- {
+ while (myFirstTxDesc != myNextTxDesc) {
dev_kfree_skb(myFirstTxDesc->skb);
myFirstTxDesc->skb = 0;
myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
@@ -1161,7 +1291,7 @@ e100_tx_timeout(struct net_device *dev)
static int
e100_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned char *buf = skb->data;
unsigned long flags;
@@ -1174,7 +1304,7 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- e100_hardware_send_packet(buf, skb->len);
+ e100_hardware_send_packet(np, buf, skb->len);
myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next);
@@ -1197,13 +1327,15 @@ static irqreturn_t
e100rxtx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *np = (struct net_local *)dev->priv;
- unsigned long irqbits = *R_IRQ_MASK2_RD;
+ struct net_local *np = netdev_priv(dev);
+ unsigned long irqbits;
- /* Disable RX/TX IRQs to avoid reentrancy */
- *R_IRQ_MASK2_CLR =
- IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) |
- IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr);
+ /*
+ * Note that both rx and tx interrupts are blocked at this point,
+ * regardless of which got us here.
+ */
+
+ irqbits = *R_IRQ_MASK2_RD;
/* Handle received packets */
if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) {
@@ -1219,7 +1351,7 @@ e100rxtx_interrupt(int irq, void *dev_id)
* allocate a new buffer to put a packet in.
*/
e100_rx(dev);
- ((struct net_local *)dev->priv)->stats.rx_packets++;
+ np->stats.rx_packets++;
/* restart/continue on the channel, for safety */
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart);
/* clear dma channel 1 eop/descr irq bits */
@@ -1233,9 +1365,8 @@ e100rxtx_interrupt(int irq, void *dev_id)
}
/* Report any packets that have been sent */
- while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) &&
- myFirstTxDesc != myNextTxDesc)
- {
+ while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST &&
+ (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) {
np->stats.tx_bytes += myFirstTxDesc->skb->len;
np->stats.tx_packets++;
@@ -1244,19 +1375,15 @@ e100rxtx_interrupt(int irq, void *dev_id)
dev_kfree_skb_irq(myFirstTxDesc->skb);
myFirstTxDesc->skb = 0;
myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
+ /* Wake up queue. */
+ netif_wake_queue(dev);
}
if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {
- /* acknowledge the eop interrupt and wake up queue */
+ /* acknowledge the eop interrupt. */
*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
- netif_wake_queue(dev);
}
- /* Enable RX/TX IRQs again */
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);
-
return IRQ_HANDLED;
}
@@ -1264,7 +1391,7 @@ static irqreturn_t
e100nw_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned long irqbits = *R_IRQ_MASK0_RD;
/* check for underrun irq */
@@ -1286,7 +1413,6 @@ e100nw_interrupt(int irq, void *dev_id)
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr);
*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop);
- *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr);
np->stats.tx_errors++;
D(printk("ethernet excessive collisions!\n"));
}
@@ -1299,12 +1425,13 @@ e100_rx(struct net_device *dev)
{
struct sk_buff *skb;
int length = 0;
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned char *skb_data_ptr;
#ifdef ETHDEBUG
int i;
#endif
-
+ etrax_eth_descr *prevRxDesc; /* The descriptor right before myNextRxDesc */
+ spin_lock(&np->led_lock);
if (!led_active && time_after(jiffies, led_next_time)) {
/* light the network leds depending on the current speed. */
e100_set_network_leds(NETWORK_ACTIVITY);
@@ -1314,9 +1441,10 @@ e100_rx(struct net_device *dev)
led_active = 1;
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
+ spin_unlock(&np->led_lock);
length = myNextRxDesc->descr.hw_len - 4;
- ((struct net_local *)dev->priv)->stats.rx_bytes += length;
+ np->stats.rx_bytes += length;
#ifdef ETHDEBUG
printk("Got a packet of length %d:\n", length);
@@ -1336,7 +1464,7 @@ e100_rx(struct net_device *dev)
if (!skb) {
np->stats.rx_errors++;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- return;
+ goto update_nextrxdesc;
}
skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */
@@ -1354,15 +1482,15 @@ e100_rx(struct net_device *dev)
else {
/* Large packet, send directly to upper layers and allocate new
* memory (aligned to cache line boundary to avoid bug).
- * Before sending the skb to upper layers we must make sure that
- * skb->data points to the aligned start of the packet.
+ * Before sending the skb to upper layers we must make sure
+ * that skb->data points to the aligned start of the packet.
*/
int align;
struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
if (!new_skb) {
np->stats.rx_errors++;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- return;
+ goto update_nextrxdesc;
}
skb = myNextRxDesc->skb;
align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data;
@@ -1377,9 +1505,10 @@ e100_rx(struct net_device *dev)
/* Send the packet to the upper layers */
netif_rx(skb);
+ update_nextrxdesc:
/* Prepare for next packet */
myNextRxDesc->descr.status = 0;
- myPrevRxDesc = myNextRxDesc;
+ prevRxDesc = myNextRxDesc;
myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next);
rx_queue_len++;
@@ -1387,9 +1516,9 @@ e100_rx(struct net_device *dev)
/* Check if descriptors should be returned */
if (rx_queue_len == RX_QUEUE_THRESHOLD) {
flush_etrax_cache();
- myPrevRxDesc->descr.ctrl |= d_eol;
+ prevRxDesc->descr.ctrl |= d_eol;
myLastRxDesc->descr.ctrl &= ~d_eol;
- myLastRxDesc = myPrevRxDesc;
+ myLastRxDesc = prevRxDesc;
rx_queue_len = 0;
}
}
@@ -1398,7 +1527,7 @@ e100_rx(struct net_device *dev)
static int
e100_close(struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
printk(KERN_INFO "Closing %s.\n", dev->name);
@@ -1426,6 +1555,9 @@ e100_close(struct net_device *dev)
free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
+ cris_free_dma(NETWORK_TX_DMA_NBR, cardname);
+ cris_free_dma(NETWORK_RX_DMA_NBR, cardname);
+
/* Update the statistics here. */
update_rx_stats(&np->stats);
@@ -1443,18 +1575,11 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct mii_ioctl_data *data = if_mii(ifr);
struct net_local *np = netdev_priv(dev);
+ int rc = 0;
+ int old_autoneg;
spin_lock(&np->lock); /* Preempt protection */
switch (cmd) {
- case SIOCGMIIPHY: /* Get PHY address */
- data->phy_id = mdio_phy_addr;
- break;
- case SIOCGMIIREG: /* Read MII register */
- data->val_out = e100_get_mdio_reg(dev, mdio_phy_addr, data->reg_num);
- break;
- case SIOCSMIIREG: /* Write MII register */
- e100_set_mdio_reg(dev, mdio_phy_addr, data->reg_num, data->val_in);
- break;
/* The ioctls below should be considered obsolete but are */
/* still present for compatability with old scripts/apps */
case SET_ETH_SPEED_10: /* 10 Mbps */
@@ -1463,60 +1588,47 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SET_ETH_SPEED_100: /* 100 Mbps */
e100_set_speed(dev, 100);
break;
- case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */
+ case SET_ETH_SPEED_AUTO: /* Auto-negotiate speed */
e100_set_speed(dev, 0);
break;
- case SET_ETH_DUPLEX_HALF: /* Half duplex. */
+ case SET_ETH_DUPLEX_HALF: /* Half duplex */
e100_set_duplex(dev, half);
break;
- case SET_ETH_DUPLEX_FULL: /* Full duplex. */
+ case SET_ETH_DUPLEX_FULL: /* Full duplex */
e100_set_duplex(dev, full);
break;
- case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/
+ case SET_ETH_DUPLEX_AUTO: /* Auto-negotiate duplex */
e100_set_duplex(dev, autoneg);
break;
+ case SET_ETH_AUTONEG:
+ old_autoneg = autoneg_normal;
+ autoneg_normal = *(int*)data;
+ if (autoneg_normal != old_autoneg)
+ e100_negotiate(dev);
+ break;
default:
- return -EINVAL;
+ rc = generic_mii_ioctl(&np->mii_if, if_mii(ifr),
+ cmd, NULL);
+ break;
}
spin_unlock(&np->lock);
- return 0;
+ return rc;
}
-static int e100_set_settings(struct net_device *dev,
- struct ethtool_cmd *ecmd)
+static int e100_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
- ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
- SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
- ecmd->port = PORT_TP;
- ecmd->transceiver = XCVR_EXTERNAL;
- ecmd->phy_address = mdio_phy_addr;
- ecmd->speed = current_speed;
- ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
- ecmd->advertising = ADVERTISED_TP;
+ struct net_local *np = netdev_priv(dev);
+ int err;
- if (current_duplex == autoneg && current_speed_selection == 0)
- ecmd->advertising |= ADVERTISED_Autoneg;
- else {
- ecmd->advertising |=
- ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
- if (current_speed_selection == 10)
- ecmd->advertising &= ~(ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full);
- else if (current_speed_selection == 100)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full);
- if (current_duplex == half)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Full);
- else if (current_duplex == full)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Half |
- ADVERTISED_100baseT_Half);
- }
+ spin_lock_irq(&np->lock);
+ err = mii_ethtool_gset(&np->mii_if, cmd);
+ spin_unlock_irq(&np->lock);
- ecmd->autoneg = AUTONEG_ENABLE;
- return 0;
+ /* The PHY may support 1000baseT, but the Etrax100 does not. */
+ cmd->supported &= ~(SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full);
+ return err;
}
static int e100_set_settings(struct net_device *dev,
@@ -1560,7 +1672,8 @@ static const struct ethtool_ops e100_ethtool_ops = {
static int
e100_set_config(struct net_device *dev, struct ifmap *map)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
+
spin_lock(&np->lock); /* Preempt protection */
switch(map->port) {
@@ -1612,7 +1725,6 @@ update_tx_stats(struct net_device_stats *es)
es->collisions +=
IO_EXTRACT(R_TR_COUNTERS, single_col, r) +
IO_EXTRACT(R_TR_COUNTERS, multiple_col, r);
- es->tx_errors += IO_EXTRACT(R_TR_COUNTERS, deferred, r);
}
/*
@@ -1622,8 +1734,9 @@ update_tx_stats(struct net_device_stats *es)
static struct net_device_stats *
e100_get_stats(struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = netdev_priv(dev);
unsigned long flags;
+
spin_lock_irqsave(&lp->lock, flags);
update_rx_stats(&lp->stats);
@@ -1643,13 +1756,13 @@ e100_get_stats(struct net_device *dev)
static void
set_multicast_list(struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = netdev_priv(dev);
int num_addr = dev->mc_count;
unsigned long int lo_bits;
unsigned long int hi_bits;
+
spin_lock(&lp->lock);
- if (dev->flags & IFF_PROMISC)
- {
+ if (dev->flags & IFF_PROMISC) {
/* promiscuous mode */
lo_bits = 0xfffffffful;
hi_bits = 0xfffffffful;
@@ -1679,9 +1792,10 @@ set_multicast_list(struct net_device *dev)
struct dev_mc_list *dmi = dev->mc_list;
int i;
char *baddr;
+
lo_bits = 0x00000000ul;
hi_bits = 0x00000000ul;
- for (i=0; i<num_addr; i++) {
+ for (i = 0; i < num_addr; i++) {
/* Calculate the hash index for the GA registers */
hash_ix = 0;
@@ -1708,8 +1822,7 @@ set_multicast_list(struct net_device *dev)
if (hash_ix >= 32) {
hi_bits |= (1 << (hash_ix-32));
- }
- else {
+ } else {
lo_bits |= (1 << hash_ix);
}
dmi = dmi->next;
@@ -1724,10 +1837,11 @@ set_multicast_list(struct net_device *dev)
}
void
-e100_hardware_send_packet(char *buf, int length)
+e100_hardware_send_packet(struct net_local *np, char *buf, int length)
{
D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
+ spin_lock(&np->led_lock);
if (!led_active && time_after(jiffies, led_next_time)) {
/* light the network leds depending on the current speed. */
e100_set_network_leds(NETWORK_ACTIVITY);
@@ -1737,6 +1851,7 @@ e100_hardware_send_packet(char *buf, int length)
led_active = 1;
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
+ spin_unlock(&np->led_lock);
/* configure the tx dma descriptor */
myNextTxDesc->descr.sw_len = length;
@@ -1754,6 +1869,11 @@ e100_hardware_send_packet(char *buf, int length)
static void
e100_clear_network_leds(unsigned long dummy)
{
+ struct net_device *dev = (struct net_device *)dummy;
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->led_lock);
+
if (led_active && time_after(jiffies, led_next_time)) {
e100_set_network_leds(NO_NETWORK_ACTIVITY);
@@ -1761,6 +1881,8 @@ e100_clear_network_leds(unsigned long dummy)
led_next_time = jiffies + NET_FLASH_PAUSE;
led_active = 0;
}
+
+ spin_unlock(&np->led_lock);
}
static void
@@ -1781,19 +1903,25 @@ e100_set_network_leds(int active)
#else
LED_NETWORK_SET(LED_OFF);
#endif
- }
- else if (light_leds) {
+ } else if (light_leds) {
if (current_speed == 10) {
LED_NETWORK_SET(LED_ORANGE);
} else {
LED_NETWORK_SET(LED_GREEN);
}
- }
- else {
+ } else {
LED_NETWORK_SET(LED_OFF);
}
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+e100_netpoll(struct net_device* netdev)
+{
+ e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL);
+}
+#endif
+
static int
etrax_init_module(void)
{
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 72deff0d4d9..4f37506ad37 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3942,7 +3942,7 @@ e1000_clean(struct napi_struct *napi, int budget)
&work_done, budget);
/* If no Tx and not enough Rx work done, exit the polling mode */
- if ((!tx_cleaned && (work_done < budget)) ||
+ if ((!tx_cleaned && (work_done == 0)) ||
!netif_running(poll_dev)) {
quit_polling:
if (likely(adapter->itr_setting & 3))
@@ -4804,6 +4804,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
if (adapter->hw.media_type == e1000_media_type_copper) {
switch (data->reg_num) {
case PHY_CTRL:
@@ -4824,12 +4825,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
DUPLEX_HALF;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if (retval) {
- spin_unlock_irqrestore(
- &adapter->stats_lock,
- flags);
+ if (retval)
return retval;
- }
}
if (netif_running(adapter->netdev))
e1000_reinit_locked(adapter);
@@ -4838,11 +4835,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if (e1000_phy_reset(&adapter->hw)) {
- spin_unlock_irqrestore(
- &adapter->stats_lock, flags);
+ if (e1000_phy_reset(&adapter->hw))
return -EIO;
- }
break;
}
} else {
@@ -4857,7 +4851,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
}
}
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index f78e5bf7cb3..5f82a4647ee 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_0080"
+#define DRV_VERSION "EHEA_0083"
/* 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 f0319f1e8e0..869e1604b16 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -136,7 +136,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
struct ehea_port *port = netdev_priv(dev);
struct net_device_stats *stats = &port->stats;
struct hcp_ehea_port_cb2 *cb2;
- u64 hret, rx_packets;
+ u64 hret, rx_packets, tx_packets;
int i;
memset(stats, 0, sizeof(*stats));
@@ -162,7 +162,11 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
for (i = 0; i < port->num_def_qps; i++)
rx_packets += port->port_res[i].rx_packets;
- stats->tx_packets = cb2->txucp + cb2->txmcp + cb2->txbcp;
+ tx_packets = 0;
+ for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ tx_packets += port->port_res[i].tx_packets;
+
+ stats->tx_packets = tx_packets;
stats->multicast = cb2->rxmcp;
stats->rx_errors = cb2->rxuerr;
stats->rx_bytes = cb2->rxo;
@@ -406,11 +410,6 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
if (cqe->status & EHEA_CQE_STAT_ERR_CRC)
pr->p_stats.err_frame_crc++;
- if (netif_msg_rx_err(pr->port)) {
- ehea_error("CQE Error for QP %d", pr->qp->init_attr.qp_nr);
- ehea_dump(cqe, sizeof(*cqe), "CQE");
- }
-
if (rq == 2) {
*processed_rq2 += 1;
skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe);
@@ -422,7 +421,11 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
}
if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) {
- ehea_error("Critical receive error. Resetting port.");
+ if (netif_msg_rx_err(pr->port)) {
+ ehea_error("Critical receive error for QP %d. "
+ "Resetting port.", pr->qp->init_attr.qp_nr);
+ ehea_dump(cqe, sizeof(*cqe), "CQE");
+ }
schedule_work(&pr->port->reset_task);
return 1;
}
@@ -2000,6 +2003,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
ehea_post_swqe(pr->qp, swqe);
+ pr->tx_packets++;
if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
spin_lock_irqsave(&pr->netif_queue, flags);
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index 562de0ebdd8..bc62d389c16 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -145,8 +145,8 @@ struct ehea_rwqe {
#define EHEA_CQE_VLAN_TAG_XTRACT 0x0400
#define EHEA_CQE_TYPE_RQ 0x60
-#define EHEA_CQE_STAT_ERR_MASK 0x720F
-#define EHEA_CQE_STAT_FAT_ERR_MASK 0x1F
+#define EHEA_CQE_STAT_ERR_MASK 0x700F
+#define EHEA_CQE_STAT_FAT_ERR_MASK 0xF
#define EHEA_CQE_STAT_ERR_TCP 0x4000
#define EHEA_CQE_STAT_ERR_IP 0x2000
#define EHEA_CQE_STAT_ERR_CRC 0x1000
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index a8a0ee220da..bf5a7caa5b5 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -971,6 +971,8 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
mpc52xx_fec_reset_stats(ndev);
+ SET_NETDEV_DEV(ndev, &op->dev);
+
/* Register the new network device */
rv = register_netdev(ndev);
if (rv < 0)
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 92ce2e38f0d..a96583cceb5 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -5286,19 +5286,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) {
np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use);
- for (i = 0; i < 5000; i++) {
- msleep(1);
- if (nv_mgmt_acquire_sema(dev)) {
- /* management unit setup the phy already? */
- if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
- NVREG_XMITCTL_SYNC_PHY_INIT) {
- /* phy is inited by mgmt unit */
- phyinitialized = 1;
- dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
- } else {
- /* we need to init the phy */
- }
- break;
+ if (nv_mgmt_acquire_sema(dev)) {
+ /* management unit setup the phy already? */
+ if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
+ NVREG_XMITCTL_SYNC_PHY_INIT) {
+ /* phy is inited by mgmt unit */
+ phyinitialized = 1;
+ dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
+ } else {
+ /* we need to init the phy */
}
}
}
@@ -5613,6 +5609,22 @@ static struct pci_device_id pci_tbl[] = {
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
},
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+ },
{0,},
};
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 2765e49e07d..562ea68ed99 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -2,6 +2,7 @@ config FS_ENET
tristate "Freescale Ethernet Driver"
depends on CPM1 || CPM2
select MII
+ select PHYLIB
config FS_ENET_HAS_SCC
bool "Chip has an SCC usable for ethernet"
@@ -11,11 +12,19 @@ config FS_ENET_HAS_SCC
config FS_ENET_HAS_FCC
bool "Chip has an FCC usable for ethernet"
depends on FS_ENET && CPM2
- select MDIO_BITBANG
default y
config FS_ENET_HAS_FEC
bool "Chip has an FEC usable for ethernet"
depends on FS_ENET && CPM1
+ select FS_ENET_MDIO_FEC
default y
+config FS_ENET_MDIO_FEC
+ tristate "MDIO driver for FEC"
+ depends on FS_ENET && CPM1
+
+config FS_ENET_MDIO_FCC
+ tristate "MDIO driver for FCC"
+ depends on FS_ENET && CPM2
+ select MDIO_BITBANG
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index 02d4dc18ba6..1ffbe0756a0 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -4,7 +4,16 @@
obj-$(CONFIG_FS_ENET) += fs_enet.o
-obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
-obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
+fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o
+fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o
+fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o
-fs_enet-objs := fs_enet-main.o
+ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y)
+obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
+obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
+else
+fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
+fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
+endif
+
+fs_enet-objs := fs_enet-main.o $(fs_enet-m)
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index e0119f6a331..580cb4ab2af 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -762,26 +762,20 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
if (copy_from_user(&addr,
(void __user *) arg, AX25_ADDR_LEN)) {
- err = -EFAULT;
- break;
- }
+ err = -EFAULT;
+ break;
+ }
- netif_tx_lock_bh(dev);
- memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
- netif_tx_unlock_bh(dev);
+ netif_tx_lock_bh(dev);
+ memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
+ netif_tx_unlock_bh(dev);
- err = 0;
- break;
- }
-
- /* Allow stty to read, but not set, the serial port */
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, (struct file *) file, cmd, arg);
- break;
+ err = 0;
+ break;
+ }
default:
- err = -ENOIOCTLCMD;
+ err = tty_mode_ioctl(tty, file, cmd, arg);
}
sp_put(sp);
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 0de3aa2a2e4..eb0718b441b 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -642,9 +642,11 @@ static void emac_reset_work(struct work_struct *work)
DBG(dev, "reset_work" NL);
mutex_lock(&dev->link_lock);
- emac_netif_stop(dev);
- emac_full_tx_reset(dev);
- emac_netif_start(dev);
+ if (dev->opened) {
+ emac_netif_stop(dev);
+ emac_full_tx_reset(dev);
+ emac_netif_start(dev);
+ }
mutex_unlock(&dev->link_lock);
}
@@ -1063,10 +1065,9 @@ static int emac_open(struct net_device *ndev)
dev->rx_sg_skb = NULL;
mutex_lock(&dev->link_lock);
+ dev->opened = 1;
- /* XXX Start PHY polling now. Shouldn't wr do like sungem instead and
- * always poll the PHY even when the iface is down ? That would allow
- * things like laptop-net to work. --BenH
+ /* Start PHY polling now.
*/
if (dev->phy.address >= 0) {
int link_poll_interval;
@@ -1145,9 +1146,11 @@ static void emac_link_timer(struct work_struct *work)
int link_poll_interval;
mutex_lock(&dev->link_lock);
-
DBG2(dev, "link timer" NL);
+ if (!dev->opened)
+ goto bail;
+
if (dev->phy.def->ops->poll_link(&dev->phy)) {
if (!netif_carrier_ok(dev->ndev)) {
/* Get new link parameters */
@@ -1170,13 +1173,14 @@ static void emac_link_timer(struct work_struct *work)
link_poll_interval = PHY_POLL_LINK_OFF;
}
schedule_delayed_work(&dev->link_work, link_poll_interval);
-
+ bail:
mutex_unlock(&dev->link_lock);
}
static void emac_force_link_update(struct emac_instance *dev)
{
netif_carrier_off(dev->ndev);
+ smp_rmb();
if (dev->link_polling) {
cancel_rearming_delayed_work(&dev->link_work);
if (dev->link_polling)
@@ -1191,11 +1195,14 @@ static int emac_close(struct net_device *ndev)
DBG(dev, "close" NL);
- if (dev->phy.address >= 0)
+ if (dev->phy.address >= 0) {
+ dev->link_polling = 0;
cancel_rearming_delayed_work(&dev->link_work);
-
+ }
+ mutex_lock(&dev->link_lock);
emac_netif_stop(dev);
- flush_scheduled_work();
+ dev->opened = 0;
+ mutex_unlock(&dev->link_lock);
emac_rx_disable(dev);
emac_tx_disable(dev);
@@ -2756,6 +2763,8 @@ static int __devexit emac_remove(struct of_device *ofdev)
unregister_netdev(dev->ndev);
+ flush_scheduled_work();
+
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_detach(dev->tah_dev, dev->tah_port);
if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII))
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 4011803117c..a010b2463fd 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -258,6 +258,7 @@ struct emac_instance {
int stop_timeout; /* in us */
int no_mcast;
int mcast_pending;
+ int opened;
struct work_struct reset_work;
spinlock_t lock;
};
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 2c6f7be36e8..fc753d7f674 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -434,11 +434,6 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
IRDA_ASSERT(dev != NULL, return -1;);
switch (cmd) {
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
case IRTTY_IOCTDONGLE:
/* this call blocks for completion */
err = sirdev_set_dongle(dev, (IRDA_DONGLE) arg);
@@ -454,7 +449,7 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
err = -EFAULT;
break;
default:
- err = -ENOIOCTLCMD;
+ err = tty_mode_ioctl(tty, file, cmd, arg);
break;
}
return err;
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index 9a855e51214..b59f442bbf3 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -176,8 +176,8 @@ struct i596_reg {
struct i596_tbd {
unsigned short size;
unsigned short pad;
- dma_addr_t next;
- dma_addr_t data;
+ u32 next;
+ u32 data;
u32 cache_pad[5]; /* Total 32 bytes... */
};
@@ -195,12 +195,12 @@ struct i596_cmd {
struct i596_cmd *v_next; /* Address from CPUs viewpoint */
unsigned short status;
unsigned short command;
- dma_addr_t b_next; /* Address from i596 viewpoint */
+ u32 b_next; /* Address from i596 viewpoint */
};
struct tx_cmd {
struct i596_cmd cmd;
- dma_addr_t tbd;
+ u32 tbd;
unsigned short size;
unsigned short pad;
struct sk_buff *skb; /* So we can free it after tx */
@@ -237,8 +237,8 @@ struct cf_cmd {
struct i596_rfd {
unsigned short stat;
unsigned short cmd;
- dma_addr_t b_next; /* Address from i596 viewpoint */
- dma_addr_t rbd;
+ u32 b_next; /* Address from i596 viewpoint */
+ u32 rbd;
unsigned short count;
unsigned short size;
struct i596_rfd *v_next; /* Address from CPUs viewpoint */
@@ -249,18 +249,18 @@ struct i596_rfd {
};
struct i596_rbd {
- /* hardware data */
- unsigned short count;
- unsigned short zero1;
- dma_addr_t b_next;
- dma_addr_t b_data; /* Address from i596 viewpoint */
- unsigned short size;
- unsigned short zero2;
- /* driver data */
- struct sk_buff *skb;
- struct i596_rbd *v_next;
- dma_addr_t b_addr; /* This rbd addr from i596 view */
- unsigned char *v_data; /* Address from CPUs viewpoint */
+ /* hardware data */
+ unsigned short count;
+ unsigned short zero1;
+ u32 b_next;
+ u32 b_data; /* Address from i596 viewpoint */
+ unsigned short size;
+ unsigned short zero2;
+ /* driver data */
+ struct sk_buff *skb;
+ struct i596_rbd *v_next;
+ u32 b_addr; /* This rbd addr from i596 view */
+ unsigned char *v_data; /* Address from CPUs viewpoint */
/* Total 32 bytes... */
#ifdef __LP64__
u32 cache_pad[4];
@@ -275,8 +275,8 @@ struct i596_rbd {
struct i596_scb {
unsigned short status;
unsigned short command;
- dma_addr_t cmd;
- dma_addr_t rfd;
+ u32 cmd;
+ u32 rfd;
u32 crc_err;
u32 align_err;
u32 resource_err;
@@ -288,14 +288,14 @@ struct i596_scb {
};
struct i596_iscp {
- u32 stat;
- dma_addr_t scb;
+ u32 stat;
+ u32 scb;
};
struct i596_scp {
- u32 sysbus;
- u32 pad;
- dma_addr_t iscp;
+ u32 sysbus;
+ u32 pad;
+ u32 iscp;
};
struct i596_dma {
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 45f30a2974b..662b8d16803 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -284,7 +284,7 @@ static __net_exit void loopback_net_exit(struct net *net)
unregister_netdev(dev);
}
-static struct pernet_operations loopback_net_ops = {
+static struct pernet_operations __net_initdata loopback_net_ops = {
.init = loopback_net_init,
.exit = loopback_net_exit,
};
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index f8d63d39f59..b226e019bc8 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -171,9 +171,10 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
buf->u.direct.map);
else {
for (i = 0; i < buf->nbufs; ++i)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- buf->u.page_list[i].buf,
- buf->u.page_list[i].map);
+ if (buf->u.page_list[i].buf)
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+ buf->u.page_list[i].buf,
+ buf->u.page_list[i].map);
kfree(buf->u.page_list);
}
}
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index cc4b1be1821..fa24e659759 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -113,7 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
struct mlx4_cmd_mailbox *mailbox;
int ret = 0;
- if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
+ if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE ||
!op[cur_state][new_state])
return -EINVAL;
@@ -240,7 +240,7 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
- if (qp->qpn < dev->caps.sqp_start + 8)
+ if (qp->qpn >= dev->caps.sqp_start + 8)
mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
}
EXPORT_SYMBOL_GPL(mlx4_qp_free);
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 8d29319cc5c..656a260fc95 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -134,7 +134,7 @@ static int myri_do_handshake(struct myri_eth *mp)
myri_disable_irq(mp->lregs, cregs);
- while (tick++ <= 25) {
+ while (tick++ < 25) {
u32 softstate;
/* Wake it up. */
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index eb0aff787df..5267e031daa 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -128,8 +128,8 @@ netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
FIFO_PTR_FRAMELEN(len));
ndev->trans_start = jiffies;
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
netif_stop_queue(ndev);
spin_unlock_irq(&priv->lock);
@@ -155,7 +155,7 @@ static void netx_eth_receive(struct net_device *ndev)
if (unlikely(skb == NULL)) {
printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
ndev->name);
- dev->stats.rx_dropped++;
+ ndev->stats.rx_dropped++;
return;
}
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index ab4d309a858..09b4fde8d92 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -580,6 +580,16 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
+ pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
+
+ if (macrx & XCT_MACRX_CRC) {
+ /* CRC error flagged */
+ mac->netdev->stats.rx_errors++;
+ mac->netdev->stats.rx_crc_errors++;
+ dev_kfree_skb_irq(skb);
+ goto next;
+ }
+
if (len < 256) {
struct sk_buff *new_skb;
@@ -595,11 +605,10 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
} else
info->skb = NULL;
- pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
-
info->dma = 0;
- skb_put(skb, len);
+ /* Don't include CRC */
+ skb_put(skb, len-4);
if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -614,6 +623,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
skb->protocol = eth_type_trans(skb, mac->netdev);
netif_receive_skb(skb);
+next:
RX_RING(mac, n) = 0;
RX_RING(mac, n+1) = 0;
@@ -1126,7 +1136,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
int i, nfrags;
- dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD;
+ dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const unsigned char *nh = skb_network_header(skb);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 035fd41fb61..f0574073a2a 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -143,21 +143,29 @@ static int m88e1111_config_init(struct phy_device *phydev)
int err;
if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
- (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) {
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
int temp;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
- temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
- if (temp < 0)
- return temp;
+ temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
+ if (temp < 0)
+ return temp;
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
-
- err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
- if (err < 0)
- return err;
+ } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+ temp &= ~MII_M1111_TX_DELAY;
+ temp |= MII_M1111_RX_DELAY;
+ } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
+ temp &= ~MII_M1111_RX_DELAY;
+ temp |= MII_M1111_TX_DELAY;
}
+ err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
+ if (err < 0)
+ return err;
+
temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
if (temp < 0)
return temp;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 9bc11773705..7c9e6e34950 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -406,6 +406,9 @@ int phy_mii_ioctl(struct phy_device *phydev,
&& phydev->drv->config_init)
phydev->drv->config_init(phydev);
break;
+
+ default:
+ return -ENOTTY;
}
return 0;
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 5071fcd8a0b..57c98669984 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -663,7 +663,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl,
case PLIP_PK_DONE:
/* Inform the upper layer for the arrival of a packet. */
rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
- netif_rx(rcv->skb);
+ netif_rx_ni(rcv->skb);
dev->last_rx = jiffies;
dev->stats.rx_bytes += rcv->length.h;
dev->stats.rx_packets++;
@@ -1269,7 +1269,7 @@ static void plip_attach (struct parport *port)
nl = netdev_priv(dev);
nl->dev = dev;
- nl->pardev = parport_register_device(port, name, plip_preempt,
+ nl->pardev = parport_register_device(port, dev->name, plip_preempt,
plip_wakeup, plip_interrupt,
0, dev);
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 27f5b904f48..f023d5b67e6 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -160,7 +160,7 @@ ppp_asynctty_open(struct tty_struct *tty)
err = -ENOMEM;
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
- if (ap == 0)
+ if (!ap)
goto out;
/* initialize the asyncppp structure */
@@ -215,7 +215,7 @@ ppp_asynctty_close(struct tty_struct *tty)
ap = tty->disc_data;
tty->disc_data = NULL;
write_unlock_irq(&disc_data_lock);
- if (ap == 0)
+ if (!ap)
return;
/*
@@ -230,10 +230,10 @@ ppp_asynctty_close(struct tty_struct *tty)
tasklet_kill(&ap->tsk);
ppp_unregister_channel(&ap->chan);
- if (ap->rpkt != 0)
+ if (ap->rpkt)
kfree_skb(ap->rpkt);
skb_queue_purge(&ap->rqueue);
- if (ap->tpkt != 0)
+ if (ap->tpkt)
kfree_skb(ap->tpkt);
kfree(ap);
}
@@ -285,13 +285,13 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
int err, val;
int __user *p = (int __user *)arg;
- if (ap == 0)
+ if (!ap)
return -ENXIO;
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
@@ -301,7 +301,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
case PPPIOCGUNIT:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
@@ -309,16 +309,11 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
err = 0;
break;
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
case TCFLSH:
/* flush our buffers and the serial port's buffer */
if (arg == TCIOFLUSH || arg == TCOFLUSH)
ppp_async_flush_output(ap);
- err = n_tty_ioctl(tty, file, cmd, arg);
+ err = tty_perform_flush(tty, arg);
break;
case FIONREAD:
@@ -329,7 +324,8 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
- err = -ENOIOCTLCMD;
+ /* Try the various mode ioctls */
+ err = tty_mode_ioctl(tty, file, cmd, arg);
}
ap_put(ap);
@@ -354,7 +350,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
struct asyncppp *ap = ap_get(tty);
unsigned long flags;
- if (ap == 0)
+ if (!ap)
return;
spin_lock_irqsave(&ap->recv_lock, flags);
ppp_async_input(ap, buf, cflags, count);
@@ -373,7 +369,7 @@ ppp_asynctty_wakeup(struct tty_struct *tty)
struct asyncppp *ap = ap_get(tty);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- if (ap == 0)
+ if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
@@ -688,7 +684,7 @@ ppp_async_push(struct asyncppp *ap)
tty_stuffed = 1;
continue;
}
- if (ap->optr >= ap->olim && ap->tpkt != 0) {
+ if (ap->optr >= ap->olim && ap->tpkt) {
if (ppp_async_encode(ap)) {
/* finished processing ap->tpkt */
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -708,7 +704,7 @@ ppp_async_push(struct asyncppp *ap)
clear_bit(XMIT_BUSY, &ap->xmit_flags);
/* any more work to do? if not, exit the loop */
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
- || (!tty_stuffed && ap->tpkt != 0)))
+ || (!tty_stuffed && ap->tpkt)))
break;
/* more work to do, see if we can do it now */
if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
@@ -719,7 +715,7 @@ ppp_async_push(struct asyncppp *ap)
flush:
clear_bit(XMIT_BUSY, &ap->xmit_flags);
- if (ap->tpkt != 0) {
+ if (ap->tpkt) {
kfree_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -852,7 +848,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
s = 0;
for (i = 0; i < count; ++i) {
c = buf[i];
- if (flags != 0 && flags[i] != 0)
+ if (flags && flags[i] != 0)
continue;
s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
c = ((c >> 4) ^ c) & 0xf;
@@ -869,7 +865,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
n = scan_ordinary(ap, buf, count);
f = 0;
- if (flags != 0 && (ap->state & SC_TOSS) == 0) {
+ if (flags && (ap->state & SC_TOSS) == 0) {
/* check the flags to see if any char had an error */
for (j = 0; j < n; ++j)
if ((f = flags[j]) != 0)
@@ -882,9 +878,9 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
} else if (n > 0 && (ap->state & SC_TOSS) == 0) {
/* stuff the chars in the skb */
skb = ap->rpkt;
- if (skb == 0) {
+ if (!skb) {
skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
- if (skb == 0)
+ if (!skb)
goto nomem;
ap->rpkt = skb;
}
@@ -931,7 +927,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
++n;
buf += n;
- if (flags != 0)
+ if (flags)
flags += n;
count -= n;
}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 4b49d0e8c7e..4f690378bb7 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -367,7 +367,7 @@ static int ppp_release(struct inode *inode, struct file *file)
struct ppp_file *pf = file->private_data;
struct ppp *ppp;
- if (pf != 0) {
+ if (pf) {
file->private_data = NULL;
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
@@ -398,7 +398,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
ret = count;
- if (pf == 0)
+ if (!pf)
return -ENXIO;
add_wait_queue(&pf->rwait, &wait);
for (;;) {
@@ -431,7 +431,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
set_current_state(TASK_RUNNING);
remove_wait_queue(&pf->rwait, &wait);
- if (skb == 0)
+ if (!skb)
goto out;
ret = -EOVERFLOW;
@@ -455,11 +455,11 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
struct sk_buff *skb;
ssize_t ret;
- if (pf == 0)
+ if (!pf)
return -ENXIO;
ret = -ENOMEM;
skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
- if (skb == 0)
+ if (!skb)
goto out;
skb_reserve(skb, pf->hdrlen);
ret = -EFAULT;
@@ -491,11 +491,11 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait)
struct ppp_file *pf = file->private_data;
unsigned int mask;
- if (pf == 0)
+ if (!pf)
return 0;
poll_wait(file, &pf->rwait, wait);
mask = POLLOUT | POLLWRNORM;
- if (skb_peek(&pf->rq) != 0)
+ if (skb_peek(&pf->rq))
mask |= POLLIN | POLLRDNORM;
if (pf->dead)
mask |= POLLHUP;
@@ -559,7 +559,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file,
void __user *argp = (void __user *)arg;
int __user *p = argp;
- if (pf == 0)
+ if (!pf)
return ppp_unattached_ioctl(pf, file, cmd, arg);
if (cmd == PPPIOCDETACH) {
@@ -689,13 +689,13 @@ static int ppp_ioctl(struct inode *inode, struct file *file,
val &= 0xffff;
}
vj = slhc_init(val2+1, val+1);
- if (vj == 0) {
+ if (!vj) {
printk(KERN_ERR "PPP: no memory (VJ compressor)\n");
err = -ENOMEM;
break;
}
ppp_lock(ppp);
- if (ppp->vj != 0)
+ if (ppp->vj)
slhc_free(ppp->vj);
ppp->vj = vj;
ppp_unlock(ppp);
@@ -786,7 +786,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
if (get_user(unit, p))
break;
ppp = ppp_create_interface(unit, &err);
- if (ppp == 0)
+ if (!ppp)
break;
file->private_data = &ppp->file;
ppp->owner = file;
@@ -803,7 +803,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
mutex_lock(&all_ppp_mutex);
err = -ENXIO;
ppp = ppp_find_unit(unit);
- if (ppp != 0) {
+ if (ppp) {
atomic_inc(&ppp->file.refcnt);
file->private_data = &ppp->file;
err = 0;
@@ -817,7 +817,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
spin_lock_bh(&all_channels_lock);
err = -ENXIO;
chan = ppp_find_channel(unit);
- if (chan != 0) {
+ if (chan) {
atomic_inc(&chan->file.refcnt);
file->private_data = &chan->file;
err = 0;
@@ -946,9 +946,9 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGPPPCSTATS:
memset(&cstats, 0, sizeof(cstats));
- if (ppp->xc_state != 0)
+ if (ppp->xc_state)
ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c);
- if (ppp->rc_state != 0)
+ if (ppp->rc_state)
ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d);
if (copy_to_user(addr, &cstats, sizeof(cstats)))
break;
@@ -993,14 +993,14 @@ ppp_xmit_process(struct ppp *ppp)
struct sk_buff *skb;
ppp_xmit_lock(ppp);
- if (ppp->dev != 0) {
+ if (ppp->dev) {
ppp_push(ppp);
- while (ppp->xmit_pending == 0
- && (skb = skb_dequeue(&ppp->file.xq)) != 0)
+ while (!ppp->xmit_pending
+ && (skb = skb_dequeue(&ppp->file.xq)))
ppp_send_frame(ppp, skb);
/* If there's no work left to do, tell the core net
code that we can accept some more. */
- if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0)
+ if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
netif_wake_queue(ppp->dev);
}
ppp_xmit_unlock(ppp);
@@ -1100,12 +1100,12 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
switch (proto) {
case PPP_IP:
- if (ppp->vj == 0 || (ppp->flags & SC_COMP_TCP) == 0)
+ if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0)
break;
/* try to do VJ TCP header compression */
new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
GFP_ATOMIC);
- if (new_skb == 0) {
+ if (!new_skb) {
printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n");
goto drop;
}
@@ -1140,7 +1140,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
}
/* try to do packet compression */
- if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
+ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state
&& proto != PPP_LCP && proto != PPP_CCP) {
if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
if (net_ratelimit())
@@ -1185,7 +1185,7 @@ ppp_push(struct ppp *ppp)
struct channel *pch;
struct sk_buff *skb = ppp->xmit_pending;
- if (skb == 0)
+ if (!skb)
return;
list = &ppp->channels;
@@ -1355,7 +1355,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if (flen == len && nfree == 0)
bits |= E;
frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
- if (frag == 0)
+ if (!frag)
goto noskb;
q = skb_put(frag, flen + hdrlen);
@@ -1425,7 +1425,7 @@ ppp_channel_push(struct channel *pch)
struct ppp *ppp;
spin_lock_bh(&pch->downl);
- if (pch->chan != 0) {
+ if (pch->chan) {
while (!skb_queue_empty(&pch->file.xq)) {
skb = skb_dequeue(&pch->file.xq);
if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
@@ -1443,7 +1443,7 @@ ppp_channel_push(struct channel *pch)
if (skb_queue_empty(&pch->file.xq)) {
read_lock_bh(&pch->upl);
ppp = pch->ppp;
- if (ppp != 0)
+ if (ppp)
ppp_xmit_process(ppp);
read_unlock_bh(&pch->upl);
}
@@ -1462,7 +1462,7 @@ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
ppp_recv_lock(ppp);
/* ppp->dev == 0 means interface is closing down */
- if (ppp->dev != 0)
+ if (ppp->dev)
ppp_receive_frame(ppp, skb, pch);
else
kfree_skb(skb);
@@ -1475,19 +1475,19 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
struct channel *pch = chan->ppp;
int proto;
- if (pch == 0 || skb->len == 0) {
+ if (!pch || skb->len == 0) {
kfree_skb(skb);
return;
}
proto = PPP_PROTO(skb);
read_lock_bh(&pch->upl);
- if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) {
+ if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {
/* put it on the channel queue */
skb_queue_tail(&pch->file.rq, skb);
/* drop old frames if queue too long */
while (pch->file.rq.qlen > PPP_MAX_RQLEN
- && (skb = skb_dequeue(&pch->file.rq)) != 0)
+ && (skb = skb_dequeue(&pch->file.rq)))
kfree_skb(skb);
wake_up_interruptible(&pch->file.rwait);
} else {
@@ -1503,13 +1503,13 @@ ppp_input_error(struct ppp_channel *chan, int code)
struct channel *pch = chan->ppp;
struct sk_buff *skb;
- if (pch == 0)
+ if (!pch)
return;
read_lock_bh(&pch->upl);
- if (pch->ppp != 0) {
+ if (pch->ppp) {
skb = alloc_skb(0, GFP_ATOMIC);
- if (skb != 0) {
+ if (skb) {
skb->len = 0; /* probably unnecessary */
skb->cb[0] = code;
ppp_do_recv(pch->ppp, skb, pch);
@@ -1548,7 +1548,7 @@ static void
ppp_receive_error(struct ppp *ppp)
{
++ppp->stats.rx_errors;
- if (ppp->vj != 0)
+ if (ppp->vj)
slhc_toss(ppp->vj);
}
@@ -1563,7 +1563,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
* Note that some decompressors need to see uncompressed frames
* that come in as well as compressed frames.
*/
- if (ppp->rc_state != 0 && (ppp->rstate & SC_DECOMP_RUN)
+ if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN)
&& (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0)
skb = ppp_decompress_frame(ppp, skb);
@@ -1574,13 +1574,13 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
switch (proto) {
case PPP_VJC_COMP:
/* decompress VJ compressed packets */
- if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
+ if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
/* copy to a new sk_buff with more tailroom */
ns = dev_alloc_skb(skb->len + 128);
- if (ns == 0) {
+ if (!ns) {
printk(KERN_ERR"PPP: no memory (VJ decomp)\n");
goto err;
}
@@ -1606,7 +1606,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
break;
case PPP_VJC_UNCOMP:
- if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
+ if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
/* Until we fix the decompressor need to make sure
@@ -1636,7 +1636,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
skb_queue_tail(&ppp->file.rq, skb);
/* limit queue length by dropping old frames */
while (ppp->file.rq.qlen > PPP_MAX_RQLEN
- && (skb = skb_dequeue(&ppp->file.rq)) != 0)
+ && (skb = skb_dequeue(&ppp->file.rq)))
kfree_skb(skb);
/* wake up any process polling or blocking on read */
wake_up_interruptible(&ppp->file.rwait);
@@ -1718,7 +1718,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
}
ns = dev_alloc_skb(obuff_size);
- if (ns == 0) {
+ if (!ns) {
printk(KERN_ERR "ppp_decompress_frame: no memory\n");
goto err;
}
@@ -1836,7 +1836,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
ppp->minseq = ppp->mrq.next->sequence;
/* Pull completed packets off the queue and receive them. */
- while ((skb = ppp_mp_reconstruct(ppp)) != 0)
+ while ((skb = ppp_mp_reconstruct(ppp)))
ppp_receive_nonmp_frame(ppp, skb);
return;
@@ -2002,7 +2002,7 @@ ppp_register_channel(struct ppp_channel *chan)
struct channel *pch;
pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
- if (pch == 0)
+ if (!pch)
return -ENOMEM;
pch->ppp = NULL;
pch->chan = chan;
@@ -2030,7 +2030,7 @@ int ppp_channel_index(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- if (pch != 0)
+ if (pch)
return pch->file.index;
return -1;
}
@@ -2043,9 +2043,9 @@ int ppp_unit_number(struct ppp_channel *chan)
struct channel *pch = chan->ppp;
int unit = -1;
- if (pch != 0) {
+ if (pch) {
read_lock_bh(&pch->upl);
- if (pch->ppp != 0)
+ if (pch->ppp)
unit = pch->ppp->file.index;
read_unlock_bh(&pch->upl);
}
@@ -2061,7 +2061,7 @@ ppp_unregister_channel(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- if (pch == 0)
+ if (!pch)
return; /* should never happen */
chan->ppp = NULL;
@@ -2093,7 +2093,7 @@ ppp_output_wakeup(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- if (pch == 0)
+ if (!pch)
return;
ppp_channel_push(pch);
}
@@ -2124,18 +2124,18 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
cp = find_compressor(ccp_option[0]);
#ifdef CONFIG_KMOD
- if (cp == 0) {
+ if (!cp) {
request_module("ppp-compress-%d", ccp_option[0]);
cp = find_compressor(ccp_option[0]);
}
#endif /* CONFIG_KMOD */
- if (cp == 0)
+ if (!cp)
goto out;
err = -ENOBUFS;
if (data.transmit) {
state = cp->comp_alloc(ccp_option, data.length);
- if (state != 0) {
+ if (state) {
ppp_xmit_lock(ppp);
ppp->xstate &= ~SC_COMP_RUN;
ocomp = ppp->xcomp;
@@ -2143,7 +2143,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
ppp->xcomp = cp;
ppp->xc_state = state;
ppp_xmit_unlock(ppp);
- if (ostate != 0) {
+ if (ostate) {
ocomp->comp_free(ostate);
module_put(ocomp->owner);
}
@@ -2153,7 +2153,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
} else {
state = cp->decomp_alloc(ccp_option, data.length);
- if (state != 0) {
+ if (state) {
ppp_recv_lock(ppp);
ppp->rstate &= ~SC_DECOMP_RUN;
ocomp = ppp->rcomp;
@@ -2161,7 +2161,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
ppp->rcomp = cp;
ppp->rc_state = state;
ppp_recv_unlock(ppp);
- if (ostate != 0) {
+ if (ostate) {
ocomp->decomp_free(ostate);
module_put(ocomp->owner);
}
@@ -2228,7 +2228,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
break;
if (inbound) {
/* we will start receiving compressed packets */
- if (ppp->rc_state == 0)
+ if (!ppp->rc_state)
break;
if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
ppp->file.index, 0, ppp->mru, ppp->debug)) {
@@ -2237,7 +2237,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
}
} else {
/* we will soon start sending compressed packets */
- if (ppp->xc_state == 0)
+ if (!ppp->xc_state)
break;
if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
ppp->file.index, 0, ppp->debug))
@@ -2320,11 +2320,11 @@ ppp_register_compressor(struct compressor *cp)
int ret;
spin_lock(&compressor_list_lock);
ret = -EEXIST;
- if (find_comp_entry(cp->compress_proto) != 0)
+ if (find_comp_entry(cp->compress_proto))
goto out;
ret = -ENOMEM;
ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC);
- if (ce == 0)
+ if (!ce)
goto out;
ret = 0;
ce->comp = cp;
@@ -2342,7 +2342,7 @@ ppp_unregister_compressor(struct compressor *cp)
spin_lock(&compressor_list_lock);
ce = find_comp_entry(cp->compress_proto);
- if (ce != 0 && ce->comp == cp) {
+ if (ce && ce->comp == cp) {
list_del(&ce->list);
kfree(ce);
}
@@ -2358,7 +2358,7 @@ find_compressor(int type)
spin_lock(&compressor_list_lock);
ce = find_comp_entry(type);
- if (ce != 0) {
+ if (ce) {
cp = ce->comp;
if (!try_module_get(cp->owner))
cp = NULL;
@@ -2383,7 +2383,7 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
st->p.ppp_opackets = ppp->stats.tx_packets;
st->p.ppp_oerrors = ppp->stats.tx_errors;
st->p.ppp_obytes = ppp->stats.tx_bytes;
- if (vj == 0)
+ if (!vj)
return;
st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
st->vj.vjs_compressed = vj->sls_o_compressed;
@@ -2604,11 +2604,11 @@ ppp_connect_channel(struct channel *pch, int unit)
mutex_lock(&all_ppp_mutex);
ppp = ppp_find_unit(unit);
- if (ppp == 0)
+ if (!ppp)
goto out;
write_lock_bh(&pch->upl);
ret = -EINVAL;
- if (pch->ppp != 0)
+ if (pch->ppp)
goto outl;
ppp_lock(ppp);
@@ -2644,7 +2644,7 @@ ppp_disconnect_channel(struct channel *pch)
ppp = pch->ppp;
pch->ppp = NULL;
write_unlock_bh(&pch->upl);
- if (ppp != 0) {
+ if (ppp) {
/* remove it from the ppp unit's list */
ppp_lock(ppp);
list_del(&pch->clist);
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index ce64032a465..f0c6a1926a0 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -209,7 +209,7 @@ ppp_sync_open(struct tty_struct *tty)
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
err = -ENOMEM;
- if (ap == 0)
+ if (!ap)
goto out;
/* initialize the syncppp structure */
@@ -262,7 +262,7 @@ ppp_sync_close(struct tty_struct *tty)
ap = tty->disc_data;
tty->disc_data = NULL;
write_unlock_irq(&disc_data_lock);
- if (ap == 0)
+ if (!ap)
return;
/*
@@ -278,7 +278,7 @@ ppp_sync_close(struct tty_struct *tty)
ppp_unregister_channel(&ap->chan);
skb_queue_purge(&ap->rqueue);
- if (ap->tpkt != 0)
+ if (ap->tpkt)
kfree_skb(ap->tpkt);
kfree(ap);
}
@@ -325,13 +325,13 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
int __user *p = (int __user *)arg;
int err, val;
- if (ap == 0)
+ if (!ap)
return -ENXIO;
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
@@ -341,7 +341,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
case PPPIOCGUNIT:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
@@ -349,16 +349,11 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
err = 0;
break;
- case TCGETS:
- case TCGETA:
- err = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
case TCFLSH:
/* flush our buffers and the serial port's buffer */
if (arg == TCIOFLUSH || arg == TCOFLUSH)
ppp_sync_flush_output(ap);
- err = n_tty_ioctl(tty, file, cmd, arg);
+ err = tty_perform_flush(tty, arg);
break;
case FIONREAD:
@@ -369,7 +364,8 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
- err = -ENOIOCTLCMD;
+ err = tty_mode_ioctl(tty, file, cmd, arg);
+ break;
}
sp_put(ap);
@@ -394,7 +390,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
struct syncppp *ap = sp_get(tty);
unsigned long flags;
- if (ap == 0)
+ if (!ap)
return;
spin_lock_irqsave(&ap->recv_lock, flags);
ppp_sync_input(ap, buf, cflags, count);
@@ -413,7 +409,7 @@ ppp_sync_wakeup(struct tty_struct *tty)
struct syncppp *ap = sp_get(tty);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- if (ap == 0)
+ if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
@@ -655,7 +651,7 @@ ppp_sync_push(struct syncppp *ap)
for (;;) {
if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
tty_stuffed = 0;
- if (!tty_stuffed && ap->tpkt != 0) {
+ if (!tty_stuffed && ap->tpkt) {
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len);
if (sent < 0)
@@ -673,7 +669,7 @@ ppp_sync_push(struct syncppp *ap)
/* haven't made any progress */
spin_unlock_bh(&ap->xmit_lock);
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
- || (!tty_stuffed && ap->tpkt != 0)))
+ || (!tty_stuffed && ap->tpkt)))
break;
if (!spin_trylock_bh(&ap->xmit_lock))
break;
@@ -681,7 +677,7 @@ ppp_sync_push(struct syncppp *ap)
return done;
flush:
- if (ap->tpkt != 0) {
+ if (ap->tpkt) {
kfree_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -736,7 +732,8 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
ppp_print_buffer ("receive buffer", buf, count);
/* stuff the chars in the skb */
- if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+ skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
+ if (!skb) {
printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
goto err;
}
@@ -744,7 +741,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
if (buf[0] != PPP_ALLSTATIONS)
skb_reserve(skb, 2 + (buf[0] & 1));
- if (flags != 0 && *flags) {
+ if (flags && *flags) {
/* error flag set, ignore frame */
goto err;
} else if (count > skb_tailroom(skb)) {
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index f8904fd9236..a7556cd2df7 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -488,7 +488,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
{
struct pppol2tp_session *session = NULL;
struct pppol2tp_tunnel *tunnel;
- unsigned char *ptr;
+ unsigned char *ptr, *optr;
u16 hdrflags;
u16 tunnel_id, session_id;
int length;
@@ -496,7 +496,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
tunnel = pppol2tp_sock_to_tunnel(sock);
if (tunnel == NULL)
- goto error;
+ goto no_tunnel;
/* UDP always verifies the packet length. */
__skb_pull(skb, sizeof(struct udphdr));
@@ -509,7 +509,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
}
/* Point to L2TP header */
- ptr = skb->data;
+ optr = ptr = skb->data;
/* Get L2TP header flags */
hdrflags = ntohs(*(__be16*)ptr);
@@ -637,12 +637,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
/* If offset bit set, skip it. */
if (hdrflags & L2TP_HDRFLAG_O) {
offset = ntohs(*(__be16 *)ptr);
- skb->transport_header += 2 + offset;
- if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2))
- goto discard;
+ ptr += 2 + offset;
}
- __skb_pull(skb, skb_transport_offset(skb));
+ offset = ptr - optr;
+ if (!pskb_may_pull(skb, offset))
+ goto discard;
+
+ __skb_pull(skb, offset);
/* Skip PPP header, if present. In testing, Microsoft L2TP clients
* don't send the PPP header (PPP header compression enabled), but
@@ -652,6 +654,9 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
* Note that skb->data[] isn't dereferenced from a u16 ptr here since
* the field may be unaligned.
*/
+ if (!pskb_may_pull(skb, 2))
+ goto discard;
+
if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03))
skb_pull(skb, 2);
@@ -709,6 +714,10 @@ discard:
return 0;
error:
+ /* Put UDP header back */
+ __skb_push(skb, sizeof(struct udphdr));
+
+no_tunnel:
return 1;
}
@@ -1050,6 +1059,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
/* Get routing info from the tunnel socket */
dst_release(skb->dst);
skb->dst = sk_dst_get(sk_tun);
+ skb_orphan(skb);
+ skb->sk = sk_tun;
/* Queue the packet to IP for output */
len = skb->len;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 30adf726743..a5791114b7b 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1456,16 +1456,11 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
PHYAddr[qdev->mac_index]);
reg &= ~PHY_GIG_ALL_PARAMS;
- if(portConfiguration &
- PORT_CONFIG_FULL_DUPLEX_ENABLED &
- PORT_CONFIG_1000MB_SPEED) {
- reg |= PHY_GIG_ADV_1000F;
- }
-
- if(portConfiguration &
- PORT_CONFIG_HALF_DUPLEX_ENABLED &
- PORT_CONFIG_1000MB_SPEED) {
- reg |= PHY_GIG_ADV_1000H;
+ if(portConfiguration & PORT_CONFIG_1000MB_SPEED) {
+ if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED)
+ reg |= PHY_GIG_ADV_1000F;
+ else
+ reg |= PHY_GIG_ADV_1000H;
}
ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg,
@@ -1645,8 +1640,11 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev)
return 0;
}
-static void ql_link_state_machine(struct ql3_adapter *qdev)
+static void ql_link_state_machine_work(struct work_struct *work)
{
+ struct ql3_adapter *qdev =
+ container_of(work, struct ql3_adapter, link_state_work.work);
+
u32 curr_link_state;
unsigned long hw_flags;
@@ -1661,6 +1659,10 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
"state.\n", qdev->ndev->name);
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+ /* Restart timer on 2 second interval. */
+ mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\
+
return;
}
@@ -1705,6 +1707,9 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
break;
}
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+ /* Restart timer on 2 second interval. */
+ mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
}
/*
@@ -3941,19 +3946,7 @@ static void ql_get_board_info(struct ql3_adapter *qdev)
static void ql3xxx_timer(unsigned long ptr)
{
struct ql3_adapter *qdev = (struct ql3_adapter *)ptr;
-
- if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
- printk(KERN_DEBUG PFX
- "%s: Reset in progress.\n",
- qdev->ndev->name);
- goto end;
- }
-
- ql_link_state_machine(qdev);
-
- /* Restart timer on 2 second interval. */
-end:
- mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+ queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0);
}
static int __devinit ql3xxx_probe(struct pci_dev *pdev,
@@ -4103,6 +4096,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
qdev->workqueue = create_singlethread_workqueue(ndev->name);
INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work);
INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work);
+ INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work);
init_timer(&qdev->adapter_timer);
qdev->adapter_timer.function = ql3xxx_timer;
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
index fbcb0b94963..d0ffb30ef37 100644
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -1286,6 +1286,7 @@ struct ql3_adapter {
struct workqueue_struct *workqueue;
struct delayed_work reset_work;
struct delayed_work tx_timeout_work;
+ struct delayed_work link_state_work;
u32 max_frame_size;
u32 device_id;
u16 phyType;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index b94fa7ef195..1f647b9ce35 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -171,6 +171,8 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
{ PCI_VENDOR_ID_LINKSYS, 0x1032,
PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
+ { 0x0001, 0x8168,
+ PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
{0,},
};
@@ -468,7 +470,7 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
{
int i;
- RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
+ RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff));
for (i = 20; i > 0; i--) {
/*
@@ -485,7 +487,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
{
int i, value = -1;
- RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
+ RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16);
for (i = 20; i > 0; i--) {
/*
@@ -493,7 +495,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
* the specified MII register.
*/
if (RTL_R32(PHYAR) & 0x80000000) {
- value = (int) (RTL_R32(PHYAR) & 0xFFFF);
+ value = RTL_R32(PHYAR) & 0xffff;
break;
}
udelay(25);
@@ -1245,16 +1247,6 @@ static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
-static void rtl8168b_hw_phy_config(void __iomem *ioaddr)
-{
- struct phy_reg phy_reg_init[] = {
- { 0x1f, 0x0000 },
- { 0x10, 0xf41b },
- { 0x1f, 0x0000 }
- };
-
- rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
-}
static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
{
@@ -1324,11 +1316,6 @@ static void rtl_hw_phy_config(struct net_device *dev)
case RTL_GIGA_MAC_VER_04:
rtl8169sb_hw_phy_config(ioaddr);
break;
- case RTL_GIGA_MAC_VER_11:
- case RTL_GIGA_MAC_VER_12:
- case RTL_GIGA_MAC_VER_17:
- rtl8168b_hw_phy_config(ioaddr);
- break;
case RTL_GIGA_MAC_VER_18:
rtl8168cp_hw_phy_config(ioaddr);
break;
@@ -1739,7 +1726,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
RTL_W8(Cfg9346, Cfg9346_Lock);
- if (RTL_R8(PHYstatus) & TBI_Enable) {
+ if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) &&
+ (RTL_R8(PHYstatus) & TBI_Enable)) {
tp->set_speed = rtl8169_set_speed_tbi;
tp->get_settings = rtl8169_gset_tbi;
tp->phy_reset_enable = rtl8169_tbi_reset_enable;
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index b822859c8de..73a7e6529ee 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -78,12 +78,6 @@ static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen
* stack will need to know about I/O vectors or something similar.
*/
-/*
- * sysctl_[wr]mem_max are checked at init time to see if they are at
- * least 256KB and increased to 256KB if they are not. This is done to
- * avoid ending up with socket buffers smaller than the MTU size,
- */
-
static int __devinit rr_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -561,18 +555,6 @@ static int __devinit rr_init(struct net_device *dev)
sram_size = rr_read_eeprom_word(rrpriv, (void *)8);
printk(" SRAM size 0x%06x\n", sram_size);
- if (sysctl_rmem_max < 262144){
- printk(" Receive socket buffer limit too low (%i), "
- "setting to 262144\n", sysctl_rmem_max);
- sysctl_rmem_max = 262144;
- }
-
- if (sysctl_wmem_max < 262144){
- printk(" Transmit socket buffer limit too low (%i), "
- "setting to 262144\n", sysctl_wmem_max);
- sysctl_wmem_max = 262144;
- }
-
return 0;
}
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index b8c0e7b4ca1..d5113dd712c 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -84,7 +84,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.5"
+#define DRV_VERSION "2.0.26.6"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -1081,7 +1081,7 @@ static int init_nic(struct s2io_nic *nic)
/* to set the swapper controle on the card */
if(s2io_set_swapper(nic)) {
DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
- return -1;
+ return -EIO;
}
/*
@@ -1503,7 +1503,7 @@ static int init_nic(struct s2io_nic *nic)
DBG_PRINT(ERR_DBG, "%s: failed rts ds steering",
dev->name);
DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i);
- return FAILURE;
+ return -ENODEV;
}
}
@@ -1570,7 +1570,7 @@ static int init_nic(struct s2io_nic *nic)
if (time > 10) {
DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n",
dev->name);
- return -1;
+ return -ENODEV;
}
msleep(50);
time++;
@@ -1623,7 +1623,7 @@ static int init_nic(struct s2io_nic *nic)
if (time > 10) {
DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
dev->name);
- return -1;
+ return -ENODEV;
}
time++;
msleep(50);
@@ -3775,6 +3775,40 @@ static int __devinit s2io_test_msi(struct s2io_nic *sp)
return err;
}
+
+static void remove_msix_isr(struct s2io_nic *sp)
+{
+ int i;
+ u16 msi_control;
+
+ for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+ if (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+ free_irq(vector, arg);
+ }
+ }
+
+ kfree(sp->entries);
+ kfree(sp->s2io_entries);
+ sp->entries = NULL;
+ sp->s2io_entries = NULL;
+
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+ pci_disable_msix(sp->pdev);
+}
+
+static void remove_inta_isr(struct s2io_nic *sp)
+{
+ struct net_device *dev = sp->dev;
+
+ free_irq(sp->pdev->irq, dev);
+}
+
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
@@ -3809,28 +3843,9 @@ static int s2io_open(struct net_device *dev)
int ret = s2io_enable_msi_x(sp);
if (!ret) {
- u16 msi_control;
-
ret = s2io_test_msi(sp);
-
/* rollback MSI-X, will re-enable during add_isr() */
- kfree(sp->entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
-
+ remove_msix_isr(sp);
}
if (ret) {
@@ -3899,6 +3914,12 @@ static int s2io_close(struct net_device *dev)
{
struct s2io_nic *sp = dev->priv;
+ /* Return if the device is already closed *
+ * Can happen when s2io_card_up failed in change_mtu *
+ */
+ if (!is_s2io_card_up(sp))
+ return 0;
+
netif_stop_queue(dev);
napi_disable(&sp->napi);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
@@ -6340,6 +6361,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int s2io_change_mtu(struct net_device *dev, int new_mtu)
{
struct s2io_nic *sp = dev->priv;
+ int ret = 0;
if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
@@ -6351,9 +6373,11 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
if (netif_running(dev)) {
s2io_card_down(sp);
netif_stop_queue(dev);
- if (s2io_card_up(sp)) {
+ ret = s2io_card_up(sp);
+ if (ret) {
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
__FUNCTION__);
+ return ret;
}
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
@@ -6364,7 +6388,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
}
- return 0;
+ return ret;
}
/**
@@ -6719,15 +6743,22 @@ static int s2io_add_isr(struct s2io_nic * sp)
}
}
if (err) {
+ remove_msix_isr(sp);
DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
"failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
- return -1;
+ DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n",
+ dev->name);
+ sp->config.intr_type = INTA;
+ break;
}
sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
}
- printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
- printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
+ if (!err) {
+ printk(KERN_INFO "MSI-X-TX %d entries enabled\n",
+ msix_tx_cnt);
+ printk(KERN_INFO "MSI-X-RX %d entries enabled\n",
+ msix_rx_cnt);
+ }
}
if (sp->config.intr_type == INTA) {
err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
@@ -6742,40 +6773,10 @@ static int s2io_add_isr(struct s2io_nic * sp)
}
static void s2io_rem_isr(struct s2io_nic * sp)
{
- struct net_device *dev = sp->dev;
- struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
-
- if (sp->config.intr_type == MSI_X) {
- int i;
- u16 msi_control;
-
- for (i=1; (sp->s2io_entries[i].in_use ==
- MSIX_REGISTERED_SUCCESS); i++) {
- int vector = sp->entries[i].vector;
- void *arg = sp->s2io_entries[i].arg;
-
- synchronize_irq(vector);
- free_irq(vector, arg);
- }
-
- kfree(sp->entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
- } else {
- synchronize_irq(sp->pdev->irq);
- free_irq(sp->pdev->irq, dev);
- }
+ if (sp->config.intr_type == MSI_X)
+ remove_msix_isr(sp);
+ else
+ remove_inta_isr(sp);
}
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
@@ -6785,6 +6786,9 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
unsigned long flags;
register u64 val64 = 0;
+ if (!is_s2io_card_up(sp))
+ return;
+
del_timer_sync(&sp->alarm_timer);
/* If s2io_set_link task is executing, wait till it completes. */
while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) {
@@ -6858,11 +6862,13 @@ static int s2io_card_up(struct s2io_nic * sp)
u16 interruptible;
/* Initialize the H/W I/O registers */
- if (init_nic(sp) != 0) {
+ ret = init_nic(sp);
+ if (ret != 0) {
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
dev->name);
- s2io_reset(sp);
- return -ENODEV;
+ if (ret != -EIO)
+ s2io_reset(sp);
+ return ret;
}
/*
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index b9961dc4760..186eb8ebfda 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -44,7 +44,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "1.12"
+#define DRV_VERSION "1.13"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -1095,16 +1095,9 @@ static void xm_link_down(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
struct skge_port *skge = netdev_priv(dev);
- u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
- cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
- xm_write16(hw, port, XM_MMU_CMD, cmd);
-
- /* dummy read to ensure writing */
- xm_read16(hw, port, XM_MMU_CMD);
-
if (netif_carrier_ok(dev))
skge_link_down(skge);
}
@@ -1194,6 +1187,7 @@ static void genesis_init(struct skge_hw *hw)
static void genesis_reset(struct skge_hw *hw, int port)
{
const u8 zero[8] = { 0 };
+ u32 reg;
skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
@@ -1209,6 +1203,11 @@ static void genesis_reset(struct skge_hw *hw, int port)
xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
xm_outhash(hw, port, XM_HSM, zero);
+
+ /* Flush TX and RX fifo */
+ reg = xm_read32(hw, port, XM_MODE);
+ xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF);
+ xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF);
}
@@ -1634,15 +1633,14 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
}
xm_write16(hw, port, XM_RX_CMD, r);
-
/* We want short frames padded to 60 bytes. */
xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD);
- /*
- * Bump up the transmit threshold. This helps hold off transmit
- * underruns when we're blasting traffic from both ports at once.
- */
- xm_write16(hw, port, XM_TX_THR, 512);
+ /* Increase threshold for jumbo frames on dual port */
+ if (hw->ports > 1 && jumbo)
+ xm_write16(hw, port, XM_TX_THR, 1020);
+ else
+ xm_write16(hw, port, XM_TX_THR, 512);
/*
* Enable the reception of all error frames. This is is
@@ -1713,7 +1711,13 @@ static void genesis_stop(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
- u32 reg;
+ unsigned retries = 1000;
+ u16 cmd;
+
+ /* Disable Tx and Rx */
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
+ cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ xm_write16(hw, port, XM_MMU_CMD, cmd);
genesis_reset(hw, port);
@@ -1721,20 +1725,17 @@ static void genesis_stop(struct skge_port *skge)
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
- /*
- * If the transfer sticks at the MAC the STOP command will not
- * terminate if we don't flush the XMAC's transmit FIFO !
- */
- xm_write32(hw, port, XM_MODE,
- xm_read32(hw, port, XM_MODE)|XM_MD_FTF);
-
-
/* Reset the MAC */
- skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+ do {
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+ if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST))
+ break;
+ } while (--retries > 0);
/* For external PHYs there must be special handling */
if (hw->phy_type != SK_PHY_XMAC) {
- reg = skge_read32(hw, B2_GP_IO);
+ u32 reg = skge_read32(hw, B2_GP_IO);
if (port == 0) {
reg |= GP_DIR_0;
reg &= ~GP_IO_0;
@@ -1801,11 +1802,6 @@ static void genesis_mac_intr(struct skge_hw *hw, int port)
xm_write32(hw, port, XM_MODE, XM_MD_FTF);
++dev->stats.tx_fifo_errors;
}
-
- if (status & XM_IS_RXF_OV) {
- xm_write32(hw, port, XM_MODE, XM_MD_FRF);
- ++dev->stats.rx_fifo_errors;
- }
}
static void genesis_link_up(struct skge_port *skge)
@@ -1862,9 +1858,9 @@ static void genesis_link_up(struct skge_port *skge)
xm_write32(hw, port, XM_MODE, mode);
- /* Turn on detection of Tx underrun, Rx overrun */
+ /* Turn on detection of Tx underrun */
msk = xm_read16(hw, port, XM_IMSK);
- msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR);
+ msk &= ~XM_IS_TXF_UR;
xm_write16(hw, port, XM_IMSK, msk);
xm_read16(hw, port, XM_ISRC);
@@ -2194,9 +2190,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
TX_IPG_JAM_DATA(TX_IPG_JAM_DEF));
- /* serial mode register */
- reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
- if (hw->dev[port]->mtu > 1500)
+ /* configure the Serial Mode Register */
+ reg = DATA_BLIND_VAL(DATA_BLIND_DEF)
+ | GM_SMOD_VLAN_ENA
+ | IPG_DATA_VAL(IPG_DATA_DEF);
+
+ if (hw->dev[port]->mtu > ETH_DATA_LEN)
reg |= GM_SMOD_JUMBO_ENA;
gma_write16(hw, port, GM_SERIAL_MODE, reg);
@@ -2512,31 +2511,32 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
}
-/* Assign Ram Buffer allocation to queue */
-static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, u32 space)
+static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len)
{
u32 end;
- /* convert from K bytes to qwords used for hw register */
- start *= 1024/8;
- space *= 1024/8;
- end = start + space - 1;
+ start /= 8;
+ len /= 8;
+ end = start + len - 1;
skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
skge_write32(hw, RB_ADDR(q, RB_START), start);
- skge_write32(hw, RB_ADDR(q, RB_END), end);
skge_write32(hw, RB_ADDR(q, RB_WP), start);
skge_write32(hw, RB_ADDR(q, RB_RP), start);
+ skge_write32(hw, RB_ADDR(q, RB_END), end);
if (q == Q_R1 || q == Q_R2) {
- u32 tp = space - space/4;
-
/* Set thresholds on receive queue's */
- skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
- skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
- } else if (hw->chip_id != CHIP_ID_GENESIS)
- /* Genesis Tx Fifo is too small for normal store/forward */
+ skge_write32(hw, RB_ADDR(q, RB_RX_UTPP),
+ start + (2*len)/3);
+ skge_write32(hw, RB_ADDR(q, RB_RX_LTPP),
+ start + (len/3));
+ } else {
+ /* Enable store & forward on Tx queue's because
+ * Tx FIFO is only 4K on Genesis and 1K on Yukon
+ */
skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+ }
skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
}
@@ -2564,7 +2564,7 @@ static int skge_up(struct net_device *dev)
struct skge_port *skge = netdev_priv(dev);
struct skge_hw *hw = skge->hw;
int port = skge->port;
- u32 ramaddr, ramsize, rxspace;
+ u32 chunk, ram_addr;
size_t rx_size, tx_size;
int err;
@@ -2618,16 +2618,15 @@ static int skge_up(struct net_device *dev)
yukon_mac_init(hw, port);
spin_unlock_bh(&hw->phy_lock);
- /* Configure RAMbuffers */
- ramsize = (hw->ram_size - hw->ram_offset) / hw->ports;
- ramaddr = hw->ram_offset + port * ramsize;
- rxspace = 8 + (2*(ramsize - 16))/3;
-
- skge_ramset(hw, rxqaddr[port], ramaddr, rxspace);
- skge_ramset(hw, txqaddr[port], ramaddr + rxspace, ramsize - rxspace);
+ /* Configure RAMbuffers - equally between ports and tx/rx */
+ chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2);
+ ram_addr = hw->ram_offset + 2 * chunk * port;
+ skge_ramset(hw, rxqaddr[port], ram_addr, chunk);
skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean);
+
BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean);
+ skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk);
skge_qset(skge, txqaddr[port], skge->tx_ring.to_use);
/* Start receiver BMU */
@@ -2897,11 +2896,7 @@ static void skge_tx_timeout(struct net_device *dev)
static int skge_change_mtu(struct net_device *dev, int new_mtu)
{
- struct skge_port *skge = netdev_priv(dev);
- struct skge_hw *hw = skge->hw;
- int port = skge->port;
int err;
- u16 ctl, reg;
if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
return -EINVAL;
@@ -2911,40 +2906,13 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
- skge_write32(hw, B0_IMSK, 0);
- dev->trans_start = jiffies; /* prevent tx timeout */
- netif_stop_queue(dev);
- napi_disable(&skge->napi);
-
- ctl = gma_read16(hw, port, GM_GP_CTRL);
- gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
-
- skge_rx_clean(skge);
- skge_rx_stop(hw, port);
+ skge_down(dev);
dev->mtu = new_mtu;
- reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
- if (new_mtu > 1500)
- reg |= GM_SMOD_JUMBO_ENA;
- gma_write16(hw, port, GM_SERIAL_MODE, reg);
-
- skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);
-
- err = skge_rx_fill(dev);
- wmb();
- if (!err)
- skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
- skge_write32(hw, B0_IMSK, hw->intr_mask);
-
+ err = skge_up(dev);
if (err)
dev_close(dev);
- else {
- gma_write16(hw, port, GM_GP_CTRL, ctl);
-
- napi_enable(&skge->napi);
- netif_wake_queue(dev);
- }
return err;
}
@@ -3591,12 +3559,15 @@ static int skge_reset(struct skge_hw *hw)
if (hw->chip_id == CHIP_ID_GENESIS) {
if (t8 == 3) {
/* special case: 4 x 64k x 36, offset = 0x80000 */
- hw->ram_size = 1024;
- hw->ram_offset = 512;
+ hw->ram_size = 0x100000;
+ hw->ram_offset = 0x80000;
} else
hw->ram_size = t8 * 512;
- } else /* Yukon */
- hw->ram_size = t8 ? t8 * 4 : 128;
+ }
+ else if (t8 == 0)
+ hw->ram_size = 0x20000;
+ else
+ hw->ram_size = t8 * 4096;
hw->intr_mask = IS_HW_ERR;
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index c27c7d63b6a..3d1dfc94840 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -31,7 +31,6 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
-#include <linux/aer.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <linux/tcp.h>
@@ -52,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.19"
+#define DRV_VERSION "1.20"
#define PFX DRV_NAME " "
/*
@@ -121,6 +120,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
@@ -134,6 +134,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */
{ 0 }
};
@@ -156,7 +157,7 @@ static const char *yukon2_name[] = {
static void sky2_set_multicast(struct net_device *dev);
-/* Access to external PHY */
+/* Access to PHY via serial interconnect */
static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
{
int i;
@@ -166,13 +167,22 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg));
for (i = 0; i < PHY_RETRIES; i++) {
- if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (!(ctrl & GM_SMI_CT_BUSY))
return 0;
- udelay(1);
+
+ udelay(10);
}
- printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name);
+ dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name);
return -ETIMEDOUT;
+
+io_error:
+ dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
}
static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
@@ -183,23 +193,29 @@ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
| GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
for (i = 0; i < PHY_RETRIES; i++) {
- if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) {
+ u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL);
+ if (ctrl == 0xffff)
+ goto io_error;
+
+ if (ctrl & GM_SMI_CT_RD_VAL) {
*val = gma_read16(hw, port, GM_SMI_DATA);
return 0;
}
- udelay(1);
+ udelay(10);
}
+ dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name);
return -ETIMEDOUT;
+io_error:
+ dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name);
+ return -EIO;
}
-static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
+static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
{
u16 v;
-
- if (__gm_phy_read(hw, port, reg, &v) != 0)
- printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name);
+ __gm_phy_read(hw, port, reg, &v);
return v;
}
@@ -223,22 +239,21 @@ static void sky2_power_on(struct sky2_hw *hw)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
- struct pci_dev *pdev = hw->pdev;
u32 reg;
- pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
- pci_read_config_dword(pdev, PCI_DEV_REG4, &reg);
+ reg = sky2_pci_read32(hw, PCI_DEV_REG4);
/* set all bits to 0 except bits 15..12 and 8 */
reg &= P_ASPM_CONTROL_MSK;
- pci_write_config_dword(pdev, PCI_DEV_REG4, reg);
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg);
- pci_read_config_dword(pdev, PCI_DEV_REG5, &reg);
+ reg = sky2_pci_read32(hw, PCI_DEV_REG5);
/* set all bits to 0 except bits 28 & 27 */
reg &= P_CTL_TIM_VMAIN_AV_MSK;
- pci_write_config_dword(pdev, PCI_DEV_REG5, reg);
+ sky2_pci_write32(hw, PCI_DEV_REG5, reg);
- pci_write_config_dword(pdev, PCI_CFG_REG_1, 0);
+ sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
/* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
reg = sky2_read32(hw, B2_GP_IO);
@@ -273,8 +288,6 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
/* disable all GMAC IRQ's */
sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
- /* disable PHY IRQs */
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
gma_write16(hw, port, GM_MC_ADDR_H2, 0);
@@ -604,12 +617,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
{
- struct pci_dev *pdev = hw->pdev;
u32 reg1;
static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
- pci_read_config_dword(pdev, PCI_DEV_REG1, &reg1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
/* Turn on/off phy power saving */
if (onoff)
reg1 &= ~phy_power[port];
@@ -619,8 +631,8 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
reg1 |= coma_mode[port];
- pci_write_config_dword(pdev, PCI_DEV_REG1, reg1);
- pci_read_config_dword(pdev, PCI_DEV_REG1, &reg1);
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
udelay(100);
}
@@ -689,9 +701,9 @@ static void sky2_wol_init(struct sky2_port *sky2)
sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl);
/* Turn on legacy PCI-Express PME mode */
- pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
reg1 |= PCI_Y2_PME_LEGACY;
- pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
/* block receiver */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
@@ -833,6 +845,13 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
sky2_set_tx_stfwd(hw, port);
}
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ /* disable dynamic watermark */
+ reg = sky2_read16(hw, SK_REG(port, TX_GMF_EA));
+ reg &= ~TX_DYN_WM_ENA;
+ sky2_write16(hw, SK_REG(port, TX_GMF_EA), reg);
+ }
}
/* Assign Ram Buffer allocation to queue */
@@ -1305,15 +1324,12 @@ static int sky2_up(struct net_device *dev)
*/
if (otherdev && netif_running(otherdev) &&
(cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) {
- struct sky2_port *osky2 = netdev_priv(otherdev);
u16 cmd;
- pci_read_config_word(hw->pdev, cap + PCI_X_CMD, &cmd);
+ cmd = sky2_pci_read16(hw, cap + PCI_X_CMD);
cmd &= ~PCI_X_CMD_MAX_SPLIT;
- pci_write_config_word(hw->pdev, cap + PCI_X_CMD, cmd);
+ sky2_pci_write16(hw, cap + PCI_X_CMD, cmd);
- sky2->rx_csum = 0;
- osky2->rx_csum = 0;
}
if (netif_msg_ifup(sky2))
@@ -1805,29 +1821,6 @@ static void sky2_link_up(struct sky2_port *sky2)
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
- if (hw->flags & SKY2_HW_NEWER_PHY) {
- u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
- u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
-
- switch(sky2->speed) {
- case SPEED_10:
- led |= PHY_M_LEDC_INIT_CTRL(7);
- break;
-
- case SPEED_100:
- led |= PHY_M_LEDC_STA1_CTRL(7);
- break;
-
- case SPEED_1000:
- led |= PHY_M_LEDC_STA0_CTRL(7);
- break;
- }
-
- gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
- gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led);
- gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
- }
-
if (netif_msg_link(sky2))
printk(KERN_INFO PFX
"%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
@@ -2247,20 +2240,26 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
do {
struct sky2_port *sky2;
struct sky2_status_le *le = hw->st_le + hw->st_idx;
- unsigned port = le->css & CSS_LINK_BIT;
+ unsigned port;
struct net_device *dev;
struct sk_buff *skb;
u32 status;
u16 length;
+ u8 opcode = le->opcode;
+
+ if (!(opcode & HW_OWNER))
+ break;
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
+ port = le->css & CSS_LINK_BIT;
dev = hw->dev[port];
sky2 = netdev_priv(dev);
length = le16_to_cpu(le->length);
status = le32_to_cpu(le->status);
- switch (le->opcode & ~HW_OWNER) {
+ le->opcode = 0;
+ switch (opcode & ~HW_OWNER) {
case OP_RXSTAT:
++rx[port];
skb = sky2_receive(dev, length, status);
@@ -2353,7 +2352,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
default:
if (net_ratelimit())
printk(KERN_WARNING PFX
- "unknown status opcode 0x%x\n", le->opcode);
+ "unknown status opcode 0x%x\n", opcode);
}
} while (hw->st_idx != idx);
@@ -2428,24 +2427,26 @@ static void sky2_hw_intr(struct sky2_hw *hw)
if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
u16 pci_err;
- pci_read_config_word(pdev, PCI_STATUS, &pci_err);
+ pci_err = sky2_pci_read16(hw, PCI_STATUS);
if (net_ratelimit())
dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
pci_err);
- pci_write_config_word(pdev, PCI_STATUS,
+ sky2_pci_write16(hw, PCI_STATUS,
pci_err | PCI_STATUS_ERROR_BITS);
}
if (status & Y2_IS_PCI_EXP) {
/* PCI-Express uncorrectable Error occurred */
- int pos = pci_find_aer_capability(hw->pdev);
u32 err;
- pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err);
+ err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
if (net_ratelimit())
dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
- pci_cleanup_aer_uncorrect_error_status(pdev);
+
+ sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
}
if (status & Y2_HWE_L1_MASK)
@@ -2692,13 +2693,10 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
static int __devinit sky2_init(struct sky2_hw *hw)
{
- int rc;
u8 t8;
/* Enable all clocks and check for bad PCI access */
- rc = pci_write_config_dword(hw->pdev, PCI_DEV_REG3, 0);
- if (rc)
- return rc;
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
sky2_write8(hw, B0_CTST, CS_RST_CLR);
@@ -2791,24 +2789,25 @@ static void sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_RST_SET);
sky2_write8(hw, B0_CTST, CS_RST_CLR);
+ /* allow writes to PCI config */
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
/* clear PCI errors, if any */
- pci_read_config_word(pdev, PCI_STATUS, &status);
+ status = sky2_pci_read16(hw, PCI_STATUS);
status |= PCI_STATUS_ERROR_BITS;
- pci_write_config_word(pdev, PCI_STATUS, status);
+ sky2_pci_write16(hw, PCI_STATUS, status);
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
if (cap) {
- /* Check for advanced error reporting */
- pci_cleanup_aer_uncorrect_error_status(pdev);
- pci_cleanup_aer_correct_error_status(pdev);
+ sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 0xfffffffful);
/* If error bit is stuck on ignore it */
if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP)
dev_info(&pdev->dev, "ignoring stuck error report bit\n");
-
- else if (pci_enable_pcie_error_reporting(pdev))
+ else
hwe_mask |= Y2_IS_PCI_EXP;
}
@@ -3649,32 +3648,33 @@ static int sky2_set_tso(struct net_device *dev, u32 data)
static int sky2_get_eeprom_len(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
u16 reg2;
- pci_read_config_word(sky2->hw->pdev, PCI_DEV_REG2, &reg2);
+ reg2 = sky2_pci_read16(hw, PCI_DEV_REG2);
return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
}
-static u32 sky2_vpd_read(struct pci_dev *pdev, int cap, u16 offset)
+static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset)
{
u32 val;
- pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset);
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
do {
- pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
+ offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR);
} while (!(offset & PCI_VPD_ADDR_F));
- pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val);
+ val = sky2_pci_read32(hw, cap + PCI_VPD_DATA);
return val;
}
-static void sky2_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val)
+static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val)
{
- pci_write_config_word(pdev, cap + PCI_VPD_DATA, val);
- pci_write_config_dword(pdev, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+ sky2_pci_write16(hw, cap + PCI_VPD_DATA, val);
+ sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
do {
- pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset);
+ offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR);
} while (offset & PCI_VPD_ADDR_F);
}
@@ -3692,7 +3692,7 @@ static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
eeprom->magic = SKY2_EEPROM_MAGIC;
while (length > 0) {
- u32 val = sky2_vpd_read(sky2->hw->pdev, cap, offset);
+ u32 val = sky2_vpd_read(sky2->hw, cap, offset);
int n = min_t(int, length, sizeof(val));
memcpy(data, &val, n);
@@ -3722,10 +3722,10 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
int n = min_t(int, length, sizeof(val));
if (n < sizeof(val))
- val = sky2_vpd_read(sky2->hw->pdev, cap, offset);
+ val = sky2_vpd_read(sky2->hw, cap, offset);
memcpy(&val, data, n);
- sky2_vpd_write(sky2->hw->pdev, cap, offset, val);
+ sky2_vpd_write(sky2->hw, cap, offset, val);
length -= n;
data += n;
@@ -3974,7 +3974,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
dev->tx_timeout = sky2_tx_timeout;
dev->watchdog_timeo = TX_WATCHDOG;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = sky2_netpoll;
+ if (port == 0)
+ dev->poll_controller = sky2_netpoll;
#endif
sky2 = netdev_priv(dev);
@@ -3989,7 +3990,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
sky2->duplex = -1;
sky2->speed = -1;
sky2->advertising = sky2_supported_modes(hw);
- sky2->rx_csum = 1;
+ sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL);
sky2->wol = wol;
spin_lock_init(&sky2->phy_lock);
@@ -4160,9 +4161,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
*/
{
u32 reg;
- pci_read_config_dword(pdev,PCI_DEV_REG2, &reg);
+ reg = sky2_pci_read32(hw, PCI_DEV_REG2);
reg &= ~PCI_REV_DESC;
- pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
+ sky2_pci_write32(hw, PCI_DEV_REG2, reg);
}
#endif
@@ -4353,7 +4354,7 @@ static int sky2_resume(struct pci_dev *pdev)
if (hw->chip_id == CHIP_ID_YUKON_EX ||
hw->chip_id == CHIP_ID_YUKON_EC_U ||
hw->chip_id == CHIP_ID_YUKON_FE_P)
- pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
sky2_reset(hw);
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 49ee264064a..bc646a47edd 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -247,7 +247,8 @@ enum csr_regs {
B3_PA_CTRL = 0x01f0,
B3_PA_TEST = 0x01f2,
- Y2_CFG_SPC = 0x1c00,
+ Y2_CFG_SPC = 0x1c00, /* PCI config space region */
+ Y2_CFG_AER = 0x1d00, /* PCI Advanced Error Report region */
};
/* B0_CTST 16 bit Control/Status register */
@@ -2127,4 +2128,25 @@ static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg,
gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
}
+
+/* PCI config space access */
+static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read32(hw, Y2_CFG_SPC + reg);
+}
+
+static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read16(hw, Y2_CFG_SPC + reg);
+}
+
+static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val)
+{
+ sky2_write32(hw, Y2_CFG_SPC + reg, val);
+}
+
+static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val)
+{
+ sky2_write16(hw, Y2_CFG_SPC + reg, val);
+}
#endif
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 335b7cc80eb..251a3ce376a 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1218,14 +1218,8 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
return 0;
/* VSV changes end */
#endif
-
- /* Allow stty to read, but not set, the serial port */
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(tty, file, cmd, arg);
-
default:
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(tty, file, cmd, arg);
}
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index dd18af0ce67..1a3d80bfe9e 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -428,7 +428,6 @@ static inline void smc911x_drop_pkt(struct net_device *dev)
*/
static inline void smc911x_rcv(struct net_device *dev)
{
- struct smc911x_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
unsigned int pkt_len, status;
struct sk_buff *skb;
@@ -473,6 +472,7 @@ static inline void smc911x_rcv(struct net_device *dev)
skb_put(skb,pkt_len-4);
#ifdef SMC_USE_DMA
{
+ struct smc911x_local *lp = netdev_priv(dev);
unsigned int fifo;
/* Lower the FIFO threshold if possible */
fifo = SMC_GET_FIFO_INT();
@@ -1379,13 +1379,6 @@ static void smc911x_set_multicast_list(struct net_device *dev)
unsigned int multicast_table[2];
unsigned int mcr, update_multicast = 0;
unsigned long flags;
- /* table for flipping the order of 5 bits */
- static const unsigned char invert5[] =
- {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C,
- 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E,
- 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D,
- 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F};
-
DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
@@ -1432,7 +1425,7 @@ static void smc911x_set_multicast_list(struct net_device *dev)
cur_addr = dev->mc_list;
for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
- int position;
+ u32 position;
/* do we have a pointer here? */
if (!cur_addr)
@@ -1442,12 +1435,10 @@ static void smc911x_set_multicast_list(struct net_device *dev)
if (!(*cur_addr->dmi_addr & 1))
continue;
- /* only use the low order bits */
- position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f;
+ /* upper 6 bits are used as hash index */
+ position = ether_crc(ETH_ALEN, cur_addr->dmi_addr)>>26;
- /* do some messy swapping to put the bit in the right spot */
- multicast_table[invert5[position&0x1F]&0x1] |=
- (1<<invert5[(position>>1)&0x1F]);
+ multicast_table[position>>5] |= 1 << (position&0x1f);
}
/* be sure I get rid of flags I might have set */
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
index 16a0edc078f..d04e4fa3520 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/smc911x.h
@@ -37,7 +37,7 @@
#define SMC_USE_16BIT 0
#define SMC_USE_32BIT 1
#define SMC_IRQ_SENSE IRQF_TRIGGER_FALLING
-#elif CONFIG_SH_MAGIC_PANEL_R2
+#elif defined(CONFIG_SH_MAGIC_PANEL_R2)
#define SMC_USE_SH_DMA 0
#define SMC_USE_16BIT 0
#define SMC_USE_32BIT 1
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 729fd28c08b..07b7f7120e3 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -55,7 +55,7 @@
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
-#elif defined(CONFIG_BFIN)
+#elif defined(CONFIG_BLACKFIN)
#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH
#define RPC_LSA_DEFAULT RPC_LED_100_10
@@ -224,6 +224,21 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
+#elif defined(CONFIG_MACH_ZYLONITE)
+
+#define SMC_CAN_USE_8BIT 1
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+#define SMC_USE_PXA_DMA 1
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+
#elif defined(CONFIG_ARCH_OMAP)
/* We can only do 16-bit reads and writes in the static memory space. */
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 53b8344a68e..68872142530 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2281,14 +2281,12 @@ static void gem_reset_task(struct work_struct *work)
mutex_lock(&gp->pm_mutex);
- napi_disable(&gp->napi);
+ if (gp->opened)
+ napi_disable(&gp->napi);
spin_lock_irq(&gp->lock);
spin_lock(&gp->tx_lock);
- if (gp->running == 0)
- goto not_running;
-
if (gp->running) {
netif_stop_queue(gp->dev);
@@ -2298,13 +2296,14 @@ static void gem_reset_task(struct work_struct *work)
gem_set_link_modes(gp);
netif_wake_queue(gp->dev);
}
- not_running:
+
gp->reset_task_pending = 0;
spin_unlock(&gp->tx_lock);
spin_unlock_irq(&gp->lock);
- napi_enable(&gp->napi);
+ if (gp->opened)
+ napi_enable(&gp->napi);
mutex_unlock(&gp->pm_mutex);
}
@@ -2333,10 +2332,10 @@ static int gem_close(struct net_device *dev)
{
struct gem *gp = dev->priv;
- napi_disable(&gp->napi);
-
mutex_lock(&gp->pm_mutex);
+ napi_disable(&gp->napi);
+
gp->opened = 0;
if (!gp->asleep)
gem_do_stop(dev, 0);
@@ -2355,8 +2354,6 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
mutex_lock(&gp->pm_mutex);
- napi_disable(&gp->napi);
-
printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
dev->name,
(gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
@@ -2370,6 +2367,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
/* If the driver is opened, we stop the MAC */
if (gp->opened) {
+ napi_disable(&gp->napi);
+
/* Stop traffic, mark us closed */
netif_device_detach(dev);
@@ -2460,6 +2459,7 @@ static int gem_resume(struct pci_dev *pdev)
/* Re-attach net device */
netif_device_attach(dev);
+ napi_enable(&gp->napi);
}
spin_lock_irqsave(&gp->lock, flags);
@@ -2479,8 +2479,6 @@ static int gem_resume(struct pci_dev *pdev)
spin_unlock(&gp->tx_lock);
spin_unlock_irqrestore(&gp->lock, flags);
- napi_enable(&gp->napi);
-
mutex_unlock(&gp->pm_mutex);
return 0;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index c20a3bd21bb..9cc13dd8a82 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1281,7 +1281,7 @@ static void happy_meal_init_rings(struct happy_meal *hp)
skb->dev = dev;
/* Because we reserve afterwards. */
- skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
+ skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
hme_write_rxd(hp, &hb->happy_meal_rxd[i],
(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
@@ -1700,6 +1700,11 @@ static int happy_meal_init(struct happy_meal *hp)
HMD(("tx old[%08x] and rx [%08x] ON!\n",
hme_read32(hp, bregs + BMAC_TXCFG),
hme_read32(hp, bregs + BMAC_RXCFG)));
+
+ /* Set larger TX/RX size to allow for 802.1q */
+ hme_write32(hp, bregs + BMAC_TXMAX, ETH_FRAME_LEN + 8);
+ hme_write32(hp, bregs + BMAC_RXMAX, ETH_FRAME_LEN + 8);
+
hme_write32(hp, bregs + BMAC_TXCFG,
hme_read32(hp, bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE);
hme_write32(hp, bregs + BMAC_RXCFG,
@@ -2039,7 +2044,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
hp->rx_skbs[elem] = new_skb;
new_skb->dev = dev;
- skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
+ skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
hme_write_rxd(hp, this,
(RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
@@ -2809,8 +2814,8 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
dev->watchdog_timeo = 5*HZ;
dev->ethtool_ops = &hme_ethtool_ops;
- /* Happy Meal can do it all... except VLAN. */
- dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
+ /* Happy Meal can do it all... */
+ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
dev->irq = sdev->irqs[0];
@@ -3143,8 +3148,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
dev->irq = pdev->irq;
dev->dma = 0;
- /* Happy Meal can do it all... except VLAN. */
- dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
+ /* Happy Meal can do it all... */
+ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
/* Hook up PCI register/dma accessors. */
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 4e1b84e6d66..21230c97b2a 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -2168,10 +2168,10 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
{
struct bdx_priv *priv = netdev->priv;
- strncat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
- strncat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
- strncat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
- strncat(drvinfo->bus_info, pci_name(priv->pdev),
+ strlcat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
+ strlcat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
+ strlcat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+ strlcat(drvinfo->bus_info, pci_name(priv->pdev),
sizeof(drvinfo->bus_info));
drvinfo->n_stats = ((priv->stats_flag) ?
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index cad51991076..4942f7d1893 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.85"
-#define DRV_MODULE_RELDATE "October 18, 2007"
+#define DRV_MODULE_VERSION "3.86"
+#define DRV_MODULE_RELDATE "November 9, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -1106,6 +1106,24 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err)
return err;
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ u32 val;
+
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+ CPMU_LSPD_1000MB_MACCLK_12_5) {
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ udelay(40);
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
+ /* Disable GPHY autopowerdown. */
+ tg3_writephy(tp, MII_TG3_MISC_SHDW,
+ MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_APD_SEL |
+ MII_TG3_MISC_SHDW_APD_WKTM_84MS);
+ }
+
out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1297,6 +1315,8 @@ static void tg3_nvram_unlock(struct tg3 *);
static void tg3_power_down_phy(struct tg3 *tp)
{
+ u32 val;
+
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -1311,8 +1331,6 @@ static void tg3_power_down_phy(struct tg3 *tp)
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 val;
-
tg3_bmcr_reset(tp);
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
@@ -1332,6 +1350,14 @@ static void tg3_power_down_phy(struct tg3 *tp)
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
+
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
}
@@ -3126,6 +3152,23 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
err = tg3_setup_copper_phy(tp, force_reset);
}
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+ u32 val, scale;
+
+ val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+ if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+ scale = 65;
+ else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+ scale = 6;
+ else
+ scale = 12;
+
+ val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+ val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+ tw32(GRC_MISC_CFG, val);
+ }
+
if (tp->link_config.active_speed == SPEED_1000 &&
tp->link_config.active_duplex == DUPLEX_HALF)
tw32(MAC_TX_LENGTHS,
@@ -5054,12 +5097,15 @@ static void tg3_restore_pci_state(struct tg3 *tp)
pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
- if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+ pcie_set_readrq(tp->pdev, 4096);
+ else {
pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
tp->pci_cacheline_sz);
pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
tp->pci_lat_timer);
}
+
/* Make sure PCI-X relaxed ordering bit is clear. */
if (tp->pcix_cap) {
u16 pcix_cmd;
@@ -6343,10 +6389,26 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
+
+ val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+ val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+ val |= CPMU_LSPD_10MB_MACCLK_6_25;
+ tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+
+ val = tr32(TG3_CPMU_LNK_AWARE_PWRMD);
+ val &= ~CPMU_LNK_AWARE_MACCLK_MASK;
+ val |= CPMU_LNK_AWARE_MACCLK_6_25;
+ tw32(TG3_CPMU_LNK_AWARE_PWRMD, val);
+
+ val = tr32(TG3_CPMU_HST_ACC);
+ val &= ~CPMU_HST_ACC_MACCLK_MASK;
+ val |= CPMU_HST_ACC_MACCLK_6_25;
+ tw32(TG3_CPMU_HST_ACC, val);
}
/* This works around an issue with Athlon chipsets on
@@ -8267,7 +8329,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;
@@ -8664,7 +8726,9 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
}
#define NVRAM_TEST_SIZE 0x100
-#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
+#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c
#define NVRAM_SELFBOOT_HW_SIZE 0x20
#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
@@ -8679,9 +8743,22 @@ static int tg3_test_nvram(struct tg3 *tp)
if (magic == TG3_EEPROM_MAGIC)
size = NVRAM_TEST_SIZE;
else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
- if ((magic & 0xe00000) == 0x200000)
- size = NVRAM_SELFBOOT_FORMAT1_SIZE;
- else
+ if ((magic & TG3_EEPROM_SB_FORMAT_MASK) ==
+ TG3_EEPROM_SB_FORMAT_1) {
+ switch (magic & TG3_EEPROM_SB_REVISION_MASK) {
+ case TG3_EEPROM_SB_REVISION_0:
+ size = NVRAM_SELFBOOT_FORMAT1_0_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_2:
+ size = NVRAM_SELFBOOT_FORMAT1_2_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_3:
+ size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
+ break;
+ default:
+ return 0;
+ }
+ } else
return 0;
} else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
size = NVRAM_SELFBOOT_HW_SIZE;
@@ -8708,8 +8785,17 @@ static int tg3_test_nvram(struct tg3 *tp)
TG3_EEPROM_MAGIC_FW) {
u8 *buf8 = (u8 *) buf, csum8 = 0;
- for (i = 0; i < size; i++)
- csum8 += buf8[i];
+ if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) ==
+ TG3_EEPROM_SB_REVISION_2) {
+ /* For rev 2, the csum doesn't include the MBA. */
+ for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++)
+ csum8 += buf8[i];
+ for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++)
+ csum8 += buf8[i];
+ } else {
+ for (i = 0; i < size; i++)
+ csum8 += buf8[i];
+ }
if (csum8 == 0) {
err = 0;
@@ -9293,7 +9379,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (err)
return TG3_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
int i;
u32 status;
@@ -9310,17 +9396,17 @@ static int tg3_test_loopback(struct tg3 *tp)
if (status != CPMU_MUTEX_GNT_DRIVER)
return TG3_LOOPBACK_FAILED;
- cpmuctrl = tr32(TG3_CPMU_CTRL);
-
/* Turn off power management based on link speed. */
+ cpmuctrl = tr32(TG3_CPMU_CTRL);
tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE);
+ cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
+ CPMU_CTRL_LINK_AWARE_MODE));
}
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
/* Release the mutex */
@@ -10541,6 +10627,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1)
+ tp->led_ctrl = LED_CTRL_MODE_MAC;
+
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if ((tp->pdev->subsystem_vendor ==
@@ -10859,7 +10949,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
}
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
- (tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;
for (offset = TG3_NVM_DIR_START;
@@ -11127,6 +11217,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
if (pcie_cap != 0) {
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+
+ pcie_set_readrq(tp->pdev, 4096);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u16 lnkctl;
@@ -11307,9 +11400,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
+ tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
+ }
+
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
* GPIO1 driven high will bring 5700's external PHY out of reset.
* It is also used as eeprom write protect on LOMs.
@@ -12464,6 +12564,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+ if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX "Cannot find proper PCI device "
+ "base address for APE, aborting.\n");
+ err = -ENODEV;
+ goto err_out_iounmap;
+ }
+
+ tg3reg_base = pci_resource_start(pdev, 2);
+ tg3reg_len = pci_resource_len(pdev, 2);
+
+ tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
+ if (tp->aperegs == 0UL) {
+ printk(KERN_ERR PFX "Cannot map APE registers, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ tg3_ape_lock_init(tp);
+ }
+
/*
* Reset chip in case UNDI or EFI driver did not shutdown
* DMA self test will enable WDMAC and we'll see (spurious)
@@ -12478,7 +12600,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
err = tg3_test_dma(tp);
if (err) {
printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
- goto err_out_iounmap;
+ goto err_out_apeunmap;
}
/* Tigon3 can do ipv4 only... and some chips have buggy
@@ -12501,28 +12623,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_init_coal(tp);
- if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
- if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find proper PCI device "
- "base address for APE, aborting.\n");
- err = -ENODEV;
- goto err_out_iounmap;
- }
-
- tg3reg_base = pci_resource_start(pdev, 2);
- tg3reg_len = pci_resource_len(pdev, 2);
-
- tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
- if (tp->aperegs == 0UL) {
- printk(KERN_ERR PFX "Cannot map APE registers, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_out_iounmap;
- }
-
- tg3_ape_lock_init(tp);
- }
-
pci_set_drvdata(pdev, dev);
err = register_netdev(dev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 1d5b2a3dd29..da18fb22071 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -109,6 +109,9 @@
#define CHIPREV_ID_5714_A2 0x9002
#define CHIPREV_ID_5906_A1 0xc001
#define CHIPREV_ID_5784_A0 0x5784000
+#define CHIPREV_ID_5784_A1 0x5784001
+#define CHIPREV_ID_5761_A0 0x5761000
+#define CHIPREV_ID_5761_A1 0x5761001
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00
@@ -856,7 +859,31 @@
#define CPMU_CTRL_LINK_IDLE_MODE 0x00000200
#define CPMU_CTRL_LINK_AWARE_MODE 0x00000400
#define CPMU_CTRL_LINK_SPEED_MODE 0x00004000
-/* 0x3604 --> 0x365c unused */
+#define TG3_CPMU_LSPD_10MB_CLK 0x00003604
+#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000
+#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000
+/* 0x3608 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c
+#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000
+#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000
+#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000
+#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610
+#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000
+#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC 0x0000361c
+#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000
+#define CPMU_HST_ACC_MACCLK_6_25 0x00130000
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_STAT 0x00003630
+#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000
+#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000
+#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000
+#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000
+/* 0x3634 --> 0x365c unused */
#define TG3_CPMU_MUTEX_REQ 0x0000365c
#define CPMU_MUTEX_REQ_DRIVER 0x00001000
@@ -1537,6 +1564,12 @@
#define TG3_EEPROM_MAGIC 0x669955aa
#define TG3_EEPROM_MAGIC_FW 0xa5000000
#define TG3_EEPROM_MAGIC_FW_MSK 0xff000000
+#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000
+#define TG3_EEPROM_SB_FORMAT_1 0x00200000
+#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000
+#define TG3_EEPROM_SB_REVISION_0 0x00000000
+#define TG3_EEPROM_SB_REVISION_2 0x00020000
+#define TG3_EEPROM_SB_REVISION_3 0x00030000
#define TG3_EEPROM_MAGIC_HW 0xabcd
#define TG3_EEPROM_MAGIC_HW_MSK 0xffff
@@ -1691,6 +1724,12 @@
#define MII_TG3_ISTAT 0x1a /* IRQ status register */
#define MII_TG3_IMASK 0x1b /* IRQ mask register */
+#define MII_TG3_MISC_SHDW 0x1c
+#define MII_TG3_MISC_SHDW_WREN 0x8000
+#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
+
/* ISTAT/IMASK event bits */
#define MII_TG3_INT_LINKCHG 0x0002
#define MII_TG3_INT_SPEEDCHG 0x0004
@@ -1747,6 +1786,8 @@
/* APE convenience enumerations. */
#define TG3_APE_LOCK_MEM 4
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+
/* There are two ways to manage the TX descriptors on the tigon3.
* Either the descriptors are in host DMA'able memory, or they
@@ -2352,6 +2393,7 @@ struct tg3 {
u32 tg3_flags3;
#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
#define TG3_FLG3_ENABLE_APE 0x00000002
+#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
struct timer_list timer;
u16 timer_counter;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 49d7a290dbb..20ac1503021 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -24,8 +24,7 @@ config DE2104X
will say Y here.) Do read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called de2104x.
config TULIP
@@ -42,8 +41,7 @@ config TULIP
will say Y here.) Do read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called tulip.
config TULIP_MWI
@@ -104,8 +102,7 @@ config DE4X5
information is contained in
<file:Documentation/networking/de4x5.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called de4x5.
config WINBOND_840
@@ -129,8 +126,7 @@ config DM9102
(Ethernet) card, say Y. Some information is contained in the file
<file:Documentation/networking/dmfe.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called dmfe.
config ULI526X
@@ -141,8 +137,7 @@ config ULI526X
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
(<http://www.uli.com.tw/>).
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called uli526x.
config PCMCIA_XIRCOM
@@ -154,8 +149,7 @@ config PCMCIA_XIRCOM
as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
ASIX.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called xircom_cb. If unsure, say N.
config PCMCIA_XIRTULIP
@@ -168,8 +162,7 @@ config PCMCIA_XIRTULIP
as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
ASIX.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called xircom_tulip_cb. If unsure, say N.
endif # NET_TULIP
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index ca90566d5bc..b4891caeae5 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -2118,8 +2118,8 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state)
pci_enable_wake(pci_dev, PCI_D3cold, 1);
/* Power down device*/
- pci_set_power_state(pci_dev, pci_choose_state (pci_dev,state));
pci_save_state(pci_dev);
+ pci_set_power_state(pci_dev, pci_choose_state (pci_dev, state));
return 0;
}
@@ -2129,8 +2129,8 @@ static int dmfe_resume(struct pci_dev *pci_dev)
struct net_device *dev = pci_get_drvdata(pci_dev);
u32 tmp;
- pci_restore_state(pci_dev);
pci_set_power_state(pci_dev, PCI_D0);
+ pci_restore_state(pci_dev);
/* Re-initilize DM910X board */
dmfe_init_dm910x(dev);
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index a3ff270593f..7f689907ac2 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1460,6 +1460,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+ (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+ (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
upsmr |= UPSMR_RPM;
switch (ugeth->max_speed) {
@@ -1557,6 +1559,8 @@ static void adjust_link(struct net_device *dev)
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+ (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+ (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
if (phydev->speed == SPEED_10)
upsmr |= UPSMR_R10M;
@@ -3795,6 +3799,10 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type)
return PHY_INTERFACE_MODE_RGMII;
if (strcasecmp(phy_connection_type, "rgmii-id") == 0)
return PHY_INTERFACE_MODE_RGMII_ID;
+ if (strcasecmp(phy_connection_type, "rgmii-txid") == 0)
+ return PHY_INTERFACE_MODE_RGMII_TXID;
+ if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0)
+ return PHY_INTERFACE_MODE_RGMII_RXID;
if (strcasecmp(phy_connection_type, "rtbi") == 0)
return PHY_INTERFACE_MODE_RTBI;
@@ -3889,6 +3897,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_TBI:
case PHY_INTERFACE_MODE_RTBI:
max_speed = SPEED_1000;
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 5a96d74e4ce..a12c9c41b21 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -93,13 +93,9 @@ config USB_RTL8150
To compile this driver as a module, choose M here: the
module will be called rtl8150.
-config USB_USBNET_MII
- tristate
- default n
-
config USB_USBNET
tristate "Multi-purpose USB Networking Framework"
- select MII if USB_USBNET_MII != n
+ select MII
---help---
This driver supports several kinds of network links over USB,
with "minidrivers" built around a common network driver core
@@ -135,7 +131,6 @@ config USB_NET_AX8817X
tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
depends on USB_USBNET && NET_ETHERNET
select CRC32
- select USB_USBNET_MII
default y
help
This option adds support for ASIX AX88xxx based USB 2.0
@@ -190,7 +185,6 @@ config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET
select CRC32
- select USB_USBNET_MII
help
This option adds support for Davicom DM9601 based USB 1.1
10/100 Ethernet adapters.
@@ -225,7 +219,6 @@ config USB_NET_PLUSB
config USB_NET_MCS7830
tristate "MosChip MCS7830 based Ethernet adapters"
depends on USB_USBNET
- select USB_USBNET_MII
help
Choose this option if you're using a 10/100 Ethernet USB2
adapter based on the MosChip 7830 controller. This includes
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 2c685734b7a..1ffdd106f4c 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -94,7 +94,7 @@ static void dm_write_async_callback(struct urb *urb)
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
if (urb->status < 0)
- printk(KERN_DEBUG "dm_write_async_callback() failed with %d",
+ printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n",
urb->status);
kfree(req);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index acd5f1c0e63..8ed1fc5cbc7 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -683,9 +683,6 @@ done_nopm:
* they'll probably want to use this base set.
*/
-#if defined(CONFIG_MII) || defined(CONFIG_MII_MODULE)
-#define HAVE_MII
-
int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
@@ -744,8 +741,6 @@ int usbnet_nway_reset(struct net_device *net)
}
EXPORT_SYMBOL_GPL(usbnet_nway_reset);
-#endif /* HAVE_MII */
-
void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
{
struct usbnet *dev = netdev_priv(net);
@@ -776,12 +771,10 @@ EXPORT_SYMBOL_GPL(usbnet_set_msglevel);
/* drivers may override default ethtool_ops in their bind() routine */
static struct ethtool_ops usbnet_ethtool_ops = {
-#ifdef HAVE_MII
.get_settings = usbnet_get_settings,
.set_settings = usbnet_set_settings,
.get_link = usbnet_get_link,
.nway_reset = usbnet_nway_reset,
-#endif
.get_drvinfo = usbnet_get_drvinfo,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 5c4a92de9a0..35cd65d6b9e 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1242,6 +1242,9 @@ static int velocity_rx_refill(struct velocity_info *vptr)
static int velocity_init_rd_ring(struct velocity_info *vptr)
{
int ret;
+ int mtu = vptr->dev->mtu;
+
+ vptr->rx_buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32;
vptr->rd_info = kcalloc(vptr->options.numrx,
sizeof(struct velocity_rd_info), GFP_KERNEL);
@@ -1898,8 +1901,6 @@ static int velocity_open(struct net_device *dev)
struct velocity_info *vptr = netdev_priv(dev);
int ret;
- vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);
-
ret = velocity_init_rings(vptr);
if (ret < 0)
goto out;
@@ -1963,6 +1964,11 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
+ if (!netif_running(dev)) {
+ dev->mtu = new_mtu;
+ return 0;
+ }
+
if (new_mtu != oldmtu) {
spin_lock_irqsave(&vptr->lock, flags);
@@ -1973,12 +1979,6 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
velocity_free_rd_ring(vptr);
dev->mtu = new_mtu;
- if (new_mtu > 8192)
- vptr->rx_buf_sz = 9 * 1024;
- else if (new_mtu > 4096)
- vptr->rx_buf_sz = 8192;
- else
- vptr->rx_buf_sz = 4 * 1024;
ret = velocity_init_rd_ring(vptr);
if (ret < 0)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index e396c9d2af8..5413dbf3d4a 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -146,6 +146,7 @@ static void try_fill_recv(struct virtnet_info *vi)
struct scatterlist sg[1+MAX_SKB_FRAGS];
int num, err;
+ sg_init_table(sg, 1+MAX_SKB_FRAGS);
for (;;) {
skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
if (unlikely(!skb))
@@ -197,8 +198,8 @@ again:
if (vi->num < vi->max / 2)
try_fill_recv(vi);
- /* All done? */
- if (!skb) {
+ /* Out of packets? */
+ if (received < budget) {
netif_rx_complete(vi->dev, napi);
if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
&& netif_rx_reschedule(vi->dev, napi))
@@ -231,6 +232,8 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
DECLARE_MAC_BUF(mac);
+ sg_init_table(sg, 1+MAX_SKB_FRAGS);
+
pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest));
free_old_xmit_skbs(vi);
@@ -401,8 +404,12 @@ free:
static void virtnet_remove(struct virtio_device *vdev)
{
- unregister_netdev(vdev->priv);
- free_netdev(vdev->priv);
+ struct virtnet_info *vi = vdev->priv;
+
+ vdev->config->del_vq(vi->svq);
+ vdev->config->del_vq(vi->rvq);
+ unregister_netdev(vi->dev);
+ free_netdev(vi->dev);
}
static struct virtio_device_id id_table[] = {
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index c48b1cc63fd..1e89d4de1bb 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -719,12 +719,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
return 0;
case SIOCSIFHWADDR:
return -EINVAL;
- /* Allow stty to read, but not set, the serial port */
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(tty, file, cmd, arg);
default:
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(tty, file, cmd, arg);
}
}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index dae5c8d5a31..2b733c58291 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -325,7 +325,7 @@ config HERMES
Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
- PRO/Wireless, and Symbol Spectrum24 High Rate amongst others.
+ IPW2011, and Symbol Spectrum24 High Rate amongst others.
This option includes the guts of the driver, but in order to
actually use a card you will also need to enable support for PCMCIA
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index e3c573e56b6..fdbc351ac33 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -61,16 +61,18 @@ config B43_PCMCIA
If unsure, say N.
-# LED support
+# This config option automatically enables b43 LEDS support,
+# if it's possible.
config B43_LEDS
bool
- depends on B43 && MAC80211_LEDS
+ depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
default y
-# RFKILL support
+# This config option automatically enables b43 RFKILL support,
+# if it's possible.
config B43_RFKILL
bool
- depends on B43 && RFKILL && RFKILL_INPUT && INPUT_POLLDEV
+ depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43)
default y
config B43_DEBUG
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 734e70e1a06..ef0075d9f9c 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -128,7 +128,7 @@ static ssize_t shm_read_file(struct b43_wldev *dev,
__le16 *le16buf = (__le16 *)buf;
for (i = 0; i < 0x1000; i++) {
- if (bufsize <= 0)
+ if (bufsize < sizeof(tmp))
break;
tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i);
le16buf[i] = cpu_to_le16(tmp);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5058e60e570..b45eecc53c4 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1566,7 +1566,7 @@ static void b43_release_firmware(struct b43_wldev *dev)
static void b43_print_fw_helptext(struct b43_wl *wl)
{
b43err(wl, "You must go to "
- "http://linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware "
+ "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "
"and download the correct firmware (version 4).\n");
}
@@ -2985,6 +2985,16 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
if (b43_status(dev) < B43_STAT_STARTED)
return;
+
+ /* Disable and sync interrupts. We must do this before than
+ * setting the status to INITIALIZED, as the interrupt handler
+ * won't care about IRQs then. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
+ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43_synchronize_irq(dev);
+
b43_set_status(dev, B43_STAT_INITIALIZED);
mutex_unlock(&wl->mutex);
@@ -2995,13 +3005,6 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy.
- /* Disable and sync interrupts. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
- b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43_synchronize_irq(dev);
-
b43_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43dbg(wl, "Wireless interface stopped\n");
@@ -3661,7 +3664,6 @@ static int b43_setup_modes(struct b43_wldev *dev,
static void b43_wireless_core_detach(struct b43_wldev *dev)
{
- b43_rfkill_free(dev);
/* We release firmware that late to not be required to re-request
* is all the time when we reinit the core. */
b43_release_firmware(dev);
@@ -3747,7 +3749,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
if (!wl->current_dev)
wl->current_dev = dev;
INIT_WORK(&dev->restart_work, b43_chip_reset);
- b43_rfkill_alloc(dev);
b43_radio_turn_off(dev, 1);
b43_switch_analog(dev, 0);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index b242a9a90dd..b79a6bd5396 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -65,12 +65,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
tuple_t tuple;
cisparse_t parse;
int err = -ENOMEM;
- int res;
+ int res = 0;
unsigned char buf[64];
ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
if (!ssb)
- goto out;
+ goto out_error;
err = -ENODEV;
tuple.DesiredTuple = CISTPL_CONFIG;
@@ -96,10 +96,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
dev->io.NumPorts2 = 0;
dev->io.Attributes2 = 0;
- win.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
+ win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM |
+ WIN_ENABLE | WIN_DATA_WIDTH_16 |
+ WIN_USE_WAIT;
win.Base = 0;
win.Size = SSB_CORE_SIZE;
- win.AccessSpeed = 1000;
+ win.AccessSpeed = 250;
res = pcmcia_request_window(&dev, &win, &dev->win);
if (res != CS_SUCCESS)
goto err_kfree_ssb;
@@ -108,21 +110,34 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
mem.Page = 0;
res = pcmcia_map_mem_page(dev->win, &mem);
if (res != CS_SUCCESS)
- goto err_kfree_ssb;
+ goto err_disable;
+
+ dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED;
+ dev->irq.IRQInfo1 = IRQ_LEVEL_ID | IRQ_SHARE_ID;
+ dev->irq.Handler = NULL; /* The handler is registered later. */
+ dev->irq.Instance = NULL;
+ res = pcmcia_request_irq(dev, &dev->irq);
+ if (res != CS_SUCCESS)
+ goto err_disable;
res = pcmcia_request_configuration(dev, &dev->conf);
if (res != CS_SUCCESS)
goto err_disable;
err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
+ if (err)
+ goto err_disable;
dev->priv = ssb;
- out:
- return err;
- err_disable:
+ return 0;
+
+err_disable:
pcmcia_disable_device(dev);
- err_kfree_ssb:
+err_kfree_ssb:
kfree(ssb);
+out_error:
+ printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
+ res, err);
return err;
}
@@ -131,22 +146,21 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
struct ssb_bus *ssb = dev->priv;
ssb_bus_unregister(ssb);
- pcmcia_release_window(dev->win);
pcmcia_disable_device(dev);
kfree(ssb);
dev->priv = NULL;
}
static struct pcmcia_driver b43_pcmcia_driver = {
- .owner = THIS_MODULE,
- .drv = {
- .name = "b43-pcmcia",
- },
- .id_table = b43_pcmcia_tbl,
- .probe = b43_pcmcia_probe,
- .remove = b43_pcmcia_remove,
- .suspend = b43_pcmcia_suspend,
- .resume = b43_pcmcia_resume,
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = "b43-pcmcia",
+ },
+ .id_table = b43_pcmcia_tbl,
+ .probe = b43_pcmcia_probe,
+ .remove = __devexit_p(b43_pcmcia_remove),
+ .suspend = b43_pcmcia_suspend,
+ .resume = b43_pcmcia_resume,
};
int b43_pcmcia_init(void)
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
index 3d4ed647c31..7ff091e69f0 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy.c
@@ -2214,7 +2214,7 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
}
dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
if (dyn_tssi2dbm == NULL) {
- b43err(dev->wl, "Could not allocate memory"
+ b43err(dev->wl, "Could not allocate memory "
"for tssi2dbm table\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 800e0a61a7f..9b1f905ffbf 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -47,32 +47,35 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
struct b43_wldev *dev = poll_dev->private;
struct b43_wl *wl = dev->wl;
bool enabled;
+ bool report_change = 0;
mutex_lock(&wl->mutex);
B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
enabled = b43_is_hw_radio_enabled(dev);
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
+ report_change = 1;
b43info(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
- mutex_unlock(&wl->mutex);
+ }
+ mutex_unlock(&wl->mutex);
+
+ if (unlikely(report_change))
input_report_key(poll_dev->input, KEY_WLAN, enabled);
- } else
- mutex_unlock(&wl->mutex);
}
-/* Called when the RFKILL toggled in software.
- * This is called without locking. */
+/* Called when the RFKILL toggled in software. */
static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
{
struct b43_wldev *dev = data;
struct b43_wl *wl = dev->wl;
int err = 0;
- mutex_lock(&wl->mutex);
- if (b43_status(dev) < B43_STAT_INITIALIZED)
- goto out_unlock;
+ if (!wl->rfkill.registered)
+ return 0;
+ mutex_lock(&wl->mutex);
+ B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
switch (state) {
case RFKILL_STATE_ON:
if (!dev->radio_hw_enable) {
@@ -89,7 +92,6 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
b43_radio_turn_off(dev, 0);
break;
}
-
out_unlock:
mutex_unlock(&wl->mutex);
@@ -98,11 +100,11 @@ out_unlock:
char * b43_rfkill_led_name(struct b43_wldev *dev)
{
- struct b43_wl *wl = dev->wl;
+ struct b43_rfkill *rfk = &(dev->wl->rfkill);
- if (!wl->rfkill.rfkill)
+ if (!rfk->registered)
return NULL;
- return rfkill_get_led_name(wl->rfkill.rfkill);
+ return rfkill_get_led_name(rfk->rfkill);
}
void b43_rfkill_init(struct b43_wldev *dev)
@@ -111,53 +113,13 @@ void b43_rfkill_init(struct b43_wldev *dev)
struct b43_rfkill *rfk = &(wl->rfkill);
int err;
- if (rfk->rfkill) {
- err = rfkill_register(rfk->rfkill);
- if (err) {
- b43warn(wl, "Failed to register RF-kill button\n");
- goto err_free_rfk;
- }
- }
- if (rfk->poll_dev) {
- err = input_register_polled_device(rfk->poll_dev);
- if (err) {
- b43warn(wl, "Failed to register RF-kill polldev\n");
- goto err_free_polldev;
- }
- }
-
- return;
-err_free_rfk:
- rfkill_free(rfk->rfkill);
- rfk->rfkill = NULL;
-err_free_polldev:
- input_free_polled_device(rfk->poll_dev);
- rfk->poll_dev = NULL;
-}
-
-void b43_rfkill_exit(struct b43_wldev *dev)
-{
- struct b43_rfkill *rfk = &(dev->wl->rfkill);
-
- if (rfk->poll_dev)
- input_unregister_polled_device(rfk->poll_dev);
- if (rfk->rfkill)
- rfkill_unregister(rfk->rfkill);
-}
-
-void b43_rfkill_alloc(struct b43_wldev *dev)
-{
- struct b43_wl *wl = dev->wl;
- struct b43_rfkill *rfk = &(wl->rfkill);
+ rfk->registered = 0;
+ rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
+ if (!rfk->rfkill)
+ goto out_error;
snprintf(rfk->name, sizeof(rfk->name),
"b43-%s", wiphy_name(wl->hw->wiphy));
-
- rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
- if (!rfk->rfkill) {
- b43warn(wl, "Failed to allocate RF-kill button\n");
- return;
- }
rfk->rfkill->name = rfk->name;
rfk->rfkill->state = RFKILL_STATE_ON;
rfk->rfkill->data = dev;
@@ -165,18 +127,45 @@ void b43_rfkill_alloc(struct b43_wldev *dev)
rfk->rfkill->user_claim_unsupported = 1;
rfk->poll_dev = input_allocate_polled_device();
- if (rfk->poll_dev) {
- rfk->poll_dev->private = dev;
- rfk->poll_dev->poll = b43_rfkill_poll;
- rfk->poll_dev->poll_interval = 1000; /* msecs */
- } else
- b43warn(wl, "Failed to allocate RF-kill polldev\n");
+ if (!rfk->poll_dev)
+ goto err_free_rfk;
+ rfk->poll_dev->private = dev;
+ rfk->poll_dev->poll = b43_rfkill_poll;
+ rfk->poll_dev->poll_interval = 1000; /* msecs */
+
+ err = rfkill_register(rfk->rfkill);
+ if (err)
+ goto err_free_polldev;
+ err = input_register_polled_device(rfk->poll_dev);
+ if (err)
+ goto err_unreg_rfk;
+
+ rfk->registered = 1;
+
+ return;
+err_unreg_rfk:
+ rfkill_unregister(rfk->rfkill);
+err_free_polldev:
+ input_free_polled_device(rfk->poll_dev);
+ rfk->poll_dev = NULL;
+err_free_rfk:
+ rfkill_free(rfk->rfkill);
+ rfk->rfkill = NULL;
+out_error:
+ rfk->registered = 0;
+ b43warn(wl, "RF-kill button init failed\n");
}
-void b43_rfkill_free(struct b43_wldev *dev)
+void b43_rfkill_exit(struct b43_wldev *dev)
{
struct b43_rfkill *rfk = &(dev->wl->rfkill);
+ if (!rfk->registered)
+ return;
+ rfk->registered = 0;
+
+ input_unregister_polled_device(rfk->poll_dev);
+ rfkill_unregister(rfk->rfkill);
input_free_polled_device(rfk->poll_dev);
rfk->poll_dev = NULL;
rfkill_free(rfk->rfkill);
diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h
index 29544e8c9e5..adacf936d81 100644
--- a/drivers/net/wireless/b43/rfkill.h
+++ b/drivers/net/wireless/b43/rfkill.h
@@ -15,14 +15,14 @@ struct b43_rfkill {
struct rfkill *rfkill;
/* The poll device for the RFKILL input button */
struct input_polled_dev *poll_dev;
+ /* Did initialization succeed? Used for freeing. */
+ bool registered;
/* The unique name of this rfkill switch */
- char name[32];
+ char name[sizeof("b43-phy4294967295")];
};
-/* All the init functions return void, because we are not interested
+/* The init function returns void, because we are not interested
* in failing the b43 init process when rfkill init failed. */
-void b43_rfkill_alloc(struct b43_wldev *dev);
-void b43_rfkill_free(struct b43_wldev *dev);
void b43_rfkill_init(struct b43_wldev *dev);
void b43_rfkill_exit(struct b43_wldev *dev);
@@ -36,12 +36,6 @@ struct b43_rfkill {
/* empty */
};
-static inline void b43_rfkill_alloc(struct b43_wldev *dev)
-{
-}
-static inline void b43_rfkill_free(struct b43_wldev *dev)
-{
-}
static inline void b43_rfkill_init(struct b43_wldev *dev)
{
}
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index eefa6fb7968..619b4534ef0 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -124,7 +124,7 @@ static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufs
__le16 *le16buf = (__le16 *)buf;
for (i = 0; i < 0x1000; i++) {
- if (bufsize <= 0)
+ if (bufsize < sizeof(tmp))
break;
tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 2 * i);
le16buf[i] = cpu_to_le16(tmp);
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 8cb3dc4c474..83161d9af81 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -996,7 +996,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
err = ssb_dma_set_mask(dev->dev, dmamask);
if (err) {
-#ifdef BCM43XX_PIO
+#ifdef CONFIG_B43LEGACY_PIO
b43legacywarn(dev->wl, "DMA for this device not supported. "
"Falling back to PIO\n");
dev->__using_pio = 1;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index f0e56dfc9ec..32d5e1785bd 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1419,7 +1419,7 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev)
static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
{
b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/"
- "Drivers/bcm43xx#devicefirmware "
+ "Drivers/b43#devicefirmware "
"and download the correct firmware (version 3).\n");
}
@@ -2781,6 +2781,17 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
return;
+
+ /* Disable and sync interrupts. We must do this before than
+ * setting the status to INITIALIZED, as the interrupt handler
+ * won't care about IRQs then. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ dev->irq_savedstate = b43legacy_interrupt_disable(dev,
+ B43legacy_IRQ_ALL);
+ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43legacy_synchronize_irq(dev);
+
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
mutex_unlock(&wl->mutex);
@@ -2791,14 +2802,6 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
- /* Disable and sync interrupts. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- dev->irq_savedstate = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
- b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43legacy_synchronize_irq(dev);
-
b43legacy_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43legacydbg(wl, "Wireless interface stopped\n");
@@ -3332,7 +3335,7 @@ out_mutex_unlock:
return err;
}
-void b43legacy_stop(struct ieee80211_hw *hw)
+static void b43legacy_stop(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 22a4b3d0186..491e518e4ae 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -2020,7 +2020,7 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
phy->idle_tssi = 62;
dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
if (dyn_tssi2dbm == NULL) {
- b43legacyerr(dev->wl, "Could not allocate memory"
+ b43legacyerr(dev->wl, "Could not allocate memory "
"for tssi2dbm table\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e34870..af3de334365 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -2149,7 +2149,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
}
dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
if (dyn_tssi2dbm == NULL) {
- printk(KERN_ERR PFX "Could not allocate memory"
+ printk(KERN_ERR PFX "Could not allocate memory "
"for tssi2dbm table\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 7da3664b851..fc876ba1857 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -444,7 +444,7 @@ static int prism2_pci_resume(struct pci_dev *pdev)
MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
-static struct pci_driver prism2_pci_drv_id = {
+static struct pci_driver prism2_pci_driver = {
.name = "hostap_pci",
.id_table = prism2_pci_id_table,
.probe = prism2_pci_probe,
@@ -458,13 +458,13 @@ static struct pci_driver prism2_pci_drv_id = {
static int __init init_prism2_pci(void)
{
- return pci_register_driver(&prism2_pci_drv_id);
+ return pci_register_driver(&prism2_pci_driver);
}
static void __exit exit_prism2_pci(void)
{
- pci_unregister_driver(&prism2_pci_drv_id);
+ pci_unregister_driver(&prism2_pci_driver);
}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 8d53d08b969..fc6cdd8086c 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1267,7 +1267,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv)
IPW2100_INTA_FATAL_ERROR |
IPW2100_INTA_PARITY_ERROR);
}
- } while (i--);
+ } while (--i);
/* Clear out any pending INTAs since we aren't supposed to have
* interrupts enabled at this point... */
@@ -1339,7 +1339,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
break;
- } while (i--);
+ } while (--i);
priv->status &= ~STATUS_RESET_PENDING;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 262ab0b5582..c48b1b537d2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -71,19 +71,19 @@ struct iwl_rate_scale_priv {
};
static s32 iwl_expected_tpt_g[IWL_RATE_COUNT] = {
- 0, 0, 76, 104, 130, 168, 191, 202, 7, 13, 35, 58
+ 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
};
static s32 iwl_expected_tpt_g_prot[IWL_RATE_COUNT] = {
- 0, 0, 0, 80, 93, 113, 123, 125, 7, 13, 35, 58
+ 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
};
static s32 iwl_expected_tpt_a[IWL_RATE_COUNT] = {
- 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0, 0
+ 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
};
static s32 iwl_expected_tpt_b[IWL_RATE_COUNT] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 35, 58
+ 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
};
struct iwl_tpt_entry {
@@ -350,6 +350,10 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
sta->last_txrate = sta->txrate;
+ /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
+ if (local->hw.conf.phymode == MODE_IEEE80211A)
+ sta->last_txrate += IWL_FIRST_OFDM_RATE;
+
IWL_DEBUG_RATE("leave\n");
}
@@ -417,6 +421,33 @@ static void rs_free_sta(void *priv, void *priv_sta)
IWL_DEBUG_RATE("leave\n");
}
+
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+static int rs_adjust_next_rate(struct iwl_priv *priv, int rate)
+{
+ int next_rate = iwl_get_prev_ieee_rate(rate);
+
+ switch (priv->phymode) {
+ case MODE_IEEE80211A:
+ if (rate == IWL_RATE_12M_INDEX)
+ next_rate = IWL_RATE_9M_INDEX;
+ else if (rate == IWL_RATE_6M_INDEX)
+ next_rate = IWL_RATE_6M_INDEX;
+ break;
+ case MODE_IEEE80211B:
+ if (rate == IWL_RATE_11M_INDEX_TABLE)
+ next_rate = IWL_RATE_5M_INDEX_TABLE;
+ break;
+ default:
+ break;
+ }
+
+ return next_rate;
+}
/**
* rs_tx_status - Update rate control values based on Tx results
*
@@ -479,7 +510,8 @@ static void rs_tx_status(void *priv_rate,
last_index = scale_rate_index;
} else {
current_count = priv->retry_rate;
- last_index = iwl_get_prev_ieee_rate(scale_rate_index);
+ last_index = rs_adjust_next_rate(priv,
+ scale_rate_index);
}
/* Update this rate accounting for as many retries
@@ -494,9 +526,10 @@ static void rs_tx_status(void *priv_rate,
if (retries)
scale_rate_index =
- iwl_get_prev_ieee_rate(scale_rate_index);
+ rs_adjust_next_rate(priv, scale_rate_index);
}
+
/* Update the last index window with success/failure based on ACK */
IWL_DEBUG_RATE("Update rate %d with %s.\n",
last_index,
@@ -672,7 +705,10 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
}
rate_mask = sta->supp_rates;
- index = min(sta->txrate & 0xffff, IWL_RATE_COUNT - 1);
+ index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
+
+ if (priv->phymode == (u8) MODE_IEEE80211A)
+ rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
rs_priv = (void *)sta->rate_ctrl_priv;
@@ -801,7 +837,11 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
out:
sta->last_txrate = index;
- sta->txrate = sta->last_txrate;
+ if (priv->phymode == (u8) MODE_IEEE80211A)
+ sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
+ else
+ sta->txrate = sta->last_txrate;
+
sta_info_put(sta);
IWL_DEBUG_RATE("leave: %d\n", index);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
index b926738e0ea..bec4d3ffca1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
@@ -36,10 +36,17 @@ struct iwl_rate_info {
u8 next_rs; /* next rate used in rs algo */
u8 prev_rs_tgg; /* previous rate used in TGG rs algo */
u8 next_rs_tgg; /* next rate used in TGG rs algo */
+ u8 table_rs_index; /* index in rate scale table cmd */
+ u8 prev_table_rs; /* prev in rate table cmd */
+
};
enum {
- IWL_RATE_6M_INDEX = 0,
+ IWL_RATE_1M_INDEX = 0,
+ IWL_RATE_2M_INDEX,
+ IWL_RATE_5M_INDEX,
+ IWL_RATE_11M_INDEX,
+ IWL_RATE_6M_INDEX,
IWL_RATE_9M_INDEX,
IWL_RATE_12M_INDEX,
IWL_RATE_18M_INDEX,
@@ -47,16 +54,28 @@ enum {
IWL_RATE_36M_INDEX,
IWL_RATE_48M_INDEX,
IWL_RATE_54M_INDEX,
- IWL_RATE_1M_INDEX,
- IWL_RATE_2M_INDEX,
- IWL_RATE_5M_INDEX,
- IWL_RATE_11M_INDEX,
IWL_RATE_COUNT,
IWL_RATE_INVM_INDEX,
IWL_RATE_INVALID = IWL_RATE_INVM_INDEX
};
enum {
+ IWL_RATE_6M_INDEX_TABLE = 0,
+ IWL_RATE_9M_INDEX_TABLE,
+ IWL_RATE_12M_INDEX_TABLE,
+ IWL_RATE_18M_INDEX_TABLE,
+ IWL_RATE_24M_INDEX_TABLE,
+ IWL_RATE_36M_INDEX_TABLE,
+ IWL_RATE_48M_INDEX_TABLE,
+ IWL_RATE_54M_INDEX_TABLE,
+ IWL_RATE_1M_INDEX_TABLE,
+ IWL_RATE_2M_INDEX_TABLE,
+ IWL_RATE_5M_INDEX_TABLE,
+ IWL_RATE_11M_INDEX_TABLE,
+ IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX,
+};
+
+enum {
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
IWL_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 19bcb01e278..3a45fe99a83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -54,7 +54,9 @@
IWL_RATE_##rp##M_INDEX, \
IWL_RATE_##rn##M_INDEX, \
IWL_RATE_##pp##M_INDEX, \
- IWL_RATE_##np##M_INDEX }
+ IWL_RATE_##np##M_INDEX, \
+ IWL_RATE_##r##M_INDEX_TABLE, \
+ IWL_RATE_##ip##M_INDEX_TABLE }
/*
* Parameter order:
@@ -65,6 +67,10 @@
*
*/
const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
+ IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */
+ IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */
+ IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */
+ IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */
IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11), /* 6mbps */
IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11), /* 9mbps */
IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18), /* 12mbps */
@@ -73,10 +79,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48), /* 36mbps */
IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54), /* 48mbps */
IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
- IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */
- IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */
- IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */
- IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */
};
/* 1 = enable the iwl_disable_events() function */
@@ -662,10 +664,11 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
cmd->cmd.tx.tx_flags = tx_flags;
/* OFDM */
- cmd->cmd.tx.supp_rates[0] = rate_mask & IWL_OFDM_RATES_MASK;
+ cmd->cmd.tx.supp_rates[0] =
+ ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
/* CCK */
- cmd->cmd.tx.supp_rates[1] = (rate_mask >> 8) & 0xF;
+ cmd->cmd.tx.supp_rates[1] = (rate_mask & 0xF);
IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
"cck/ofdm mask: 0x%x/0x%x\n", sta_id,
@@ -1432,7 +1435,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
/* use this channel group's 6Mbit clipping/saturation pwr,
* but cap at regulatory scan power restriction (set during init
* based on eeprom channel data) for this channel. */
- power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX]);
+ power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
/* further limit to user's max power preference.
* FIXME: Other spectrum management power limitations do not
@@ -1447,7 +1450,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
* *index*. */
power_index = ch_info->power_info[rate_index].power_table_index
- (power - ch_info->power_info
- [IWL_RATE_6M_INDEX].requested_power) * 2;
+ [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
/* store reference index that we use when adjusting *all* scan
* powers. So we can accommodate user (all channel) or spectrum
@@ -1476,7 +1479,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
*/
int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
{
- int rate_idx;
+ int rate_idx, i;
const struct iwl_channel_info *ch_info = NULL;
struct iwl_txpowertable_cmd txpower = {
.channel = priv->active_rxon.channel,
@@ -1500,20 +1503,36 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
}
/* fill cmd with power settings for all rates for current channel */
- for (rate_idx = 0; rate_idx < IWL_RATE_COUNT; rate_idx++) {
- txpower.power[rate_idx].tpc = ch_info->power_info[rate_idx].tpc;
- txpower.power[rate_idx].rate = iwl_rates[rate_idx].plcp;
+ /* Fill OFDM rate */
+ for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
+ rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) {
+
+ txpower.power[i].tpc = ch_info->power_info[i].tpc;
+ txpower.power[i].rate = iwl_rates[rate_idx].plcp;
IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
le16_to_cpu(txpower.channel),
txpower.band,
- txpower.power[rate_idx].tpc.tx_gain,
- txpower.power[rate_idx].tpc.dsp_atten,
- txpower.power[rate_idx].rate);
+ txpower.power[i].tpc.tx_gain,
+ txpower.power[i].tpc.dsp_atten,
+ txpower.power[i].rate);
+ }
+ /* Fill CCK rates */
+ for (rate_idx = IWL_FIRST_CCK_RATE;
+ rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
+ txpower.power[i].tpc = ch_info->power_info[i].tpc;
+ txpower.power[i].rate = iwl_rates[rate_idx].plcp;
+
+ IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+ le16_to_cpu(txpower.channel),
+ txpower.band,
+ txpower.power[i].tpc.tx_gain,
+ txpower.power[i].tpc.dsp_atten,
+ txpower.power[i].rate);
}
return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
- sizeof(struct iwl_txpowertable_cmd), &txpower);
+ sizeof(struct iwl_txpowertable_cmd), &txpower);
}
@@ -1549,7 +1568,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
power_info = ch_info->power_info;
/* update OFDM Txpower settings */
- for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE;
+ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
i++, ++power_info) {
int delta_idx;
@@ -1573,14 +1592,14 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
* ... all CCK power settings for a given channel are the *same*. */
if (power_changed) {
power =
- ch_info->power_info[IWL_RATE_12M_INDEX].
+ ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
/* do all CCK rates' iwl_channel_power_info structures */
- for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++) {
+ for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
power_info->requested_power = power;
power_info->base_power_index =
- ch_info->power_info[IWL_RATE_12M_INDEX].
+ ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
++power_info;
}
@@ -1674,7 +1693,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
for (scan_tbl_index = 0;
scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
s32 actual_index = (scan_tbl_index == 0) ?
- IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX;
+ IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
iwl_hw_reg_set_scan_power(priv, scan_tbl_index,
actual_index, clip_pwrs,
ch_info, a_band);
@@ -1905,19 +1924,19 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv)
for (rate_index = 0;
rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) {
switch (rate_index) {
- case IWL_RATE_36M_INDEX:
+ case IWL_RATE_36M_INDEX_TABLE:
if (i == 0) /* B/G */
*clip_pwrs = satur_pwr;
else /* A */
*clip_pwrs = satur_pwr - 5;
break;
- case IWL_RATE_48M_INDEX:
+ case IWL_RATE_48M_INDEX_TABLE:
if (i == 0)
*clip_pwrs = satur_pwr - 7;
else
*clip_pwrs = satur_pwr - 10;
break;
- case IWL_RATE_54M_INDEX:
+ case IWL_RATE_54M_INDEX_TABLE:
if (i == 0)
*clip_pwrs = satur_pwr - 9;
else
@@ -2031,7 +2050,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
}
/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
- pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX];
+ pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
power = pwr_info->requested_power +
IWL_CCK_FROM_OFDM_POWER_DIFF;
pwr_index = pwr_info->power_table_index +
@@ -2047,9 +2066,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
/* fill each CCK rate's iwl_channel_power_info structure
* NOTE: All CCK-rate Txpwrs are the same for a given chnl!
* NOTE: CCK rates start at end of OFDM rates! */
- for (rate_index = IWL_OFDM_RATES;
- rate_index < IWL_RATE_COUNT; rate_index++) {
- pwr_info = &ch_info->power_info[rate_index];
+ for (rate_index = 0;
+ rate_index < IWL_CCK_RATES; rate_index++) {
+ pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
pwr_info->requested_power = power;
pwr_info->power_table_index = pwr_index;
pwr_info->base_power_index = base_pwr_index;
@@ -2061,7 +2080,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
for (scan_tbl_index = 0;
scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
s32 actual_index = (scan_tbl_index == 0) ?
- IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX;
+ IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
iwl_hw_reg_set_scan_power(priv, scan_tbl_index,
actual_index, clip_pwrs, ch_info, a_band);
}
@@ -2139,17 +2158,20 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv)
*/
int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
{
- int rc, i;
+ int rc, i, index, prev_index;
struct iwl_rate_scaling_cmd rate_cmd = {
.reserved = {0, 0, 0},
};
struct iwl_rate_scaling_info *table = rate_cmd.table;
for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) {
- table[i].rate_n_flags =
+ index = iwl_rates[i].table_rs_index;
+
+ table[index].rate_n_flags =
iwl_hw_set_rate_n_flags(iwl_rates[i].plcp, 0);
- table[i].try_cnt = priv->retry_rate;
- table[i].next_rate_index = iwl_get_prev_ieee_rate(i);
+ table[index].try_cnt = priv->retry_rate;
+ prev_index = iwl_get_prev_ieee_rate(i);
+ table[index].next_rate_index = iwl_rates[prev_index].table_rs_index;
}
switch (priv->phymode) {
@@ -2157,26 +2179,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
IWL_DEBUG_RATE("Select A mode rate scale\n");
/* If one of the following CCK rates is used,
* have it fall back to the 6M OFDM rate */
- for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++)
- table[i].next_rate_index = IWL_FIRST_OFDM_RATE;
+ for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)
+ table[i].next_rate_index = iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
/* Don't fall back to CCK rates */
- table[IWL_RATE_12M_INDEX].next_rate_index = IWL_RATE_9M_INDEX;
+ table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE;
/* Don't drop out of OFDM rates */
- table[IWL_FIRST_OFDM_RATE].next_rate_index =
- IWL_FIRST_OFDM_RATE;
+ table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
+ iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
break;
case MODE_IEEE80211B:
IWL_DEBUG_RATE("Select B mode rate scale\n");
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
- for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE; i++)
- table[i].next_rate_index = IWL_FIRST_CCK_RATE;
+ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
+ table[i].next_rate_index = iwl_rates[IWL_FIRST_CCK_RATE].table_rs_index;
/* CCK shouldn't fall back to OFDM... */
- table[IWL_RATE_11M_INDEX].next_rate_index = IWL_RATE_5M_INDEX;
+ table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
break;
default:
@@ -2248,22 +2270,12 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
TX_CMD_FLG_TSF_MSK);
- /* supp_rates[0] == OFDM */
- tx_beacon_cmd->tx.supp_rates[0] = IWL_OFDM_BASIC_RATES_MASK;
-
- /* supp_rates[1] == CCK
- *
- * NOTE: IWL_*_RATES_MASK are not in the order that supp_rates
- * expects so we have to shift them around.
- *
- * supp_rates expects:
- * CCK rates are bit0..3
- *
- * However IWL_*_RATES_MASK has:
- * CCK rates are bit8..11
- */
+ /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
+ tx_beacon_cmd->tx.supp_rates[0] =
+ (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+
tx_beacon_cmd->tx.supp_rates[1] =
- (IWL_CCK_BASIC_RATES_MASK >> 8) & 0xF;
+ (IWL_CCK_BASIC_RATES_MASK & 0xF);
return (sizeof(struct iwl_tx_beacon_cmd) + frame_size);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4f22a7174ca..4bdf237f6ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2915,6 +2915,10 @@ static void iwl_set_rate(struct iwl_priv *priv)
int i;
hw = iwl_get_hw_mode(priv, priv->phymode);
+ if (!hw) {
+ IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+ return;
+ }
priv->active_rate = 0;
priv->active_rate_basic = 0;
@@ -4850,7 +4854,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared */
IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
- goto none;
+ goto unplugged;
}
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -4858,6 +4862,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
/* iwl_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
+unplugged:
spin_unlock(&priv->lock);
return IRQ_HANDLED;
@@ -5331,13 +5336,13 @@ static int iwl_init_geos(struct iwl_priv *priv)
/* 5.2GHz channels start after the 2.4GHz channels */
modes[A].mode = MODE_IEEE80211A;
modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
- modes[A].rates = rates;
+ modes[A].rates = &rates[4];
modes[A].num_rates = 8; /* just OFDM */
modes[A].num_channels = 0;
modes[B].mode = MODE_IEEE80211B;
modes[B].channels = channels;
- modes[B].rates = &rates[8];
+ modes[B].rates = rates;
modes[B].num_rates = 4; /* just CCK */
modes[B].num_channels = 0;
@@ -6935,13 +6940,10 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw,
DECLARE_MAC_BUF(mac);
IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
- if (conf->mac_addr)
- IWL_DEBUG_MAC80211("enter: MAC %s\n",
- print_mac(mac, conf->mac_addr));
if (priv->interface_id) {
IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
- return 0;
+ return -EOPNOTSUPP;
}
spin_lock_irqsave(&priv->lock, flags);
@@ -6950,6 +6952,12 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
+
+ if (conf->mac_addr) {
+ IWL_DEBUG_MAC80211("Set: %s\n", print_mac(mac, conf->mac_addr));
+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+ }
+
iwl_set_mode(priv, conf->type);
IWL_DEBUG_MAC80211("leave\n");
@@ -8269,6 +8277,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
iwl_hw_cancel_deferred_work(priv);
+ cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
cancel_delayed_work(&priv->post_associate);
@@ -8354,6 +8363,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-3945-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index d60adcb9bd4..8f85564ec6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3003,6 +3003,10 @@ static void iwl_set_rate(struct iwl_priv *priv)
int i;
hw = iwl_get_hw_mode(priv, priv->phymode);
+ if (!hw) {
+ IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+ return;
+ }
priv->active_rate = 0;
priv->active_rate_basic = 0;
@@ -5156,9 +5160,10 @@ static irqreturn_t iwl_isr(int irq, void *data)
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
- /* Hardware disappeared */
+ /* Hardware disappeared. It might have already raised
+ * an interrupt */
IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
- goto none;
+ goto unplugged;
}
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -5166,8 +5171,9 @@ static irqreturn_t iwl_isr(int irq, void *data)
/* iwl_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
- spin_unlock(&priv->lock);
+ unplugged:
+ spin_unlock(&priv->lock);
return IRQ_HANDLED;
none:
@@ -7324,9 +7330,6 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw,
DECLARE_MAC_BUF(mac);
IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
- if (conf->mac_addr)
- IWL_DEBUG_MAC80211("enter: MAC %s\n",
- print_mac(mac, conf->mac_addr));
if (priv->interface_id) {
IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
@@ -7339,6 +7342,11 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
+
+ if (conf->mac_addr) {
+ IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr));
+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+ }
iwl_set_mode(priv, conf->type);
IWL_DEBUG_MAC80211("leave\n");
@@ -8862,6 +8870,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
iwl_hw_cancel_deferred_work(priv);
+ cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
cancel_delayed_work(&priv->post_associate);
@@ -8955,6 +8964,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-4965-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 1cbbd96fdbd..be5cfd8402c 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -912,6 +912,10 @@ static int wlan_cmd_set_boot2_ver(wlan_private * priv,
return 0;
}
+/*
+ * Note: NEVER use libertas_queue_cmd() with addtail==0 other than for
+ * the command timer, because it does not account for queued commands.
+ */
void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
{
unsigned long flags;
@@ -941,10 +945,11 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u
spin_lock_irqsave(&adapter->driver_lock, flags);
- if (addtail)
+ if (addtail) {
list_add_tail((struct list_head *)cmdnode,
&adapter->cmdpendingq);
- else
+ adapter->nr_cmd_pending++;
+ } else
list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -1412,7 +1417,6 @@ int libertas_prepare_and_send_command(wlan_private * priv,
cmdnode->cmdwaitqwoken = 0;
libertas_queue_cmd(adapter, cmdnode, 1);
- adapter->nr_cmd_pending++;
wake_up_interruptible(&priv->waitq);
if (wait_option & CMD_OPTION_WAITFORRSP) {
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 0360cad363a..ba4fc2b3bf0 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -148,11 +148,11 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
{
int i;
- for (i = 0; i < 500; i++) {
+ for (i = 0; i < 1000; i++) {
u8 val = if_cs_read8(card, addr);
if (val == reg)
return i;
- udelay(100);
+ udelay(500);
}
return -ETIME;
}
@@ -170,7 +170,8 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
#define IF_CS_H_IC_TX_OVER 0x0001
#define IF_CS_H_IC_RX_OVER 0x0002
#define IF_CS_H_IC_DNLD_OVER 0x0004
-#define IF_CS_H_IC_HOST_EVENT 0x0008
+#define IF_CS_H_IC_POWER_DOWN 0x0008
+#define IF_CS_H_IC_HOST_EVENT 0x0010
#define IF_CS_H_IC_MASK 0x001f
#define IF_CS_H_INT_MASK 0x00000004
@@ -878,6 +879,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out3;
}
+ /* Clear any interrupt cause that happend while sending
+ * firmware/initializing card */
+ if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK);
if_cs_enable_ints(card);
/* And finally bring the card up */
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index a8e17076e7d..b24425f7488 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -182,12 +182,14 @@ static int if_sdio_handle_data(struct if_sdio_card *card,
goto out;
}
- skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+ skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN);
if (!skb) {
ret = -ENOMEM;
goto out;
}
+ skb_reserve(skb, NET_IP_ALIGN);
+
data = skb_put(skb, size);
memcpy(data, buffer, size);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 5ead08312e1..1823b48a8ba 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1165,8 +1165,6 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
#ifdef WIRELESS_EXT
dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
#endif
-#define NETIF_F_DYNALLOC 16
- dev->features |= NETIF_F_DYNALLOC;
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
dev->set_multicast_list = libertas_set_multicast_list;
@@ -1348,8 +1346,6 @@ int libertas_add_mesh(wlan_private *priv, struct device *dev)
#ifdef WIRELESS_EXT
mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
#endif
-#define NETIF_F_DYNALLOC 16
-
/* Register virtual mesh interface */
ret = register_netdev(mesh_dev);
if (ret) {
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index c6f5aa3cb46..395b7882d4d 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1528,7 +1528,7 @@ static int wlan_set_encodeext(struct net_device *dev,
&& (ext->key_len != KEY_LEN_WPA_TKIP))
|| ((alg == IW_ENCODE_ALG_CCMP)
&& (ext->key_len != KEY_LEN_WPA_AES))) {
- lbs_deb_wext("invalid size %d for key of alg"
+ lbs_deb_wext("invalid size %d for key of alg "
"type %d\n",
ext->key_len,
alg);
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 2402cb8dd32..d2fa079fbc4 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -806,7 +806,7 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {
for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i);
- printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx"
+ printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx, "
"id %c%c, hw_addr %s\n",
dev->name, dev->base_addr, dev->irq,
(u_long) ramBase,
diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c
index 755482a5a93..60d286eb0b8 100644
--- a/drivers/net/wireless/p54usb.c
+++ b/drivers/net/wireless/p54usb.c
@@ -308,7 +308,7 @@ static int p54u_read_eeprom(struct ieee80211_hw *dev)
buf = kmalloc(0x2020, GFP_KERNEL);
if (!buf) {
- printk(KERN_ERR "prism54usb: cannot allocate memory for"
+ printk(KERN_ERR "prism54usb: cannot allocate memory for "
"eeprom readback!\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index ff2d63267b1..702321c3016 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -620,7 +620,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
* up to version C the link tuning should halt after 20
* seconds.
*/
- if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
rt2x00dev->link.count > 20)
return;
@@ -630,7 +630,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
* Chipset versions C and lower should directly continue
* to the dynamic CCA tuning.
*/
- if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
goto dynamic_cca_tune;
/*
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 7cdc80a122b..50775f9234c 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -753,7 +753,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
- if (rt2x00_get_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
+ if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
reg &= ~0x0002;
} else {
@@ -1032,7 +1032,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
- int maxpacket, struct sk_buff *skb)
+ struct sk_buff *skb)
{
int length;
@@ -1041,7 +1041,7 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
* but it must _not_ be a multiple of the USB packet size.
*/
length = roundup(skb->len, 2);
- length += (2 * !(length % maxpacket));
+ length += (2 * !(length % rt2x00dev->usb_maxpacket));
return length;
}
@@ -1257,7 +1257,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
- if (rt2x00_rev(&rt2x00dev->chip, 0xffff0)) {
+ if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
@@ -1643,7 +1643,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
struct data_entry *beacon;
struct data_entry *guardian;
int pipe = usb_sndbulkpipe(usb_dev, 1);
- int max_packet = usb_maxpacket(usb_dev, pipe, 1);
int length;
/*
@@ -1672,7 +1671,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
ring->desc_size),
skb->len - ring->desc_size, control);
- length = rt2500usb_get_tx_data_len(rt2x00dev, max_packet, skb);
+ length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
skb->data, length, rt2500usb_beacondone, beacon);
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 9845e584b73..c8f16f161c2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -418,7 +418,7 @@ struct rt2x00lib_ops {
int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control);
- int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, int maxpacket,
+ int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb);
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
unsigned int queue);
@@ -599,6 +599,11 @@ struct rt2x00_dev {
u32 *rf;
/*
+ * USB Max frame size (for rt2500usb & rt73usb).
+ */
+ u16 usb_maxpacket;
+
+ /*
* Current TX power value.
*/
u16 tx_power;
@@ -751,14 +756,16 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip)
return (chipset->rf == chip);
}
-static inline u16 rt2x00_get_rev(const struct rt2x00_chip *chipset)
+static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset)
{
return chipset->rev;
}
-static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset, const u32 mask)
+static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset,
+ const u32 rev)
{
- return chipset->rev & mask;
+ return (((chipset->rev & 0xffff0) == rev) &&
+ !!(chipset->rev & 0x0000f));
}
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4a6a0bd01ff..85ea8a8e658 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -196,6 +196,14 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
+ /* FIXME: Beaconing is broken in rt2x00. */
+ if (conf->type == IEEE80211_IF_TYPE_IBSS ||
+ conf->type == IEEE80211_IF_TYPE_AP) {
+ ERROR(rt2x00dev,
+ "rt2x00 does not support Adhoc or Master mode");
+ return -EOPNOTSUPP;
+ }
+
/*
* Don't allow interfaces to be added while
* either the device has disappeared or when
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 73cc726c404..1f5675dd329 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -159,7 +159,6 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_entry *entry = rt2x00_get_data_entry(ring);
int pipe = usb_sndbulkpipe(usb_dev, 1);
- int max_packet = usb_maxpacket(usb_dev, pipe, 1);
u32 length;
if (rt2x00_ring_full(ring)) {
@@ -194,8 +193,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
* length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/
- length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev,
- max_packet, skb);
+ length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb);
/*
* Initialize URB and send the frame to the device.
@@ -490,6 +488,11 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
rt2x00dev->ops = ops;
rt2x00dev->hw = hw;
+ rt2x00dev->usb_maxpacket =
+ usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
+ if (!rt2x00dev->usb_maxpacket)
+ rt2x00dev->usb_maxpacket = 1;
+
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
goto exit_free_device;
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 46c8c0840a6..c0671c2e6e7 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1251,7 +1251,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
- int maxpacket, struct sk_buff *skb)
+ struct sk_buff *skb)
{
int length;
@@ -1260,7 +1260,7 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
* but it must _not_ be a multiple of the USB packet size.
*/
length = roundup(skb->len, 4);
- length += (4 * !(length % maxpacket));
+ length += (4 * !(length % rt2x00dev->usb_maxpacket));
return length;
}
@@ -1486,7 +1486,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt73usb_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
- if (!rt2x00_rev(&rt2x00dev->chip, 0x25730)) {
+ if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) {
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 4bd14b33186..88efe1bae58 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -2735,16 +2735,8 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file,
return -EFAULT;
return set_mac_address(strip_info, &addr);
}
- /*
- * Allow stty to read, but not set, the serial port
- */
-
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(tty, file, cmd, arg);
- break;
default:
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(tty, file, cmd, arg);
break;
}
return 0;
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index a83c3db7d18..c93d3d2640a 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -64,6 +64,8 @@ int alloc_cpu_buffers(void)
b->head_pos = 0;
b->sample_received = 0;
b->sample_lost_overflow = 0;
+ b->backtrace_aborted = 0;
+ b->sample_invalid_eip = 0;
b->cpu = i;
INIT_DELAYED_WORK(&b->work, wq_sync_buffer);
}
@@ -175,6 +177,11 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
cpu_buf->sample_received++;
+ if (pc == ESCAPE_CODE) {
+ cpu_buf->sample_invalid_eip++;
+ return 0;
+ }
+
if (nr_available_slots(cpu_buf) < 3) {
cpu_buf->sample_lost_overflow++;
return 0;
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index 49900d9e323..c66c025abe7 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -42,6 +42,7 @@ struct oprofile_cpu_buffer {
unsigned long sample_received;
unsigned long sample_lost_overflow;
unsigned long backtrace_aborted;
+ unsigned long sample_invalid_eip;
int cpu;
struct delayed_work work;
} ____cacheline_aligned;
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index f0acb661c25..d1f6d776e9e 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -26,6 +26,8 @@ void oprofile_reset_stats(void)
cpu_buf = &cpu_buffer[i];
cpu_buf->sample_received = 0;
cpu_buf->sample_lost_overflow = 0;
+ cpu_buf->backtrace_aborted = 0;
+ cpu_buf->sample_invalid_eip = 0;
}
atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
@@ -61,6 +63,8 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
&cpu_buf->sample_lost_overflow);
oprofilefs_create_ro_ulong(sb, cpudir, "backtrace_aborted",
&cpu_buf->backtrace_aborted);
+ oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip",
+ &cpu_buf->sample_invalid_eip);
}
oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index f6cc0c5b565..1ef417cca2d 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -66,7 +66,7 @@ struct slot {
char name[SLOT_NAME_SIZE];
};
-/**
+/*
* struct acpiphp_bridge - PCI bridge information
*
* for each bridge device in ACPI namespace
@@ -97,7 +97,7 @@ struct acpiphp_bridge {
};
-/**
+/*
* struct acpiphp_slot - PCI slot information
*
* PCI slot information for each *physical* PCI slot
@@ -118,7 +118,7 @@ struct acpiphp_slot {
};
-/**
+/*
* struct acpiphp_func - PCI function information
*
* PCI function information for each object in ACPI namespace
@@ -137,7 +137,7 @@ struct acpiphp_func {
u32 flags; /* see below */
};
-/**
+/*
* struct acpiphp_attention_info - device specific attention registration
*
* ACPI has no generic method of setting/getting attention status
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index a0ca63adad5..c8c263875c2 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -91,10 +91,10 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
* acpiphp_register_attention - set attention LED callback
* @info: must be completely filled with LED callbacks
*
- * Description: this is used to register a hardware specific ACPI
+ * Description: This is used to register a hardware specific ACPI
* driver that manipulates the attention LED. All the fields in
* info must be set.
- **/
+ */
int acpiphp_register_attention(struct acpiphp_attention_info *info)
{
int retval = -EINVAL;
@@ -112,10 +112,10 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info)
* acpiphp_unregister_attention - unset attention LED callback
* @info: must match the pointer used to register
*
- * Description: this is used to un-register a hardware specific acpi
+ * Description: This is used to un-register a hardware specific acpi
* driver that manipulates the attention LED. The pointer to the
* info struct must be the same as the one used to set it.
- **/
+ */
int acpiphp_unregister_attention(struct acpiphp_attention_info *info)
{
int retval = -EINVAL;
@@ -133,7 +133,6 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info)
* @hotplug_slot: slot to enable
*
* Actual tasks are done in acpiphp_enable_slot()
- *
*/
static int enable_slot(struct hotplug_slot *hotplug_slot)
{
@@ -151,7 +150,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
* @hotplug_slot: slot to disable
*
* Actual tasks are done in acpiphp_disable_slot()
- *
*/
static int disable_slot(struct hotplug_slot *hotplug_slot)
{
@@ -168,15 +166,15 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
}
- /**
- * set_attention_status - set attention LED
+/**
+ * set_attention_status - set attention LED
* @hotplug_slot: slot to set attention LED on
* @status: value to set attention LED to (0 or 1)
*
* attention status LED, so we use a callback that
* was registered with us. This allows hardware specific
* ACPI implementations to blink the light for us.
- **/
+ */
static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
{
int retval = -ENODEV;
@@ -199,7 +197,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
*
* Some platforms may not implement _STA method properly.
* In that case, the value returned may not be reliable.
- *
*/
static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
@@ -213,7 +210,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
}
- /**
+/**
* get_attention_status - get attention LED status
* @hotplug_slot: slot to get status from
* @value: returns with value of attention LED
@@ -221,8 +218,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
* ACPI doesn't have known method to determine the state
* of the attention status LED, so we use a callback that
* was registered with us. This allows hardware specific
- * ACPI implementations to determine its state
- **/
+ * ACPI implementations to determine its state.
+ */
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
int retval = -EINVAL;
@@ -244,8 +241,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
* @value: pointer to store status
*
* ACPI doesn't provide any formal means to access latch status.
- * Instead, we fake latch status from _STA
- *
+ * Instead, we fake latch status from _STA.
*/
static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
@@ -265,8 +261,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
* @value: pointer to store status
*
* ACPI doesn't provide any formal means to access adapter status.
- * Instead, we fake adapter status from _STA
- *
+ * Instead, we fake adapter status from _STA.
*/
static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 1e125b56c9a..ff1b1c71291 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -82,7 +82,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
* 2. has _PS0 method
* 3. has _PS3 method
* 4. ..
- *
*/
static int is_ejectable(acpi_handle handle)
{
@@ -986,10 +985,8 @@ static int power_off_slot(struct acpiphp_slot *slot)
/**
- * acpiphp_max_busnr - return the highest reserved bus number under
- * the given bus.
+ * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
* @bus: bus to start search with
- *
*/
static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
{
@@ -1018,7 +1015,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
/**
* acpiphp_bus_add - add a new bus to acpi subsystem
* @func: acpiphp_func of the bridge
- *
*/
static int acpiphp_bus_add(struct acpiphp_func *func)
{
@@ -1063,7 +1059,6 @@ acpiphp_bus_add_out:
/**
* acpiphp_bus_trim - trim a bus from acpi subsystem
* @handle: handle to acpi namespace
- *
*/
static int acpiphp_bus_trim(acpi_handle handle)
{
@@ -1089,7 +1084,6 @@ static int acpiphp_bus_trim(acpi_handle handle)
*
* This function should be called per *physical slot*,
* not per each slot object in ACPI namespace.
- *
*/
static int enable_device(struct acpiphp_slot *slot)
{
@@ -1185,6 +1179,7 @@ static void disable_bridges(struct pci_bus *bus)
/**
* disable_device - disable a slot
+ * @slot: ACPI PHP slot
*/
static int disable_device(struct acpiphp_slot *slot)
{
@@ -1240,14 +1235,15 @@ static int disable_device(struct acpiphp_slot *slot)
/**
* get_slot_status - get ACPI slot status
+ * @slot: ACPI PHP slot
*
- * if a slot has _STA for each function and if any one of them
- * returned non-zero status, return it
+ * If a slot has _STA for each function and if any one of them
+ * returned non-zero status, return it.
*
- * if a slot doesn't have _STA and if any one of its functions'
- * configuration space is configured, return 0x0f as a _STA
+ * If a slot doesn't have _STA and if any one of its functions'
+ * configuration space is configured, return 0x0f as a _STA.
*
- * otherwise return 0
+ * Otherwise return 0.
*/
static unsigned int get_slot_status(struct acpiphp_slot *slot)
{
@@ -1281,6 +1277,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
/**
* acpiphp_eject_slot - physically eject the slot
+ * @slot: ACPI PHP slot
*/
int acpiphp_eject_slot(struct acpiphp_slot *slot)
{
@@ -1314,6 +1311,7 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
/**
* acpiphp_check_bridge - re-enumerate devices
+ * @bridge: where to begin re-enumeration
*
* Iterate over all slots under this bridge and make sure that if a
* card is present they are enabled, and if not they are disabled.
@@ -1538,13 +1536,11 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
/**
* handle_hotplug_event_bridge - handle ACPI event on bridges
- *
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_bridge structure
*
- * handles ACPI event notification on {host,p2p} bridges
- *
+ * Handles ACPI event notification on {host,p2p} bridges.
*/
static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
{
@@ -1634,13 +1630,11 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
/**
* handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
- *
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_func structure
*
- * handles ACPI event notification on slots
- *
+ * Handles ACPI event notification on slots.
*/
static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
{
@@ -1705,7 +1699,6 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
/**
* acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
- *
*/
int __init acpiphp_glue_init(void)
{
@@ -1726,7 +1719,7 @@ int __init acpiphp_glue_init(void)
/**
* acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
*
- * This function frees all data allocated in acpiphp_glue_init()
+ * This function frees all data allocated in acpiphp_glue_init().
*/
void acpiphp_glue_exit(void)
{
@@ -1760,7 +1753,6 @@ int __init acpiphp_get_num_slots(void)
* acpiphp_for_each_slot - call function for each slot
* @fn: callback function
* @data: context to be passed to callback function
- *
*/
static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
{
@@ -1786,6 +1778,7 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
/**
* acpiphp_enable_slot - power on slot
+ * @slot: ACPI PHP slot
*/
int acpiphp_enable_slot(struct acpiphp_slot *slot)
{
@@ -1815,6 +1808,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
/**
* acpiphp_disable_slot - power off slot
+ * @slot: ACPI PHP slot
*/
int acpiphp_disable_slot(struct acpiphp_slot *slot)
{
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 56829f82be4..47d26b65e99 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -134,11 +134,11 @@ static struct acpiphp_attention_info ibm_attention_info =
* ibm_slot_from_id - workaround for bad ibm hardware
* @id: the slot number that linux refers to the slot by
*
- * Description: this method returns the aCPI slot descriptor
+ * Description: This method returns the aCPI slot descriptor
* corresponding to the Linux slot number. This descriptor
* has info about the aPCI slot id and attention status.
* This descriptor must be freed using kfree when done.
- **/
+ */
static union apci_descriptor *ibm_slot_from_id(int id)
{
int ind = 0, size;
@@ -173,9 +173,9 @@ ibm_slot_done:
* @slot: the hotplug_slot to work with
* @status: what to set the LED to (0 or 1)
*
- * Description: this method is registered with the acpiphp module as a
- * callback to do the device specific task of setting the LED status
- **/
+ * Description: This method is registered with the acpiphp module as a
+ * callback to do the device specific task of setting the LED status.
+ */
static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
{
union acpi_object args[2];
@@ -213,13 +213,13 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
* @slot: the hotplug_slot to work with
* @status: returns what the LED is set to (0 or 1)
*
- * Description: this method is registered with the acpiphp module as a
- * callback to do the device specific task of getting the LED status
+ * Description: This method is registered with the acpiphp module as a
+ * callback to do the device specific task of getting the LED status.
*
* Because there is no direct method of getting the LED status directly
* from an ACPI call, we read the aPCI table and parse out our
* slot descriptor to read the status from that.
- **/
+ */
static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
{
union apci_descriptor *ibm_slot;
@@ -245,8 +245,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
* @event: the event info (device specific)
* @context: passed context (our notification struct)
*
- * Description: this method is registered as a callback with the ACPI
- * subsystem it is called when this device has an event to notify the OS of
+ * Description: This method is registered as a callback with the ACPI
+ * subsystem it is called when this device has an event to notify the OS of.
*
* The events actually come from the device as two events that get
* synthesized into one event with data by this function. The event
@@ -256,7 +256,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
* From section 5.6.2.2 of the ACPI 2.0 spec, I understand that the OSPM will
* only re-enable the interrupt that causes this event AFTER this method
* has returned, thereby enforcing serial access for the notification struct.
- **/
+ */
static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
{
u8 detail = event & 0x0f;
@@ -279,16 +279,16 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
* ibm_get_table_from_acpi - reads the APLS buffer from ACPI
* @bufp: address to pointer to allocate for the table
*
- * Description: this method reads the APLS buffer in from ACPI and
+ * Description: This method reads the APLS buffer in from ACPI and
* stores the "stripped" table into a single buffer
- * it allocates and passes the address back in bufp
+ * it allocates and passes the address back in bufp.
*
* If NULL is passed in as buffer, this method only calculates
* the size of the table and returns that without filling
- * in the buffer
+ * in the buffer.
*
- * returns < 0 on error or the size of the table on success
- **/
+ * Returns < 0 on error or the size of the table on success.
+ */
static int ibm_get_table_from_acpi(char **bufp)
{
union acpi_object *package;
@@ -349,17 +349,18 @@ read_table_done:
/**
* ibm_read_apci_table - callback for the sysfs apci_table file
* @kobj: the kobject this binary attribute is a part of
+ * @bin_attr: struct bin_attribute for this file
* @buffer: the kernel space buffer to fill
* @pos: the offset into the file
* @size: the number of bytes requested
*
- * Description: gets registered with sysfs as the reader callback
- * to be executed when /sys/bus/pci/slots/apci_table gets read
+ * Description: Gets registered with sysfs as the reader callback
+ * to be executed when /sys/bus/pci/slots/apci_table gets read.
*
* Since we don't get notified on open and close for this file,
* things get really tricky here...
- * our solution is to only allow reading the table in all at once
- **/
+ * our solution is to only allow reading the table in all at once.
+ */
static ssize_t ibm_read_apci_table(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t size)
@@ -385,10 +386,10 @@ static ssize_t ibm_read_apci_table(struct kobject *kobj,
* @context: a pointer to our handle to fill when we find the device
* @rv: a return value to fill if desired
*
- * Description: used as a callback when calling acpi_walk_namespace
+ * Description: Used as a callback when calling acpi_walk_namespace
* to find our device. When this method returns non-zero
- * acpi_walk_namespace quits its search and returns our value
- **/
+ * acpi_walk_namespace quits its search and returns our value.
+ */
static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
u32 lvl, void *context, void **rv)
{
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index a96b739b2d3..74178875b94 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -117,12 +117,10 @@ static inline int is_slot66mhz(struct slot *slot)
/**
* detect_SMBIOS_pointer - find the System Management BIOS Table in mem region.
- *
* @begin: begin pointer for region to be scanned.
* @end: end pointer for region to be scanned.
*
- * Returns pointer to the head of the SMBIOS tables (or NULL)
- *
+ * Returns pointer to the head of the SMBIOS tables (or %NULL).
*/
static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end)
{
@@ -157,9 +155,9 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e
/**
* init_SERR - Initializes the per slot SERR generation.
+ * @ctrl: controller to use
*
* For unexpected switch opens
- *
*/
static int init_SERR(struct controller * ctrl)
{
@@ -224,14 +222,15 @@ static int pci_print_IRQ_route (void)
/**
* get_subsequent_smbios_entry: get the next entry from bios table.
- *
- * Gets the first entry if previous == NULL
- * Otherwise, returns the next entry
- * Uses global SMBIOS Table pointer
- *
+ * @smbios_start: where to start in the SMBIOS table
+ * @smbios_table: location of the SMBIOS table
* @curr: %NULL or pointer to previously returned structure
*
- * returns a pointer to an SMBIOS structure or NULL if none found
+ * Gets the first entry if previous == NULL;
+ * otherwise, returns the next entry.
+ * Uses global SMBIOS Table pointer.
+ *
+ * Returns a pointer to an SMBIOS structure or NULL if none found.
*/
static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
void __iomem *smbios_table,
@@ -272,17 +271,18 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
/**
- * get_SMBIOS_entry
- *
- * @type:SMBIOS structure type to be returned
+ * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL
+ * @smbios_start: where to start in the SMBIOS table
+ * @smbios_table: location of the SMBIOS table
+ * @type: SMBIOS structure type to be returned
* @previous: %NULL or pointer to previously returned structure
*
- * Gets the first entry of the specified type if previous == NULL
+ * Gets the first entry of the specified type if previous == %NULL;
* Otherwise, returns the next entry of the given type.
- * Uses global SMBIOS Table pointer
- * Uses get_subsequent_smbios_entry
+ * Uses global SMBIOS Table pointer.
+ * Uses get_subsequent_smbios_entry.
*
- * returns a pointer to an SMBIOS structure or %NULL if none found
+ * Returns a pointer to an SMBIOS structure or %NULL if none found.
*/
static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
void __iomem *smbios_table,
@@ -581,7 +581,9 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
/**
* cpqhp_set_attention_status - Turns the Amber LED for a slot on or off
- *
+ * @ctrl: struct controller to use
+ * @func: PCI device/function info
+ * @status: LED control flag: 1 = LED on, 0 = LED off
*/
static int
cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
@@ -621,7 +623,8 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
/**
* set_attention_status - Turns the Amber LED for a slot on or off
- *
+ * @hotplug_slot: slot to change LED on
+ * @status: LED control flag
*/
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 856d57b4d60..4018420c6f9 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -123,7 +123,7 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
}
/**
- * cpqhp_find_slot: find the struct slot of given device
+ * cpqhp_find_slot - find the struct slot of given device
* @ctrl: scan lots of this controller
* @device: the device id to find
*/
@@ -305,9 +305,8 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl)
/**
- * sort_by_size: sort nodes on the list by their length, smallest first.
+ * sort_by_size - sort nodes on the list by their length, smallest first.
* @head: list to sort
- *
*/
static int sort_by_size(struct pci_resource **head)
{
@@ -354,9 +353,8 @@ static int sort_by_size(struct pci_resource **head)
/**
- * sort_by_max_size: sort nodes on the list by their length, largest first.
+ * sort_by_max_size - sort nodes on the list by their length, largest first.
* @head: list to sort
- *
*/
static int sort_by_max_size(struct pci_resource **head)
{
@@ -403,8 +401,10 @@ static int sort_by_max_size(struct pci_resource **head)
/**
- * do_pre_bridge_resource_split: find node of resources that are unused
- *
+ * do_pre_bridge_resource_split - find node of resources that are unused
+ * @head: new list head
+ * @orig_head: original list head
+ * @alignment: max node size (?)
*/
static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **head,
struct pci_resource **orig_head, u32 alignment)
@@ -477,8 +477,9 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h
/**
- * do_bridge_resource_split: find one node of resources that aren't in use
- *
+ * do_bridge_resource_split - find one node of resources that aren't in use
+ * @head: list head
+ * @alignment: max node size (?)
*/
static struct pci_resource *do_bridge_resource_split(struct pci_resource **head, u32 alignment)
{
@@ -525,14 +526,13 @@ error:
/**
- * get_io_resource: find first node of given size not in ISA aliasing window.
+ * get_io_resource - find first node of given size not in ISA aliasing window.
* @head: list to search
* @size: size of node to find, must be a power of two.
*
- * Description: this function sorts the resource list by size and then returns
+ * Description: This function sorts the resource list by size and then returns
* returns the first node of "size" length that is not in the ISA aliasing
* window. If it finds a node larger than "size" it will split it up.
- *
*/
static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size)
{
@@ -620,7 +620,7 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
/**
- * get_max_resource: get largest node which has at least the given size.
+ * get_max_resource - get largest node which has at least the given size.
* @head: the list to search the node in
* @size: the minimum size of the node to find
*
@@ -712,7 +712,7 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
/**
- * get_resource: find resource of given size and split up larger ones.
+ * get_resource - find resource of given size and split up larger ones.
* @head: the list to search for resources
* @size: the size limit to use
*
@@ -804,14 +804,14 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
/**
- * cpqhp_resource_sort_and_combine: sort nodes by base addresses and clean up.
+ * cpqhp_resource_sort_and_combine - sort nodes by base addresses and clean up
* @head: the list to sort and clean up
*
* Description: Sorts all of the nodes in the list in ascending order by
* their base addresses. Also does garbage collection by
* combining adjacent nodes.
*
- * returns 0 if success
+ * Returns %0 if success.
*/
int cpqhp_resource_sort_and_combine(struct pci_resource **head)
{
@@ -951,9 +951,9 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
/**
* cpqhp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
+ * @busnumber: bus where new node is to be located
*
- * Returns pointer to the new node or NULL if unsuccessful
+ * Returns pointer to the new node or %NULL if unsuccessful.
*/
struct pci_func *cpqhp_slot_create(u8 busnumber)
{
@@ -986,7 +986,7 @@ struct pci_func *cpqhp_slot_create(u8 busnumber)
* slot_remove - Removes a node from the linked list of slots.
* @old_slot: slot to remove
*
- * Returns 0 if successful, !0 otherwise.
+ * Returns %0 if successful, !0 otherwise.
*/
static int slot_remove(struct pci_func * old_slot)
{
@@ -1026,7 +1026,7 @@ static int slot_remove(struct pci_func * old_slot)
* bridge_slot_remove - Removes a node from the linked list of slots.
* @bridge: bridge to remove
*
- * Returns 0 if successful, !0 otherwise.
+ * Returns %0 if successful, !0 otherwise.
*/
static int bridge_slot_remove(struct pci_func *bridge)
{
@@ -1071,7 +1071,7 @@ out:
* cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed
* @bus: bus to find
* @device: device to find
- * @index: is 0 for first function found, 1 for the second...
+ * @index: is %0 for first function found, %1 for the second...
*
* Returns pointer to the node if successful, %NULL otherwise.
*/
@@ -1115,16 +1115,13 @@ static int is_bridge(struct pci_func * func)
/**
- * set_controller_speed - set the frequency and/or mode of a specific
- * controller segment.
- *
+ * set_controller_speed - set the frequency and/or mode of a specific controller segment.
* @ctrl: controller to change frequency/mode for.
* @adapter_speed: the speed of the adapter we want to match.
* @hp_slot: the slot number where the adapter is installed.
*
- * Returns 0 if we successfully change frequency and/or mode to match the
+ * Returns %0 if we successfully change frequency and/or mode to match the
* adapter speed.
- *
*/
static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
{
@@ -1253,13 +1250,14 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
/**
* board_replaced - Called after a board has been replaced in the system.
+ * @func: PCI device/function information
+ * @ctrl: hotplug controller
*
- * This is only used if we don't have resources for hot add
- * Turns power on for the board
- * Checks to see if board is the same
- * If board is same, reconfigures it
+ * This is only used if we don't have resources for hot add.
+ * Turns power on for the board.
+ * Checks to see if board is the same.
+ * If board is same, reconfigures it.
* If board isn't same, turns it back off.
- *
*/
static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
{
@@ -1403,10 +1401,11 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
/**
* board_added - Called after a board has been added to the system.
+ * @func: PCI device/function info
+ * @ctrl: hotplug controller
*
- * Turns power on for the board
- * Configures board
- *
+ * Turns power on for the board.
+ * Configures board.
*/
static u32 board_added(struct pci_func *func, struct controller *ctrl)
{
@@ -1607,8 +1606,10 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
/**
- * remove_board - Turns off slot and LED's
- *
+ * remove_board - Turns off slot and LEDs
+ * @func: PCI device/function info
+ * @replace_flag: whether replacing or adding a new device
+ * @ctrl: target controller
*/
static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl)
{
@@ -1902,11 +1903,11 @@ static void interrupt_event_handler(struct controller *ctrl)
/**
- * cpqhp_pushbutton_thread
+ * cpqhp_pushbutton_thread - handle pushbutton events
+ * @slot: target slot (struct)
*
- * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Scheduled procedure to handle blocking stuff for the pushbuttons.
* Handles all pending events and exits.
- *
*/
void cpqhp_pushbutton_thread(unsigned long slot)
{
@@ -2137,9 +2138,10 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
}
/**
- * switch_leds: switch the leds, go from one site to the other.
+ * switch_leds - switch the leds, go from one site to the other.
* @ctrl: controller to use
* @num_of_slots: number of slots to use
+ * @work_LED: LED control value
* @direction: 1 to start from the left side, 0 to start right.
*/
static void switch_leds(struct controller *ctrl, const int num_of_slots,
@@ -2165,11 +2167,11 @@ static void switch_leds(struct controller *ctrl, const int num_of_slots,
}
/**
- * hardware_test - runs hardware tests
+ * cpqhp_hardware_test - runs hardware tests
+ * @ctrl: target controller
+ * @test_num: the number written to the "test" file in sysfs.
*
* For hot plug ctrl folks to play with.
- * test_num is the number written to the "test" file in sysfs
- *
*/
int cpqhp_hardware_test(struct controller *ctrl, int test_num)
{
@@ -2249,14 +2251,12 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
/**
* configure_new_device - Configures the PCI header information of one board.
- *
* @ctrl: pointer to controller structure
* @func: pointer to function structure
* @behind_bridge: 1 if this is a recursive call, 0 if not
* @resources: pointer to set of resource lists
*
- * Returns 0 if success
- *
+ * Returns 0 if success.
*/
static u32 configure_new_device(struct controller * ctrl, struct pci_func * func,
u8 behind_bridge, struct resource_lists * resources)
@@ -2346,15 +2346,13 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
/**
* configure_new_function - Configures the PCI header information of one device
- *
* @ctrl: pointer to controller structure
* @func: pointer to function structure
* @behind_bridge: 1 if this is a recursive call, 0 if not
* @resources: pointer to set of resource lists
*
* Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
+ * Returns 0 if success.
*/
static int configure_new_function(struct controller *ctrl, struct pci_func *func,
u8 behind_bridge,
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 027f6865d7e..d7a293e3faf 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -165,11 +165,11 @@ static void remove_slot(struct dummy_slot *dslot)
}
/**
- * Rescan slot.
- * Tries hard not to re-enable already existing devices
- * also handles scanning of subfunctions
+ * pci_rescan_slot - Rescan slot
+ * @temp: Device template. Should be set: bus and devfn.
*
- * @param temp Device template. Should be set: bus and devfn.
+ * Tries hard not to re-enable already existing devices;
+ * also handles scanning of subfunctions.
*/
static void pci_rescan_slot(struct pci_dev *temp)
{
@@ -229,10 +229,10 @@ static void pci_rescan_slot(struct pci_dev *temp)
/**
- * Rescan PCI bus.
- * call pci_rescan_slot for each possible function of the bus
+ * pci_rescan_bus - Rescan PCI bus
+ * @bus: the PCI bus to rescan
*
- * @param bus
+ * Call pci_rescan_slot for each possible function of the bus.
*/
static void pci_rescan_bus(const struct pci_bus *bus)
{
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index c8cb49c5a75..f1e0966cee9 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -208,10 +208,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
/**
* board_added - Called after a board has been added to the system.
+ * @p_slot: &slot where board is added
*
- * Turns power on for the board
- * Configures board
- *
+ * Turns power on for the board.
+ * Configures board.
*/
static int board_added(struct slot *p_slot)
{
@@ -276,8 +276,8 @@ err_exit:
}
/**
- * remove_board - Turns off slot and LED's
- *
+ * remove_board - Turns off slot and LEDs
+ * @p_slot: slot where board is being removed
*/
static int remove_board(struct slot *p_slot)
{
@@ -319,11 +319,11 @@ struct power_work_info {
};
/**
- * pciehp_pushbutton_thread
+ * pciehp_power_thread - handle pushbutton events
+ * @work: &struct work_struct describing work to be done
*
- * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Scheduled procedure to handle blocking stuff for the pushbuttons.
* Handles all pending events and exits.
- *
*/
static void pciehp_power_thread(struct work_struct *work)
{
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index deb6b5e35fe..b169b0e2647 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -100,6 +100,7 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
/**
* find_php_slot - return hotplug slot structure for device node
+ * @dn: target &device_node
*
* This routine will return the hotplug slot structure
* for a given device node. Note that built-in PCI slots
@@ -293,9 +294,8 @@ static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
* dlpar_add_slot - DLPAR add an I/O Slot
* @drc_name: drc-name of newly added slot
*
- * Make the hotplug module and the kernel aware
- * of a newly added I/O Slot.
- * Return Codes -
+ * Make the hotplug module and the kernel aware of a newly added I/O Slot.
+ * Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
* -EINVAL Slot already added
@@ -339,9 +339,9 @@ exit:
/**
* dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot
* @drc_name: drc-name of newly added slot
+ * @dn: &device_node
*
- * Remove the kernel and hotplug representations
- * of an I/O Slot.
+ * Remove the kernel and hotplug representations of an I/O Slot.
* Return Codes:
* 0 Success
* -EINVAL Vio dev doesn't exist
@@ -359,11 +359,11 @@ static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
}
/**
- * dlpar_remove_slot - DLPAR remove a PCI I/O Slot
+ * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot
* @drc_name: drc-name of newly added slot
+ * @dn: &device_node
*
- * Remove the kernel and hotplug representations
- * of a PCI I/O Slot.
+ * Remove the kernel and hotplug representations of a PCI I/O Slot.
* Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
@@ -405,8 +405,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
* dlpar_remove_slot - DLPAR remove an I/O Slot
* @drc_name: drc-name of newly added slot
*
- * Remove the kernel and hotplug representations
- * of an I/O Slot.
+ * Remove the kernel and hotplug representations of an I/O Slot.
* Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 458c08ef265..58f1a992770 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -54,10 +54,12 @@ module_param(debug, bool, 0644);
/**
* set_attention_status - set attention LED
+ * @hotplug_slot: target &hotplug_slot
+ * @value: LED control value
+ *
* echo 0 > attention -- set LED OFF
* echo 1 > attention -- set LED ON
* echo 2 > attention -- set LED ID(identify, light is blinking)
- *
*/
static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
{
@@ -99,6 +101,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
/**
* get_attention_status - get attention LED status
+ * @hotplug_slot: slot to get status
+ * @value: pointer to store status
*/
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
{
@@ -254,6 +258,11 @@ static int is_php_type(char *drc_type)
/**
* is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0
+ * @dn: target &device_node
+ * @indexes: passed to get_children_props()
+ * @names: passed to get_children_props()
+ * @types: returned from get_children_props()
+ * @power_domains:
*
* This routine will return true only if the device node is
* a hotpluggable slot. This routine will return false
@@ -279,7 +288,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
/**
* rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.
- * @dn device node of slot
+ * @dn: device node of slot
*
* This subroutine will register a hotplugable slot with the
* PCI hotplug infrastructure. This routine is typicaly called
@@ -291,7 +300,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
* routine will just return without doing anything, since embedded
* slots cannot be hotplugged.
*
- * To remove a slot, it suffices to call rpaphp_deregister_slot()
+ * To remove a slot, it suffices to call rpaphp_deregister_slot().
*/
int rpaphp_add_slot(struct device_node *dn)
{
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 54ca8650d51..0de84533cd8 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -79,6 +79,7 @@ static void set_slot_name(struct slot *slot)
/**
* rpaphp_enable_slot - record slot state, config pci device
+ * @slot: target &slot
*
* Initialize values in the slot, and the hotplug_slot info
* structures to indicate if there is a pci card plugged into
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index d2fc35598cd..eb5cac6f08a 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -231,10 +231,10 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
/**
* board_added - Called after a board has been added to the system.
+ * @p_slot: target &slot
*
- * Turns power on for the board
- * Configures board
- *
+ * Turns power on for the board.
+ * Configures board.
*/
static int board_added(struct slot *p_slot)
{
@@ -350,8 +350,8 @@ err_exit:
/**
- * remove_board - Turns off slot and LED's
- *
+ * remove_board - Turns off slot and LEDs
+ * @p_slot: target &slot
*/
static int remove_board(struct slot *p_slot)
{
@@ -397,11 +397,11 @@ struct pushbutton_work_info {
};
/**
- * shpchp_pushbutton_thread
+ * shpchp_pushbutton_thread - handle pushbutton events
+ * @work: &struct work_struct to be handled
*
- * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Scheduled procedure to handle blocking stuff for the pushbuttons.
* Handles all pending events and exits.
- *
*/
static void shpchp_pushbutton_thread(struct work_struct *work)
{
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 1b7b2812bf2..7d1877341aa 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -702,8 +702,10 @@ static int __init pci_sysfs_init(void)
sysfs_initialized = 1;
for_each_pci_dev(pdev) {
retval = pci_create_sysfs_dev_files(pdev);
- if (retval)
+ if (retval) {
+ pci_dev_put(pdev);
return retval;
+ }
}
return 0;
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 92a8469b21b..3c0d8d138f5 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -168,11 +168,11 @@ static int find_device_iter(struct device *device, void *data)
/**
* find_source_device - search through device hierarchy for source device
- * @p_dev: pointer to Root Port pci_dev data structure
+ * @parent: pointer to Root Port pci_dev data structure
* @id: device ID of agent who sends an error message to this Root Port
*
* Invoked when error is detected at the Root Port.
- **/
+ */
static struct device* find_source_device(struct pci_dev *parent, u16 id)
{
struct pci_dev *dev = parent;
@@ -286,14 +286,15 @@ static void report_resume(struct pci_dev *dev, void *data)
/**
* broadcast_error_message - handle message broadcast to downstream drivers
- * @device: pointer to from where in a hierarchy message is broadcasted down
- * @api: callback to be broadcasted
+ * @dev: pointer to from where in a hierarchy message is broadcasted down
* @state: error state
+ * @error_mesg: message to print
+ * @cb: callback to be broadcasted
*
* Invoked during error recovery process. Once being invoked, the content
* of error severity will be broadcasted to all downstream drivers in a
* hierarchy in question.
- **/
+ */
static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
enum pci_channel_state state,
char *error_mesg,
@@ -428,7 +429,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,
* Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
* error detected message to all downstream drivers within a hierarchy in
* question and return the returned code.
- **/
+ */
static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
struct pci_dev *dev,
int severity)
@@ -488,7 +489,7 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
* @info: comprehensive error information
*
* Invoked when an error being detected by Root Port.
- **/
+ */
static void handle_error_source(struct pcie_device * aerdev,
struct pci_dev *dev,
struct aer_err_info info)
@@ -521,7 +522,7 @@ static void handle_error_source(struct pcie_device * aerdev,
* @rpc: pointer to a Root Port data structure
*
* Invoked when PCIE bus loads AER service driver.
- **/
+ */
void aer_enable_rootport(struct aer_rpc *rpc)
{
struct pci_dev *pdev = rpc->rpd->port;
@@ -569,7 +570,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
* @rpc: pointer to a Root Port data structure
*
* Invoked when PCIE bus unloads AER service driver.
- **/
+ */
static void disable_root_aer(struct aer_rpc *rpc)
{
struct pci_dev *pdev = rpc->rpd->port;
@@ -590,7 +591,7 @@ static void disable_root_aer(struct aer_rpc *rpc)
* @rpc: pointer to the root port which holds an error
*
* Invoked by DPC handler to consume an error.
- **/
+ */
static struct aer_err_source* get_e_source(struct aer_rpc *rpc)
{
struct aer_err_source *e_source;
@@ -655,7 +656,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
* aer_isr_one_error - consume an error detected by root port
* @p_device: pointer to error root port service device
* @e_src: pointer to an error source
- **/
+ */
static void aer_isr_one_error(struct pcie_device *p_device,
struct aer_err_source *e_src)
{
@@ -706,7 +707,7 @@ static void aer_isr_one_error(struct pcie_device *p_device,
* @work: definition of this work item
*
* Invoked, as DPC, when root port records new detected error
- **/
+ */
void aer_isr(struct work_struct *work)
{
struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
@@ -729,7 +730,7 @@ void aer_isr(struct work_struct *work)
* @rpc: pointer to a root port device being deleted
*
* Invoked when AER service unloaded on a specific Root Port
- **/
+ */
void aer_delete_rootport(struct aer_rpc *rpc)
{
/* Disable root port AER itself */
@@ -743,7 +744,7 @@ void aer_delete_rootport(struct aer_rpc *rpc)
* @dev: pointer to AER pcie device
*
* Invoked when AER service driver is loaded.
- **/
+ */
int aer_init(struct pcie_device *dev)
{
if (aer_osc_setup(dev) && !forceload)
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index df383645e36..26057f98f72 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -217,7 +217,7 @@ static int slot_reset_iter(struct device *device, void *data)
static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
{
- pci_ers_result_t status;
+ pci_ers_result_t status = PCI_ERS_RESULT_NONE;
int retval;
/* If fatal, restore cfg space for possible link reset at upstream */
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index cd0a204d96d..3c5eb374adf 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
{
int i = 0;
int irq;
+ int p, t;
if (!valid_IRQ(gsi))
return;
@@ -82,18 +83,27 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
i < PNP_MAX_IRQ)
i++;
- if (i >= PNP_MAX_IRQ)
+ if (i >= PNP_MAX_IRQ) {
+ printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ "
+ "resources: %d \n", PNP_MAX_IRQ);
return;
-
-#ifdef CONFIG_X86
- if (gsi < 16 && (triggering != ACPI_EDGE_SENSITIVE ||
- polarity != ACPI_ACTIVE_HIGH)) {
- pnp_warn("BIOS BUG: legacy PNP IRQ %d should be edge trigger, "
- "active high", gsi);
- triggering = ACPI_EDGE_SENSITIVE;
- polarity = ACPI_ACTIVE_HIGH;
}
-#endif
+ /*
+ * in IO-APIC mode, use overrided attribute. Two reasons:
+ * 1. BIOS bug in DSDT
+ * 2. BIOS uses IO-APIC mode Interrupt Source Override
+ */
+ if (!acpi_get_override_irq(gsi, &t, &p)) {
+ t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
+ p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+
+ if (triggering != t || polarity != p) {
+ pnp_warn("IRQ %d override to %s, %s",
+ gsi, t ? "edge":"level", p ? "low":"high");
+ triggering = t;
+ polarity = p;
+ }
+ }
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
res->irq_resource[i].flags |= irq_flags(triggering, polarity);
@@ -173,6 +183,9 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
}
res->dma_resource[i].start = dma;
res->dma_resource[i].end = dma;
+ } else {
+ printk(KERN_ERR "pnpacpi: exceeded the max number of DMA "
+ "resources: %d \n", PNP_MAX_DMA);
}
}
@@ -194,6 +207,9 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
}
res->port_resource[i].start = io;
res->port_resource[i].end = io + len - 1;
+ } else {
+ printk(KERN_ERR "pnpacpi: exceeded the max number of IO "
+ "resources: %d \n", PNP_MAX_PORT);
}
}
@@ -217,6 +233,9 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
res->mem_resource[i].start = mem;
res->mem_resource[i].end = mem + len - 1;
+ } else {
+ printk(KERN_ERR "pnpacpi: exceeded the max number of mem "
+ "resources: %d\n", PNP_MAX_MEM);
}
}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 41d73a5e931..e50ebcffb96 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -367,8 +367,10 @@ int pnp_check_irq(struct pnp_dev *dev, int idx)
{
struct pci_dev *pci = NULL;
for_each_pci_dev(pci) {
- if (pci->irq == *irq)
+ if (pci->irq == *irq) {
+ pci_dev_put(pci);
return 0;
+ }
}
}
#endif
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index 746031de219..1f5a2d33bf5 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1,6 +1,6 @@
-obj-$(CONFIG_PS3_VUART) += vuart.o
+obj-$(CONFIG_PS3_VUART) += ps3-vuart.o
obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
ps3av_mod-objs += ps3av.o ps3av_cmd.o
obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
-obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
+obj-$(CONFIG_PS3_SYS_MANAGER) += ps3-sys-manager.o
obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/ps3-sys-manager.c
index 8461b08ab9f..8461b08ab9f 100644
--- a/drivers/ps3/sys-manager.c
+++ b/drivers/ps3/ps3-sys-manager.c
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/ps3-vuart.c
index 9dea585ef80..9dea585ef80 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/ps3-vuart.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index cbde770eb12..1e6715ec51e 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -36,7 +36,9 @@ config RTC_HCTOSYS_DEVICE
help
The RTC device that will be used to (re)initialize the system
clock, usually rtc0. Initialization is done when the system
- starts up, and when it resumes from a low power state.
+ starts up, and when it resumes from a low power state. This
+ device should record time in UTC, since the kernel won't do
+ timezone correction.
The driver for this RTC device must be loaded before late_initcall
functions run, so it must usually be statically linked.
@@ -133,8 +135,8 @@ config RTC_DRV_DS1307
The first seven registers on these chips hold an RTC, and other
registers may add features such as NVRAM, a trickle charger for
- the RTC/NVRAM backup power, and alarms. This driver may not
- expose all those available chip features.
+ the RTC/NVRAM backup power, and alarms. NVRAM is visible in
+ sysfs, but other chip features may not be available.
This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
@@ -445,7 +447,7 @@ config RTC_DRV_AT91RM9200
config RTC_DRV_BFIN
tristate "Blackfin On-Chip RTC"
- depends on BFIN
+ depends on BLACKFIN
help
If you say yes here you will get support for the
Blackfin On-Chip Real Time Clock.
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index 178527252c6..33c0e98243e 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -47,8 +47,8 @@ static int __init rtc_hctosys(void)
do_settimeofday(&tv);
dev_info(rtc->dev.parent,
- "setting the system clock to "
- "%d-%02d-%02d %02d:%02d:%02d (%u)\n",
+ "setting system clock to "
+ "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(unsigned int) tv.tv_sec);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index de0da545c7a..a4f56e95cf9 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -293,7 +293,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
return -EINVAL;
/* Cannot register while the char dev is in use */
- if (!(mutex_trylock(&rtc->char_lock)))
+ if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags))
return -EBUSY;
spin_lock_irq(&rtc->irq_task_lock);
@@ -303,7 +303,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
}
spin_unlock_irq(&rtc->irq_task_lock);
- mutex_unlock(&rtc->char_lock);
+ clear_bit(RTC_DEV_BUSY, &rtc->flags);
return retval;
}
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 814583bd2fe..ae1bf177d62 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -26,10 +26,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
struct rtc_device, char_dev);
const struct rtc_class_ops *ops = rtc->ops;
- /* We keep the lock as long as the device is in use
- * and return immediately if busy
- */
- if (!(mutex_trylock(&rtc->char_lock)))
+ if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags))
return -EBUSY;
file->private_data = rtc;
@@ -43,8 +40,8 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
return 0;
}
- /* something has gone wrong, release the lock */
- mutex_unlock(&rtc->char_lock);
+ /* something has gone wrong */
+ clear_bit(RTC_DEV_BUSY, &rtc->flags);
return err;
}
@@ -405,7 +402,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
if (rtc->ops->release)
rtc->ops->release(rtc->dev.parent);
- mutex_unlock(&rtc->char_lock);
+ clear_bit(RTC_DEV_BUSY, &rtc->flags);
return 0;
}
@@ -440,7 +437,6 @@ void rtc_dev_prepare(struct rtc_device *rtc)
rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id);
- mutex_init(&rtc->char_lock);
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
INIT_WORK(&rtc->uie_task, rtc_uie_task);
setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index db6f3f0d898..bc1c7fe94ad 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -89,6 +89,7 @@ enum ds_type {
struct ds1307 {
u8 reg_addr;
+ bool has_nvram;
u8 regs[8];
enum ds_type type;
struct i2c_msg msg[2];
@@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
.set_time = ds1307_set_time,
};
+/*----------------------------------------------------------------------*/
+
+#define NVRAM_SIZE 56
+
+static ssize_t
+ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client;
+ struct ds1307 *ds1307;
+ struct i2c_msg msg[2];
+ int result;
+
+ client = to_i2c_client(container_of(kobj, struct device, kobj));
+ ds1307 = i2c_get_clientdata(client);
+
+ if (unlikely(off >= NVRAM_SIZE))
+ return 0;
+ if ((off + count) > NVRAM_SIZE)
+ count = NVRAM_SIZE - off;
+ if (unlikely(!count))
+ return count;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = buf;
+
+ buf[0] = 8 + off;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = count;
+ msg[1].buf = buf;
+
+ result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2);
+ if (result != 2) {
+ dev_err(&client->dev, "%s error %d\n", "nvram read", result);
+ return -EIO;
+ }
+ return count;
+}
+
+static ssize_t
+ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client;
+ u8 buffer[NVRAM_SIZE + 1];
+ int ret;
+
+ client = to_i2c_client(container_of(kobj, struct device, kobj));
+
+ if (unlikely(off >= NVRAM_SIZE))
+ return -EFBIG;
+ if ((off + count) > NVRAM_SIZE)
+ count = NVRAM_SIZE - off;
+ if (unlikely(!count))
+ return count;
+
+ buffer[0] = 8 + off;
+ memcpy(buffer + 1, buf, count);
+
+ ret = i2c_master_send(client, buffer, count + 1);
+ return (ret < 0) ? ret : (ret - 1);
+}
+
+static struct bin_attribute nvram = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+
+ .read = ds1307_nvram_read,
+ .write = ds1307_nvram_write,
+ .size = NVRAM_SIZE,
+};
+
+/*----------------------------------------------------------------------*/
+
static struct i2c_driver ds1307_driver;
static int __devinit ds1307_probe(struct i2c_client *client)
@@ -413,6 +495,14 @@ read_rtc:
goto exit_free;
}
+ if (chip->nvram56) {
+ err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
+ if (err == 0) {
+ ds1307->has_nvram = true;
+ dev_info(&client->dev, "56 bytes nvram\n");
+ }
+ }
+
return 0;
exit_bad:
@@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client)
{
struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ if (ds1307->has_nvram)
+ sysfs_remove_bin_file(&client->dev.kobj, &nvram);
+
rtc_device_unregister(ds1307->rtc);
kfree(ds1307);
return 0;
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index bb53c09bad1..d9e848dcd45 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -291,7 +291,7 @@ static ssize_t ds1553_nvram_write(struct kobject *kobj,
static struct bin_attribute ds1553_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
},
.size = RTC_OFFSET,
.read = ds1553_nvram_read,
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index c535b78698e..2e73f0b183b 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -160,10 +160,13 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj,
static struct bin_attribute ds1742_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
},
.read = ds1742_nvram_read,
.write = ds1742_nvram_write,
+ /* REVISIT: size in sysfs won't match actual size... if it's
+ * not a constant, each RTC should have its own attribute.
+ */
};
static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 2bad1637330..cd0bbc0e803 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -353,11 +353,12 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj,
static struct bin_attribute m48t59_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.read = m48t59_nvram_read,
.write = m48t59_nvram_write,
+ .size = M48T59_NVRAM_SIZE,
};
static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 78277a118b6..8e8c8b8e81e 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -351,8 +351,10 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
- if (rtc_valid_tm(tm) < 0)
+ if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "invalid date\n");
+ rtc_time_to_tm(0, tm);
+ }
return 0;
}
@@ -588,7 +590,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
&sh_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
+ if (IS_ERR(rtc->rtc_dev)) {
ret = PTR_ERR(rtc->rtc_dev);
goto err_badmap;
}
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 8288b6b2bf2..a265da7c6ff 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -291,7 +291,7 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj,
static struct bin_attribute stk17ta8_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = RTC_OFFSET,
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 838f7ac0dc3..6db31089d2d 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -483,7 +483,7 @@ static DECLARE_WORK(css_reprobe_work, reprobe_all);
void css_schedule_reprobe(void)
{
need_reprobe = 1;
- queue_work(ccw_device_work, &css_reprobe_work);
+ queue_work(slow_path_wq, &css_reprobe_work);
}
EXPORT_SYMBOL_GPL(css_schedule_reprobe);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 8867443b806..bfad421cda6 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -1034,7 +1034,7 @@ device_trigger_reprobe(struct subchannel *sch)
if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_move_to_orphanage);
- queue_work(ccw_device_work, &cdev->private->kick_work);
+ queue_work(slow_path_wq, &cdev->private->kick_work);
} else
ccw_device_start_id(cdev, 0);
}
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index f232832f2b2..2f6bf462425 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -113,19 +113,10 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
{
struct subchannel *sch;
struct ccw1 *ccw;
- int ret;
sch = to_subchannel(cdev->dev.parent);
/* Setup sense channel program. */
ccw = cdev->private->iccws;
- if (sch->schib.pmcw.pim != 0x80) {
- /* more than one path installed. */
- ccw->cmd_code = CCW_CMD_SUSPEND_RECONN;
- ccw->cda = 0;
- ccw->count = 0;
- ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC;
- ccw++;
- }
ccw->cmd_code = CCW_CMD_SENSE_ID;
ccw->cda = (__u32) __pa (&cdev->private->senseid);
ccw->count = sizeof (struct senseid);
@@ -133,25 +124,9 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
/* Reset device status. */
memset(&cdev->private->irb, 0, sizeof(struct irb));
+ cdev->private->flags.intretry = 0;
- /* Try on every path. */
- ret = -ENODEV;
- while (cdev->private->imask != 0) {
- if ((sch->opm & cdev->private->imask) != 0 &&
- cdev->private->iretry > 0) {
- cdev->private->iretry--;
- /* Reset internal retry indication. */
- cdev->private->flags.intretry = 0;
- ret = cio_start (sch, cdev->private->iccws,
- cdev->private->imask);
- /* ret is 0, -EBUSY, -EACCES or -ENODEV */
- if (ret != -EACCES)
- return ret;
- }
- cdev->private->imask >>= 1;
- cdev->private->iretry = 5;
- }
- return ret;
+ return cio_start(sch, ccw, LPM_ANYPATH);
}
void
@@ -161,8 +136,7 @@ ccw_device_sense_id_start(struct ccw_device *cdev)
memset (&cdev->private->senseid, 0, sizeof (struct senseid));
cdev->private->senseid.cu_type = 0xFFFF;
- cdev->private->imask = 0x80;
- cdev->private->iretry = 5;
+ cdev->private->iretry = 3;
ret = __ccw_device_sense_id_start(cdev);
if (ret && ret != -EBUSY)
ccw_device_sense_id_done(cdev, ret);
@@ -278,14 +252,13 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
ccw_device_sense_id_done(cdev, ret);
break;
case -EACCES: /* channel is not operational. */
- sch->lpm &= ~cdev->private->imask;
- cdev->private->imask >>= 1;
- cdev->private->iretry = 5;
- /* fall through. */
case -EAGAIN: /* try again. */
- ret = __ccw_device_sense_id_start(cdev);
- if (ret == 0 || ret == -EBUSY)
- break;
+ cdev->private->iretry--;
+ if (cdev->private->iretry > 0) {
+ ret = __ccw_device_sense_id_start(cdev);
+ if (ret == 0 || ret == -EBUSY)
+ break;
+ }
/* fall through. */
default: /* Sense ID failed. Try asking VM. */
if (MACHINE_IS_VM) {
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 6bf3ebbe985..b3b6f654365 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -2782,35 +2782,14 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
}
/**
- * Initialize everything of the net device except the name and the
- * channel structs.
+ * Device setup function called by alloc_netdev().
+ *
+ * @param dev Device to be setup.
*/
-static struct net_device *
-ctc_init_netdevice(struct net_device * dev, int alloc_device,
- struct ctc_priv *privptr)
+void ctc_init_netdevice(struct net_device * dev)
{
- if (!privptr)
- return NULL;
-
DBF_TEXT(setup, 3, __FUNCTION__);
- if (alloc_device) {
- dev = kzalloc(sizeof(struct net_device), GFP_KERNEL);
- if (!dev)
- return NULL;
- }
-
- dev->priv = privptr;
- privptr->fsm = init_fsm("ctcdev", dev_state_names,
- dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
- dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
- if (privptr->fsm == NULL) {
- if (alloc_device)
- kfree(dev);
- return NULL;
- }
- fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
- fsm_settimer(privptr->fsm, &privptr->restart_timer);
if (dev->mtu == 0)
dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
dev->hard_start_xmit = ctc_tx;
@@ -2823,7 +2802,7 @@ ctc_init_netdevice(struct net_device * dev, int alloc_device,
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 100;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
- return dev;
+ SET_MODULE_OWNER(dev);
}
@@ -2879,14 +2858,22 @@ ctc_new_device(struct ccwgroup_device *cgdev)
"ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret);
}
- dev = ctc_init_netdevice(NULL, 1, privptr);
-
+ dev = alloc_netdev(0, "ctc%d", ctc_init_netdevice);
if (!dev) {
ctc_pr_warn("ctc_init_netdevice failed\n");
goto out;
}
+ dev->priv = privptr;
- strlcpy(dev->name, "ctc%d", IFNAMSIZ);
+ privptr->fsm = init_fsm("ctcdev", dev_state_names,
+ dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
+ dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
+ if (privptr->fsm == NULL) {
+ free_netdev(dev);
+ goto out;
+ }
+ fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
+ fsm_settimer(privptr->fsm, &privptr->restart_timer);
for (direction = READ; direction <= WRITE; direction++) {
privptr->channel[direction] =
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index 5b0932f6147..06509bff71f 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -377,7 +377,7 @@ out:
#define FLASH_RESET 0xF0
-#define FLASH_SIZE 0x200000
+#define ASD_FLASH_SIZE 0x200000
#define FLASH_DIR_COOKIE "*** ADAPTEC FLASH DIRECTORY *** "
#define FLASH_NEXT_ENTRY_OFFS 0x2000
#define FLASH_MAX_DIR_ENTRIES 32
@@ -609,7 +609,7 @@ static int asd_find_flash_dir(struct asd_ha_struct *asd_ha,
struct asd_flash_dir *flash_dir)
{
u32 v;
- for (v = 0; v < FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
+ for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
asd_read_flash_seg(asd_ha, flash_dir, v,
sizeof(FLASH_DIR_COOKIE)-1);
if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE,
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 8d0244c2e7d..7a835a35f21 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -242,16 +242,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
}
}
-static void hexdump(u8 *x, int len)
-{
- int i;
-
- printk("[ ");
- for (i = 0; i < len; i++)
- printk("%x ", x[i]);
- printk("]\n");
-}
-
static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command)
{
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
@@ -282,7 +272,8 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: queue cmd = ", drive->name);
- hexdump(pc->c, 6);
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, pc->c,
+ 6, 0);
}
rq->rq_disk = scsi->disk;
return ide_do_drive_cmd(drive, rq, ide_preempt);
@@ -337,7 +328,8 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
if (log) {
printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
- hexdump(pc->buffer,16);
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+ pc->buffer, 16, 0);
}
memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
kfree(pc->buffer);
@@ -816,10 +808,12 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
- hexdump(cmd->cmnd, cmd->cmd_len);
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+ cmd->cmnd, cmd->cmd_len, 0);
if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
- hexdump(pc->c, 12);
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+ pc->c, 12, 0);
}
}
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c
index ac67394c737..64d40a2d4d4 100644
--- a/drivers/scsi/zorro7xx.c
+++ b/drivers/scsi/zorro7xx.c
@@ -13,7 +13,10 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/zorro.h>
+
+#include <asm/amigahw.h>
#include <asm/amigaints.h>
+
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_spi.h>
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index 926f58a674a..1de098e7549 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -69,6 +69,8 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "CTL3001", 0 },
/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
{ "CTL3011", 0 },
+ /* Davicom ISA 33.6K Modem */
+ { "DAV0336", 0 },
/* Creative */
/* Creative Modem Blaster Flash56 DI5601-1 */
{ "DMB1032", 0 },
@@ -345,6 +347,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
/* Fujitsu Wacom Tablet PC devices */
{ "FUJ02E5", 0 },
{ "FUJ02E6", 0 },
+ /*
+ * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
+ * disguise)
+ */
+ { "LTS0001", 0 },
/* Rockwell's (PORALiNK) 33600 INT PNP */
{ "WCI0003", 0 },
/* Unkown PnP modems */
@@ -432,7 +439,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
}
memset(&port, 0, sizeof(struct uart_port));
- port.irq = pnp_irq(dev, 0);
+ if (pnp_irq_valid(dev, 0))
+ port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) {
port.iobase = pnp_port_start(dev, 0);
port.iotype = UPIO_PORT;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ed438bc7e98..d7e1996e2fe 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -600,7 +600,7 @@ config SERIAL_SA1100_CONSOLE
config SERIAL_BFIN
tristate "Blackfin serial port support"
- depends on BFIN
+ depends on BLACKFIN
select SERIAL_CORE
select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561)
help
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 4d6b3c56d20..111da57f533 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -204,8 +204,6 @@ static u_int atmel_get_mctrl(struct uart_port *port)
*/
static void atmel_stop_tx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IDR(port, ATMEL_US_TXRDY);
}
@@ -214,8 +212,6 @@ static void atmel_stop_tx(struct uart_port *port)
*/
static void atmel_start_tx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IER(port, ATMEL_US_TXRDY);
}
@@ -224,8 +220,6 @@ static void atmel_start_tx(struct uart_port *port)
*/
static void atmel_stop_rx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IDR(port, ATMEL_US_RXRDY);
}
@@ -409,7 +403,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
*/
static int atmel_startup(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
int retval;
/*
@@ -456,8 +449,6 @@ static int atmel_startup(struct uart_port *port)
*/
static void atmel_shutdown(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
/*
* Disable all interrupts, port and break condition.
*/
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index f523cdf4b02..a4e23cf4790 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -1,426 +1,10 @@
-/* $Id: serial.c,v 1.25 2004/09/29 10:33:49 starvik Exp $
- *
+/*
* Serial port driver for the ETRAX 100LX chip
*
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB
+ * Copyright (C) 1998-2007 Axis Communications AB
*
* Many, many authors. Based once upon a time on serial.c for 16x50.
*
- * $Log: serial.c,v $
- * Revision 1.25 2004/09/29 10:33:49 starvik
- * Resolved a dealock when printing debug from kernel.
- *
- * Revision 1.24 2004/08/27 23:25:59 johana
- * rs_set_termios() must call change_speed() if c_iflag has changed or
- * automatic XOFF handling will be enabled and transmitter will stop
- * if 0x13 is received.
- *
- * Revision 1.23 2004/08/24 06:57:13 starvik
- * More whitespace cleanup
- *
- * Revision 1.22 2004/08/24 06:12:20 starvik
- * Whitespace cleanup
- *
- * Revision 1.20 2004/05/24 12:00:20 starvik
- * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port).
- *
- * Revision 1.19 2004/05/17 13:12:15 starvik
- * Kernel console hook
- * Big merge from Linux 2.4 still pending.
- *
- * Revision 1.18 2003/10/28 07:18:30 starvik
- * Compiles with debug info
- *
- * Revision 1.17 2003/07/04 08:27:37 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.16 2003/06/13 10:05:19 johana
- * Help the user to avoid trouble by:
- * Forcing mixed mode for status/control lines if not all pins are used.
- *
- * Revision 1.15 2003/06/13 09:43:01 johana
- * Merged in the following changes from os/linux/arch/cris/drivers/serial.c
- * + some minor changes to reduce diff.
- *
- * Revision 1.49 2003/05/30 11:31:54 johana
- * Merged in change-branch--serial9bit that adds CMSPAR support for sticky
- * parity (mark/space)
- *
- * Revision 1.48 2003/05/30 11:03:57 johana
- * Implemented rs_send_xchar() by disabling the DMA and writing manually.
- * Added e100_disable_txdma_channel() and e100_enable_txdma_channel().
- * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar
- * instead of setting info->x_char and check the CRTSCTS flag before
- * controlling the rts pin.
- *
- * Revision 1.14 2003/04/09 08:12:44 pkj
- * Corrected typo changes made upstream.
- *
- * Revision 1.13 2003/04/09 05:20:47 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.11 2003/01/22 06:48:37 starvik
- * Fixed warnings issued by GCC 3.2.1
- *
- * Revision 1.9 2002/12/13 09:07:47 starvik
- * Alert user that RX_TIMEOUT_TICKS==0 doesn't work
- *
- * Revision 1.8 2002/12/11 13:13:57 starvik
- * Added arch/ to v10 specific includes
- * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
- *
- * Revision 1.7 2002/12/06 07:13:57 starvik
- * Corrected work queue stuff
- * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- *
- * Revision 1.6 2002/11/21 07:17:46 starvik
- * Change static inline to extern inline where otherwise outlined with gcc-3.2
- *
- * Revision 1.5 2002/11/14 15:59:49 starvik
- * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff
- * probably doesn't work yet.
- *
- * Revision 1.42 2002/11/05 09:08:47 johana
- * Better implementation of rs_stop() and rs_start() that uses the XOFF
- * register to start/stop transmission.
- * change_speed() also initilises XOFF register correctly so that
- * auto_xoff is enabled when IXON flag is set by user.
- * This gives fast XOFF response times.
- *
- * Revision 1.41 2002/11/04 18:40:57 johana
- * Implemented rs_stop() and rs_start().
- * Simple tests using hwtestserial indicates that this should be enough
- * to make it work.
- *
- * Revision 1.40 2002/10/14 05:33:18 starvik
- * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled
- *
- * Revision 1.39 2002/09/30 21:00:57 johana
- * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and
- * control pins can be mixed between PA and PB.
- * If no serial port uses MIXED old solution is used
- * (saves a few bytes and cycles).
- * control_pins struct uses masks instead of bit numbers.
- * Corrected dummy values and polarity in line_info() so
- * /proc/tty/driver/serial is now correct.
- * (the E100_xxx_GET() macros is really active low - perhaps not obvious)
- *
- * Revision 1.38 2002/08/23 11:01:36 starvik
- * Check that serial port is enabled in all interrupt handlers to avoid
- * restarts of DMA channels not assigned to serial ports
- *
- * Revision 1.37 2002/08/13 13:02:37 bjornw
- * Removed some warnings because of unused code
- *
- * Revision 1.36 2002/08/08 12:50:01 starvik
- * Serial interrupt is shared with synchronous serial port driver
- *
- * Revision 1.35 2002/06/03 10:40:49 starvik
- * Increased RS-485 RTS toggle timer to 2 characters
- *
- * Revision 1.34 2002/05/28 18:59:36 johana
- * Whitespace and comment fixing to be more like etrax100ser.c 1.71.
- *
- * Revision 1.33 2002/05/28 17:55:43 johana
- * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time)
- * timer from tranismit_chars (interrupt context).
- * The timer toggles RTS in interrupt context when expired giving minimum
- * latencies.
- *
- * Revision 1.32 2002/05/22 13:58:00 johana
- * Renamed rs_write() to raw_write() and made it inline.
- * New rs_write() handles RS-485 if configured and enabled
- * (moved code from e100_write_rs485()).
- * RS-485 ioctl's uses copy_from_user() instead of verify_area().
- *
- * Revision 1.31 2002/04/22 11:20:03 johana
- * Updated copyright years.
- *
- * Revision 1.30 2002/04/22 09:39:12 johana
- * RS-485 support compiles.
- *
- * Revision 1.29 2002/01/14 16:10:01 pkj
- * Allocate the receive buffers dynamically. The static 4kB buffer was
- * too small for the peaks. This means that we can get rid of the extra
- * buffer and the copying to it. It also means we require less memory
- * under normal operations, but can use more when needed (there is a
- * cap at 64kB for safety reasons). If there is no memory available
- * we panic(), and die a horrible death...
- *
- * Revision 1.28 2001/12/18 15:04:53 johana
- * Cleaned up write_rs485() - now it works correctly without padding extra
- * char.
- * Added sane default initialisation of rs485.
- * Added #ifdef around dummy variables.
- *
- * Revision 1.27 2001/11/29 17:00:41 pkj
- * 2kB seems to be too small a buffer when using 921600 bps,
- * so increase it to 4kB (this was already done for the elinux
- * version of the serial driver).
- *
- * Revision 1.26 2001/11/19 14:20:41 pkj
- * Minor changes to comments and unused code.
- *
- * Revision 1.25 2001/11/12 20:03:43 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.24 2001/11/12 15:10:05 pkj
- * Total redesign of the receiving part of the serial driver.
- * Uses eight chained descriptors to write to a 4kB buffer.
- * This data is then serialised into a 2kB buffer. From there it
- * is copied into the TTY's flip buffers when they become available.
- * A lot of copying, and the sizes of the buffers might need to be
- * tweaked, but all in all it should work better than the previous
- * version, without the need to modify the TTY code in any way.
- * Also note that erroneous bytes are now correctly marked in the
- * flag buffers (instead of always marking the first byte).
- *
- * Revision 1.23 2001/10/30 17:53:26 pkj
- * * Set info->uses_dma to 0 when a port is closed.
- * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT).
- * * Call start_flush_timer() in start_receive() if
- * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined.
- *
- * Revision 1.22 2001/10/30 17:44:03 pkj
- * Use %lu for received and transmitted counters in line_info().
- *
- * Revision 1.21 2001/10/30 17:40:34 pkj
- * Clean-up. The only change to functionality is that
- * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of
- * MAX_FLUSH_TIME(=8).
- *
- * Revision 1.20 2001/10/30 15:24:49 johana
- * Added char_time stuff from 2.0 driver.
- *
- * Revision 1.19 2001/10/30 15:23:03 johana
- * Merged with 1.13.2 branch + fixed indentation
- * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ
- *
- * Revision 1.18 2001/09/24 09:27:22 pkj
- * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud().
- *
- * Revision 1.17 2001/08/24 11:32:49 ronny
- * More fixes for the CONFIG_ETRAX_SERIAL_PORT0 define.
- *
- * Revision 1.16 2001/08/24 07:56:22 ronny
- * Added config ifdefs around ser0 irq requests.
- *
- * Revision 1.15 2001/08/16 09:10:31 bjarne
- * serial.c - corrected the initialization of rs_table, the wrong defines
- * where used.
- * Corrected a test in timed_flush_handler.
- * Changed configured to enabled.
- * serial.h - Changed configured to enabled.
- *
- * Revision 1.14 2001/08/15 07:31:23 bjarne
- * Introduced two new members to the e100_serial struct.
- * configured - Will be set to 1 if the port has been configured in .config
- * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set
- * to 1
- * when a port is opened. This is used to limit the DMA interrupt
- * routines to only manipulate DMA channels actually used by the
- * serial driver.
- *
- * Revision 1.13.2.2 2001/10/17 13:57:13 starvik
- * Receiver was broken by the break fixes
- *
- * Revision 1.13.2.1 2001/07/20 13:57:39 ronny
- * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff
- * like break handling.
- *
- * Revision 1.13 2001/05/09 12:40:31 johana
- * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h
- *
- * Revision 1.12 2001/04/19 12:23:07 bjornw
- * CONFIG_RS485 -> CONFIG_ETRAX_RS485
- *
- * Revision 1.11 2001/04/05 14:29:48 markusl
- * Updated according to review remarks i.e.
- * -Use correct types in port structure to avoid compiler warnings
- * -Try to use IO_* macros whenever possible
- * -Open should never return -EBUSY
- *
- * Revision 1.10 2001/03/05 13:14:07 bjornw
- * Another spelling fix
- *
- * Revision 1.9 2001/02/23 13:46:38 bjornw
- * Spellling check
- *
- * Revision 1.8 2001/01/23 14:56:35 markusl
- * Made use of ser1 optional
- * Needed by USB
- *
- * Revision 1.7 2001/01/19 16:14:48 perf
- * Added kernel options for serial ports 234.
- * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ.
- *
- * Revision 1.6 2000/11/22 16:36:09 bjornw
- * Please marketing by using the correct case when spelling Etrax.
- *
- * Revision 1.5 2000/11/21 16:43:37 bjornw
- * Fixed so it compiles under CONFIG_SVINTO_SIM
- *
- * Revision 1.4 2000/11/15 17:34:12 bjornw
- * Added a timeout timer for flushing input channels. The interrupt-based
- * fast flush system should be easy to merge with this later (works the same
- * way, only with an irq instead of a system timer_list)
- *
- * Revision 1.3 2000/11/13 17:19:57 bjornw
- * * Incredibly, this almost complete rewrite of serial.c worked (at least
- * for output) the first time.
- *
- * Items worth noticing:
- *
- * No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now)
- * RS485 is not ported (why can't it be done in userspace as on x86 ?)
- * Statistics done through async_icount - if any more stats are needed,
- * that's the place to put them or in an arch-dep version of it.
- * timeout_interrupt and the other fast timeout stuff not ported yet
- * There be dragons in this 3k+ line driver
- *
- * Revision 1.2 2000/11/10 16:50:28 bjornw
- * First shot at a 2.4 port, does not compile totally yet
- *
- * Revision 1.1 2000/11/10 16:47:32 bjornw
- * Added verbatim copy of rev 1.49 etrax100ser.c from elinux
- *
- * Revision 1.49 2000/10/30 15:47:14 tobiasa
- * Changed version number.
- *
- * Revision 1.48 2000/10/25 11:02:43 johana
- * Changed %ul to %lu in printf's
- *
- * Revision 1.47 2000/10/18 15:06:53 pkj
- * Compile correctly with CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST and
- * CONFIG_ETRAX_SERIAL_PROC_ENTRY together.
- * Some clean-up of the /proc/serial file.
- *
- * Revision 1.46 2000/10/16 12:59:40 johana
- * Added CONFIG_ETRAX_SERIAL_PROC_ENTRY for statistics and debug info.
- *
- * Revision 1.45 2000/10/13 17:10:59 pkj
- * Do not flush DMAs while flipping TTY buffers.
- *
- * Revision 1.44 2000/10/13 16:34:29 pkj
- * Added a delay in ser_interrupt() for 2.3ms when an error is detected.
- * We do not know why this delay is required yet, but without it the
- * irmaflash program does not work (this was the program that needed
- * the ser_interrupt() to be needed in the first place). This should not
- * affect normal use of the serial ports.
- *
- * Revision 1.43 2000/10/13 16:30:44 pkj
- * New version of the fast flush of serial buffers code. This time
- * it is localized to the serial driver and uses a fast timer to
- * do the work.
- *
- * Revision 1.42 2000/10/13 14:54:26 bennyo
- * Fix for switching RTS when using rs485
- *
- * Revision 1.41 2000/10/12 11:43:44 pkj
- * Cleaned up a number of comments.
- *
- * Revision 1.40 2000/10/10 11:58:39 johana
- * Made RS485 support generic for all ports.
- * Toggle rts in interrupt if no delay wanted.
- * WARNING: No true transmitter empty check??
- * Set d_wait bit when sending data so interrupt is delayed until
- * fifo flushed. (Fix tcdrain() problem)
- *
- * Revision 1.39 2000/10/04 16:08:02 bjornw
- * * Use virt_to_phys etc. for DMA addresses
- * * Removed CONFIG_FLUSH_DMA_FAST hacks
- * * Indentation fix
- *
- * Revision 1.38 2000/10/02 12:27:10 mattias
- * * added variable used when using fast flush on serial dma.
- * (CONFIG_FLUSH_DMA_FAST)
- *
- * Revision 1.37 2000/09/27 09:44:24 pkj
- * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS.
- *
- * Revision 1.36 2000/09/20 13:12:52 johana
- * Support for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS:
- * Number of timer ticks between flush of receive fifo (1 tick = 10ms).
- * Try 0-3 for low latency applications. Approx 5 for high load
- * applications (e.g. PPP). Maybe this should be more adaptive some day...
- *
- * Revision 1.35 2000/09/20 10:36:08 johana
- * Typo in get_lsr_info()
- *
- * Revision 1.34 2000/09/20 10:29:59 johana
- * Let rs_chars_in_buffer() check fifo content as well.
- * get_lsr_info() might work now (not tested).
- * Easier to change the port to debug.
- *
- * Revision 1.33 2000/09/13 07:52:11 torbjore
- * Support RS485
- *
- * Revision 1.32 2000/08/31 14:45:37 bjornw
- * After sending a break we need to reset the transmit DMA channel
- *
- * Revision 1.31 2000/06/21 12:13:29 johana
- * Fixed wait for all chars sent when closing port.
- * (Used to always take 1 second!)
- * Added shadows for directions of status/ctrl signals.
- *
- * Revision 1.30 2000/05/29 16:27:55 bjornw
- * Simulator ifdef moved a bit
- *
- * Revision 1.29 2000/05/09 09:40:30 mattias
- * * Added description of dma registers used in timeout_interrupt
- * * Removed old code
- *
- * Revision 1.28 2000/05/08 16:38:58 mattias
- * * Bugfix for flushing fifo in timeout_interrupt
- * Problem occurs when bluetooth stack waits for a small number of bytes
- * containing an event acknowledging free buffers in bluetooth HW
- * As before, data was stuck in fifo until more data came on uart and
- * flushed it up to the stack.
- *
- * Revision 1.27 2000/05/02 09:52:28 jonasd
- * Added fix for peculiar etrax behaviour when eop is forced on an empty
- * fifo. This is used when flashing the IRMA chip. Disabled by default.
- *
- * Revision 1.26 2000/03/29 15:32:02 bjornw
- * 2.0.34 updates
- *
- * Revision 1.25 2000/02/16 16:59:36 bjornw
- * * Receive DMA directly into the flip-buffer, eliminating an intermediary
- * receive buffer and a memcpy. Will avoid some overruns.
- * * Error message on debug port if an overrun or flip buffer overrun occurs.
- * * Just use the first byte in the flag flip buffer for errors.
- * * Check for timeout on the serial ports only each 5/100 s, not 1/100.
- *
- * Revision 1.24 2000/02/09 18:02:28 bjornw
- * * Clear serial errors (overrun, framing, parity) correctly. Before, the
- * receiver would get stuck if an error occurred and we did not restart
- * the input DMA.
- * * Cosmetics (indentation, some code made into inlines)
- * * Some more debug options
- * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop)
- * when the last open is closed. Corresponding fixes in startup().
- * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed
- * and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that)
- * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS
- *
- * Revision 1.23 2000/01/24 17:46:19 johana
- * Wait for flush of DMA/FIFO when closing port.
- *
- * Revision 1.22 2000/01/20 18:10:23 johana
- * Added TIOCMGET ioctl to return modem status.
- * Implemented modem status/control that works with the extra signals
- * (DTR, DSR, RI,CD) as well.
- * 3 different modes supported:
- * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy)
- * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when
- * closing the last filehandle, NASTY!.
- * Added break generation, not tested though!
- * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1.
- * You can't use them at the same time (yet..), but you can hopefully switch
- * between ser2/par0, ser3/par1 with the same kernel config.
- * Replaced some magic constants with defines
- *
- *
*/
static char *serial_version = "$Revision: 1.25 $";
@@ -446,6 +30,7 @@ static char *serial_version = "$Revision: 1.25 $";
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/dma.h>
#include <asm/system.h>
#include <linux/delay.h>
@@ -454,8 +39,9 @@ static char *serial_version = "$Revision: 1.25 $";
/* non-arch dependent serial structures are in linux/serial.h */
#include <linux/serial.h>
/* while we keep our own stuff (struct e100_serial) in a local .h file */
-#include "serial.h"
+#include "crisv10.h"
#include <asm/fasttimer.h>
+#include <asm/arch/io_interface_mux.h>
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
#ifndef CONFIG_ETRAX_FAST_TIMER
@@ -504,18 +90,6 @@ struct tty_driver *serial_driver;
from eLinux */
#define SERIAL_HANDLE_EARLY_ERRORS
-/* Defined and used in n_tty.c, but we need it here as well */
-#define TTY_THRESHOLD_THROTTLE 128
-
-/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE
- * must not be to high or flow control won't work if we leave it to the tty
- * layer so we have our own throttling in flush_to_flip
- * TTY_FLIPBUF_SIZE=512,
- * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128
- * BUF_SIZE can't be > 128
- */
-#define CRIS_BUF_SIZE 512
-
/* Currently 16 descriptors x 128 bytes = 2048 bytes */
#define SERIAL_DESCR_BUF_SIZE 256
@@ -588,13 +162,13 @@ unsigned long timer_data_to_ns(unsigned long timer_data);
static void change_speed(struct e100_serial *info);
static void rs_throttle(struct tty_struct * tty);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-static int rs_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count);
+static int rs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count);
#ifdef CONFIG_ETRAX_RS485
-static int e100_write_rs485(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count);
+static int e100_write_rs485(struct tty_struct *tty,
+ const unsigned char *buf, int count);
#endif
-static int get_lsr_info(struct e100_serial * info, unsigned int *value);
+static int get_lsr_info(struct e100_serial *info, unsigned int *value);
#define DEF_BAUD 115200 /* 115.2 kbit/s */
@@ -679,20 +253,39 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 2,
+ .dma_owner = dma_ser0,
+ .io_if = if_serial_0,
#ifdef CONFIG_ETRAX_SERIAL_PORT0
.enabled = 1,
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER0_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 0 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER0_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 0 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -714,20 +307,42 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 3,
+ .dma_owner = dma_ser1,
+ .io_if = if_serial_1,
#ifdef CONFIG_ETRAX_SERIAL_PORT1
.enabled = 1,
+ .io_if_description = "ser1",
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER1_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 1 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER1_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 1 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
+ .dma_in_irq_nbr = 0,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -748,20 +363,40 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 0,
+ .dma_owner = dma_ser2,
+ .io_if = if_serial_2,
#ifdef CONFIG_ETRAX_SERIAL_PORT2
.enabled = 1,
+ .io_if_description = "ser2",
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER2_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 2 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER2_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 2 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -782,20 +417,40 @@ static struct e100_serial rs_table[] = {
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 1,
+ .dma_owner = dma_ser3,
+ .io_if = if_serial_3,
#ifdef CONFIG_ETRAX_SERIAL_PORT3
.enabled = 1,
+ .io_if_description = "ser3",
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER3_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 3 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER3_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 3 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -1416,12 +1071,11 @@ e100_dtr(struct e100_serial *info, int set)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].dtr_shadow &= ~mask;
*e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#ifdef SERIAL_DEBUG_IO
@@ -1440,12 +1094,11 @@ e100_rts(struct e100_serial *info, int set)
{
#ifndef CONFIG_SVINTO_SIM
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
info->rx_ctrl &= ~E100_RTS_MASK;
info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */
info->port[REG_REC_CTRL] = info->rx_ctrl;
- restore_flags(flags);
+ local_irq_restore(flags);
#ifdef SERIAL_DEBUG_IO
printk("ser%i rts %i\n", info->line, set);
#endif
@@ -1463,12 +1116,11 @@ e100_ri_out(struct e100_serial *info, int set)
unsigned char mask = e100_modem_pins[info->line].ri_mask;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].ri_shadow &= ~mask;
*e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
}
@@ -1481,12 +1133,11 @@ e100_cd_out(struct e100_serial *info, int set)
unsigned char mask = e100_modem_pins[info->line].cd_mask;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].cd_shadow &= ~mask;
*e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
}
@@ -1560,8 +1211,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info)
/* Disable output DMA channel for the serial port in question
* ( set to something other then serialX)
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line));
if (info->line == 0) {
if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) ==
@@ -1589,7 +1239,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info)
}
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1597,8 +1247,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line));
/* Enable output DMA channel for the serial port in question */
if (info->line == 0) {
@@ -1615,7 +1264,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info)
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3);
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void e100_disable_rxdma_channel(struct e100_serial *info)
@@ -1625,8 +1274,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info)
/* Disable input DMA channel for the serial port in question
* ( set to something other then serialX)
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (info->line == 0) {
if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) ==
IO_STATE(R_GEN_CONFIG, dma7, serial0)) {
@@ -1653,7 +1301,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info)
}
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1661,8 +1309,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Enable input DMA channel for the serial port in question */
if (info->line == 0) {
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7);
@@ -1678,7 +1325,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info)
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3);
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#ifdef SERIAL_HANDLE_EARLY_ERRORS
@@ -1785,7 +1432,7 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r)
}
static int
-e100_write_rs485(struct tty_struct *tty, int from_user,
+e100_write_rs485(struct tty_struct *tty,
const unsigned char *buf, int count)
{
struct e100_serial * info = (struct e100_serial *)tty->driver_data;
@@ -1798,7 +1445,7 @@ e100_write_rs485(struct tty_struct *tty, int from_user,
*/
info->rs485.enabled = 1;
/* rs_write now deals with RS485 if enabled */
- count = rs_write(tty, from_user, buf, count);
+ count = rs_write(tty, buf, count);
info->rs485.enabled = old_enabled;
return count;
}
@@ -1836,7 +1483,7 @@ rs_stop(struct tty_struct *tty)
unsigned long flags;
unsigned long xoff;
- save_flags(flags); cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n",
CIRC_CNT(info->xmit.head,
info->xmit.tail,SERIAL_XMIT_SIZE)));
@@ -1848,7 +1495,7 @@ rs_stop(struct tty_struct *tty)
}
*((unsigned long *)&info->port[REG_XOFF]) = xoff;
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
@@ -1860,7 +1507,7 @@ rs_start(struct tty_struct *tty)
unsigned long flags;
unsigned long xoff;
- save_flags(flags); cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n",
CIRC_CNT(info->xmit.head,
info->xmit.tail,SERIAL_XMIT_SIZE)));
@@ -1875,7 +1522,7 @@ rs_start(struct tty_struct *tty)
info->xmit.head != info->xmit.tail && info->xmit.buf)
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
@@ -2055,8 +1702,7 @@ static int serial_fast_timer_expired = 0;
static void flush_timeout_function(unsigned long data);
#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\
unsigned long timer_flags; \
- save_flags(timer_flags); \
- cli(); \
+ local_irq_save(timer_flags); \
if (fast_timers[info->line].function == NULL) { \
serial_fast_timer_started++; \
TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \
@@ -2070,7 +1716,7 @@ static void flush_timeout_function(unsigned long data);
else { \
TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \
} \
- restore_flags(timer_flags); \
+ local_irq_restore(timer_flags); \
}
#define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec)
@@ -2099,8 +1745,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!info->first_recv_buffer)
info->first_recv_buffer = buffer;
@@ -2113,7 +1758,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer)
if (info->recv_cnt > info->max_recv_cnt)
info->max_recv_cnt = info->recv_cnt;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static int
@@ -2133,11 +1778,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl
info->icount.rx++;
} else {
struct tty_struct *tty = info->tty;
- *tty->flip.char_buf_ptr = data;
- *tty->flip.flag_buf_ptr = flag;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, data, flag);
info->icount.rx++;
}
@@ -2322,7 +1963,6 @@ start_receive(struct e100_serial *info)
*/
return;
#endif
- info->tty->flip.count = 0;
if (info->uses_dma_in) {
/* reset the input dma channel to be sure it works */
@@ -2484,32 +2124,20 @@ static void flush_to_flip_buffer(struct e100_serial *info)
{
struct tty_struct *tty;
struct etrax_recv_buffer *buffer;
- unsigned int length;
unsigned long flags;
- int max_flip_size;
-
- if (!info->first_recv_buffer)
- return;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
+ tty = info->tty;
- if (!(tty = info->tty)) {
- restore_flags(flags);
+ if (!tty) {
+ local_irq_restore(flags);
return;
}
while ((buffer = info->first_recv_buffer) != NULL) {
unsigned int count = buffer->length;
- count = tty_buffer_request_room(tty, count);
- if (count == 0) /* Throttle ?? */
- break;
-
- if (count > 1)
- tty_insert_flip_strings(tty, buffer->buffer, count - 1);
- tty_insert_flip_char(tty, buffer->buffer[count-1], buffer->error);
-
+ tty_insert_flip_string(tty, buffer->buffer, count);
info->recv_cnt -= count;
if (count == buffer->length) {
@@ -2525,18 +2153,9 @@ static void flush_to_flip_buffer(struct e100_serial *info)
if (!info->first_recv_buffer)
info->last_recv_buffer = NULL;
- restore_flags(flags);
-
- DFLIP(
- if (1) {
- DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx);
- DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty));
- DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty));
- }
+ local_irq_restore(flags);
- );
-
- /* this includes a check for low-latency */
+ /* This includes a check for low-latency */
tty_flip_buffer_push(tty);
}
@@ -2679,21 +2298,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
printk("!NO TTY!\n");
return info;
}
- if (tty->flip.count >= CRIS_BUF_SIZE - TTY_THRESHOLD_THROTTLE) {
- /* check TTY_THROTTLED first so it indicates our state */
- if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
- DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count));
- rs_throttle(tty);
- }
- }
- if (tty->flip.count >= CRIS_BUF_SIZE) {
- DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count);
- tty->flip.work.func((void *) tty);
- if (tty->flip.count >= CRIS_BUF_SIZE) {
- DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count);
- return info; /* if TTY_DONT_FLIP is set */
- }
- }
+
/* Read data and status at the same time */
data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]);
more_data:
@@ -2746,27 +2351,26 @@ more_data:
DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
info->errorcode = ERRCODE_INSERT_BREAK;
} else {
+ unsigned char data = IO_EXTRACT(R_SERIAL0_READ,
+ data_in, data_read);
+ char flag = TTY_NORMAL;
if (info->errorcode == ERRCODE_INSERT_BREAK) {
- info->icount.brk++;
- *tty->flip.char_buf_ptr = 0;
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ struct tty_struct *tty = info->tty;
+ tty_insert_flip_char(tty, 0, flag);
info->icount.rx++;
}
- *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read);
if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) {
info->icount.parity++;
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) {
info->icount.overrun++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
} else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) {
info->icount.frame++;
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
+ tty_insert_flip_char(tty, data, flag);
info->errorcode = 0;
}
info->break_detected_cnt = 0;
@@ -2782,16 +2386,14 @@ more_data:
log_int(rdpc(), 0, 0);
}
);
- *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read);
- *tty->flip.flag_buf_ptr = 0;
+ tty_insert_flip_char(tty,
+ IO_EXTRACT(R_SERIAL0_READ, data_in, data_read),
+ TTY_NORMAL);
} else {
DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read);
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
info->icount.rx++;
data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]);
if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) {
@@ -2929,7 +2531,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
if (info->x_char) {
unsigned char rstat;
DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char));
- save_flags(flags); cli();
+ local_irq_save(flags);
rstat = info->port[REG_STATUS];
DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
@@ -2938,7 +2540,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
info->x_char = 0;
/* We must enable since it is disabled in ser_interrupt */
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
if (info->uses_dma_out) {
@@ -2946,7 +2548,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
int i;
/* We only use normal tx interrupt when sending x_char */
DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0));
- save_flags(flags); cli();
+ local_irq_save(flags);
rstat = info->port[REG_STATUS];
DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
e100_disable_serial_tx_ready_irq(info);
@@ -2959,7 +2561,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
nop();
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
/* Normal char-by-char interrupt */
@@ -2973,7 +2575,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
}
DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail]));
/* Send a byte, rs485 timing is critical so turn of ints */
- save_flags(flags); cli();
+ local_irq_save(flags);
info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail];
info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
info->icount.tx++;
@@ -2997,7 +2599,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
/* We must enable since it is disabled in ser_interrupt */
e100_enable_serial_tx_ready_irq(info);
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (CIRC_CNT(info->xmit.head,
info->xmit.tail,
@@ -3022,7 +2624,7 @@ ser_interrupt(int irq, void *dev_id)
int handled = 0;
static volatile unsigned long reentered_ready_mask = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
irq_mask1_rd = *R_IRQ_MASK1_RD;
/* First handle all rx interrupts with ints disabled */
info = rs_table;
@@ -3067,7 +2669,7 @@ ser_interrupt(int irq, void *dev_id)
/* Unblock the serial interrupt */
*R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
- sti();
+ local_irq_enable();
ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */
info = rs_table;
for (i = 0; i < NR_PORTS; i++) {
@@ -3080,11 +2682,11 @@ ser_interrupt(int irq, void *dev_id)
ready_mask <<= 2;
}
/* handle_ser_tx_interrupt enables tr_ready interrupts */
- cli();
+ local_irq_disable();
/* Handle reentered TX interrupt */
irq_mask1_rd = reentered_ready_mask;
}
- cli();
+ local_irq_disable();
tx_started = 0;
} else {
unsigned long ready_mask;
@@ -3100,7 +2702,7 @@ ser_interrupt(int irq, void *dev_id)
}
}
- restore_flags(flags);
+ local_irq_restore(flags);
return IRQ_RETVAL(handled);
} /* ser_interrupt */
#endif
@@ -3121,11 +2723,13 @@ ser_interrupt(int irq, void *dev_id)
* them using rs_sched_event(), and they get done here.
*/
static void
-do_softint(void *private_)
+do_softint(struct work_struct *work)
{
- struct e100_serial *info = (struct e100_serial *) private_;
+ struct e100_serial *info;
struct tty_struct *tty;
+ info = container_of(work, struct e100_serial, work);
+
tty = info->tty;
if (!tty)
return;
@@ -3145,13 +2749,12 @@ startup(struct e100_serial * info)
if (!xmit_page)
return -ENOMEM;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* if it was already initialized, skip this */
if (info->flags & ASYNC_INITIALIZED) {
- restore_flags(flags);
+ local_irq_restore(flags);
free_page(xmit_page);
return 0;
}
@@ -3277,7 +2880,7 @@ startup(struct e100_serial * info)
info->flags |= ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -3328,8 +2931,7 @@ shutdown(struct e100_serial * info)
info->irq);
#endif
- save_flags(flags);
- cli(); /* Disable interrupts */
+ local_irq_save(flags);
if (info->xmit.buf) {
free_page((unsigned long)info->xmit.buf);
@@ -3353,7 +2955,7 @@ shutdown(struct e100_serial * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -3411,7 +3013,6 @@ change_speed(struct e100_serial *info)
DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8));
info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8;
}
- }
#endif
else
{
@@ -3445,8 +3046,7 @@ change_speed(struct e100_serial *info)
#ifndef CONFIG_SVINTO_SIM
/* start with default settings and then fill in changes */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* 8 bit, no/even parity */
info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) |
IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) |
@@ -3510,7 +3110,7 @@ change_speed(struct e100_serial *info)
}
*((unsigned long *)&info->port[REG_XOFF]) = xoff;
- restore_flags(flags);
+ local_irq_restore(flags);
#endif /* !CONFIG_SVINTO_SIM */
update_char_time(info);
@@ -3538,13 +3138,12 @@ rs_flush_chars(struct tty_struct *tty)
/* this protection might not exactly be necessary here */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
start_transmit(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static int rs_raw_write(struct tty_struct * tty, int from_user,
+static int rs_raw_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
int c, ret = 0;
@@ -3567,53 +3166,19 @@ static int rs_raw_write(struct tty_struct * tty, int from_user,
SIMCOUT(buf, count);
return count;
#endif
- save_flags(flags);
+ local_save_flags(flags);
DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
- /* the cli/restore_flags pairs below are needed because the
- * DMA interrupt handler moves the info->xmit values. the memcpy
- * needs to be in the critical region unfortunately, because we
- * need to read xmit values, memcpy, write xmit values in one
- * atomic operation... this could perhaps be avoided by more clever
- * design.
+ /* The local_irq_disable/restore_flags pairs below are needed
+ * because the DMA interrupt handler moves the info->xmit values.
+ * the memcpy needs to be in the critical region unfortunately,
+ * because we need to read xmit values, memcpy, write xmit values
+ * in one atomic operation... this could perhaps be avoided by
+ * more clever design.
*/
- if (from_user) {
- mutex_lock(&tmp_buf_mutex);
- while (1) {
- int c1;
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
-
- c -= copy_from_user(tmp_buf, buf, c);
- if (!c) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- cli();
- c1 = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
- if (c1 < c)
- c = c1;
- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
- info->xmit.head = ((info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1));
- restore_flags(flags);
- buf += c;
- count -= c;
- ret += c;
- }
- mutex_unlock(&tmp_buf_mutex);
- } else {
- cli();
+ local_irq_disable();
while (count) {
c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
@@ -3631,8 +3196,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user,
count -= c;
ret += c;
}
- restore_flags(flags);
- }
+ local_irq_restore(flags);
/* enable transmitter if not running, unless the tty is stopped
* this does not need IRQ protection since if tr_running == 0
@@ -3651,7 +3215,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user,
} /* raw_raw_write() */
static int
-rs_write(struct tty_struct * tty, int from_user,
+rs_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
#if defined(CONFIG_ETRAX_RS485)
@@ -3678,7 +3242,7 @@ rs_write(struct tty_struct * tty, int from_user,
}
#endif /* CONFIG_ETRAX_RS485 */
- count = rs_raw_write(tty, from_user, buf, count);
+ count = rs_raw_write(tty, buf, count);
#if defined(CONFIG_ETRAX_RS485)
if (info->rs485.enabled)
@@ -3746,10 +3310,9 @@ rs_flush_buffer(struct tty_struct *tty)
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
info->xmit.head = info->xmit.tail = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
tty_wakeup(tty);
}
@@ -3767,7 +3330,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
{
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->uses_dma_out) {
/* Put the DMA on hold and disable the channel */
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold);
@@ -3784,7 +3347,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch));
info->x_char = ch;
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -3996,21 +3559,61 @@ char *get_control_state_str(int MLines, char *s)
}
#endif
+static void
+rs_break(struct tty_struct *tty, int break_state)
+{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (!info->port)
+ return;
+
+ local_irq_save(flags);
+ if (break_state == -1) {
+ /* Go to manual mode and set the txd pin to 0 */
+ /* Clear bit 7 (txd) and 6 (tr_enable) */
+ info->tx_ctrl &= 0x3F;
+ } else {
+ /* Set bit 7 (txd) and 6 (tr_enable) */
+ info->tx_ctrl |= (0x80 | 0x40);
+ }
+ info->port[REG_TR_CTRL] = info->tx_ctrl;
+ local_irq_restore(flags);
+}
+
static int
-get_modem_info(struct e100_serial * info, unsigned int *value)
+rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
- unsigned int result;
- /* Polarity isn't verified */
-#if 0 /*def SERIAL_DEBUG_IO */
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n",
- E100_RTS_GET(info),
- E100_DTR_GET(info),
- E100_CD_GET(info),
- E100_RI_GET(info),
- E100_DSR_GET(info),
- E100_CTS_GET(info));
-#endif
+ if (clear & TIOCM_RTS)
+ e100_rts(info, 0);
+ if (clear & TIOCM_DTR)
+ e100_dtr(info, 0);
+ /* Handle FEMALE behaviour */
+ if (clear & TIOCM_RI)
+ e100_ri_out(info, 0);
+ if (clear & TIOCM_CD)
+ e100_cd_out(info, 0);
+
+ if (set & TIOCM_RTS)
+ e100_rts(info, 1);
+ if (set & TIOCM_DTR)
+ e100_dtr(info, 1);
+ /* Handle FEMALE behaviour */
+ if (set & TIOCM_RI)
+ e100_ri_out(info, 1);
+ if (set & TIOCM_CD)
+ e100_cd_out(info, 1);
+ return 0;
+}
+
+static int
+rs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned int result;
result =
(!E100_RTS_GET(info) ? TIOCM_RTS : 0)
@@ -4021,95 +3624,20 @@ get_modem_info(struct e100_serial * info, unsigned int *value)
| (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
#ifdef SERIAL_DEBUG_IO
- printk("e100ser: modem state: %i 0x%08X\n", result, result);
+ printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
+ info->line, result, result);
{
char s[100];
get_control_state_str(result, s);
- printk("state: %s\n", s);
+ printk(KERN_DEBUG "state: %s\n", s);
}
#endif
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- return 0;
-}
+ return result;
-
-static int
-set_modem_info(struct e100_serial * info, unsigned int cmd,
- unsigned int *value)
-{
- unsigned int arg;
-
- if (copy_from_user(&arg, value, sizeof(int)))
- return -EFAULT;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS) {
- e100_rts(info, 1);
- }
- if (arg & TIOCM_DTR) {
- e100_dtr(info, 1);
- }
- /* Handle FEMALE behaviour */
- if (arg & TIOCM_RI) {
- e100_ri_out(info, 1);
- }
- if (arg & TIOCM_CD) {
- e100_cd_out(info, 1);
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS) {
- e100_rts(info, 0);
- }
- if (arg & TIOCM_DTR) {
- e100_dtr(info, 0);
- }
- /* Handle FEMALE behaviour */
- if (arg & TIOCM_RI) {
- e100_ri_out(info, 0);
- }
- if (arg & TIOCM_CD) {
- e100_cd_out(info, 0);
- }
- break;
- case TIOCMSET:
- e100_rts(info, arg & TIOCM_RTS);
- e100_dtr(info, arg & TIOCM_DTR);
- /* Handle FEMALE behaviour */
- e100_ri_out(info, arg & TIOCM_RI);
- e100_cd_out(info, arg & TIOCM_CD);
- break;
- default:
- return -EINVAL;
- }
- return 0;
}
-static void
-rs_break(struct tty_struct *tty, int break_state)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- if (!info->port)
- return;
-
- save_flags(flags);
- cli();
- if (break_state == -1) {
- /* Go to manual mode and set the txd pin to 0 */
- info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */
- } else {
- info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */
- }
- info->port[REG_TR_CTRL] = info->tx_ctrl;
- restore_flags(flags);
-}
-
static int
rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
@@ -4124,49 +3652,45 @@ rs_ioctl(struct tty_struct *tty, struct file * file,
}
switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
- case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
-
- case TIOCSERGSTRUCT:
- if (copy_to_user((struct e100_serial *) arg,
- info, sizeof(struct e100_serial)))
- return -EFAULT;
- return 0;
+ case TIOCGSERIAL:
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
+
+ case TIOCSERGSTRUCT:
+ if (copy_to_user((struct e100_serial *) arg,
+ info, sizeof(struct e100_serial)))
+ return -EFAULT;
+ return 0;
#if defined(CONFIG_ETRAX_RS485)
- case TIOCSERSETRS485:
- {
- struct rs485_control rs485ctrl;
- if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl)))
- return -EFAULT;
+ case TIOCSERSETRS485:
+ {
+ struct rs485_control rs485ctrl;
+ if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
- return e100_enable_rs485(tty, &rs485ctrl);
- }
+ return e100_enable_rs485(tty, &rs485ctrl);
+ }
- case TIOCSERWRRS485:
- {
- struct rs485_write rs485wr;
- if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr)))
- return -EFAULT;
+ case TIOCSERWRRS485:
+ {
+ struct rs485_write rs485wr;
+ if (copy_from_user(&rs485wr, (struct rs485_write *)arg,
+ sizeof(rs485wr)))
+ return -EFAULT;
- return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size);
- }
+ return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size);
+ }
#endif
- default:
- return -ENOIOCTLCMD;
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
@@ -4191,46 +3715,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
}
-/* In debugport.c - register a console write function that uses the normal
- * serial driver
- */
-typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len);
-
-extern debugport_write_function debug_write_function;
-
-static int rs_debug_write_function(int i, const char *buf, unsigned int len)
-{
- int cnt;
- int written = 0;
- struct tty_struct *tty;
- static int recurse_cnt = 0;
-
- tty = rs_table[i].tty;
- if (tty) {
- unsigned long flags;
- if (recurse_cnt > 5) /* We skip this debug output */
- return 1;
-
- local_irq_save(flags);
- recurse_cnt++;
- local_irq_restore(flags);
- do {
- cnt = rs_write(tty, 0, buf + written, len);
- if (cnt >= 0) {
- written += cnt;
- buf += cnt;
- len -= cnt;
- } else
- len = cnt;
- } while(len > 0);
- local_irq_save(flags);
- recurse_cnt--;
- local_irq_restore(flags);
- return 1;
- }
- return 0;
-}
-
/*
* ------------------------------------------------------------
* rs_close()
@@ -4252,11 +3736,10 @@ rs_close(struct tty_struct *tty, struct file * filp)
/* interrupts are disabled for this entire function */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -4283,7 +3766,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
info->count = 0;
}
if (info->count) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
@@ -4337,7 +3820,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
+ local_irq_restore(flags);
/* port closed */
@@ -4359,6 +3842,28 @@ rs_close(struct tty_struct *tty, struct file * filp)
#endif
}
#endif
+
+ /*
+ * Release any allocated DMA irq's.
+ */
+ if (info->dma_in_enabled) {
+ free_irq(info->dma_in_irq_nbr, info);
+ cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
+ info->uses_dma_in = 0;
+#ifdef SERIAL_DEBUG_OPEN
+ printk(KERN_DEBUG "DMA irq '%s' freed\n",
+ info->dma_in_irq_description);
+#endif
+ }
+ if (info->dma_out_enabled) {
+ free_irq(info->dma_out_irq_nbr, info);
+ cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
+ info->uses_dma_out = 0;
+#ifdef SERIAL_DEBUG_OPEN
+ printk(KERN_DEBUG "DMA irq '%s' freed\n",
+ info->dma_out_irq_description);
+#endif
+ }
}
/*
@@ -4433,8 +3938,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ wait_event_interruptible(info->close_wait,
+ !(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -4472,21 +3977,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready before block: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count++;
info->count--;
}
- restore_flags(flags);
+ local_irq_restore(flags);
info->blocked_open++;
while (1) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* assert RTS and DTR */
e100_rts(info, 1);
e100_dtr(info, 1);
- restore_flags(flags);
+ local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
@@ -4528,6 +4031,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
return 0;
}
+static void
+deinit_port(struct e100_serial *info)
+{
+ if (info->dma_out_enabled) {
+ cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
+ free_irq(info->dma_out_irq_nbr, info);
+ }
+ if (info->dma_in_enabled) {
+ cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
+ free_irq(info->dma_in_irq_nbr, info);
+ }
+}
+
/*
* This routine is called whenever a serial port is opened.
* It performs the serial-specific initialization for the tty structure.
@@ -4538,9 +4054,9 @@ rs_open(struct tty_struct *tty, struct file * filp)
struct e100_serial *info;
int retval, line;
unsigned long page;
+ int allocated_resources = 0;
/* find which port we want to open */
-
line = tty->index;
if (line < 0 || line >= NR_PORTS)
@@ -4580,8 +4096,8 @@ rs_open(struct tty_struct *tty, struct file * filp)
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ wait_event_interruptible(info->close_wait,
+ !(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
@@ -4591,12 +4107,85 @@ rs_open(struct tty_struct *tty, struct file * filp)
}
/*
+ * If DMA is enabled try to allocate the irq's.
+ */
+ if (info->count == 1) {
+ allocated_resources = 1;
+ if (info->dma_in_enabled) {
+ if (request_irq(info->dma_in_irq_nbr,
+ rec_interrupt,
+ info->dma_in_irq_flags,
+ info->dma_in_irq_description,
+ info)) {
+ printk(KERN_WARNING "DMA irq '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_in_irq_description);
+ /* Make sure we never try to use DMA in */
+ /* for the port again. */
+ info->dma_in_enabled = 0;
+ } else if (cris_request_dma(info->dma_in_nbr,
+ info->dma_in_irq_description,
+ DMA_VERBOSE_ON_ERROR,
+ info->dma_owner)) {
+ free_irq(info->dma_in_irq_nbr, info);
+ printk(KERN_WARNING "DMA '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_in_irq_description);
+ /* Make sure we never try to use DMA in */
+ /* for the port again. */
+ info->dma_in_enabled = 0;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ else
+ printk(KERN_DEBUG "DMA irq '%s' allocated\n",
+ info->dma_in_irq_description);
+#endif
+ }
+ if (info->dma_out_enabled) {
+ if (request_irq(info->dma_out_irq_nbr,
+ tr_interrupt,
+ info->dma_out_irq_flags,
+ info->dma_out_irq_description,
+ info)) {
+ printk(KERN_WARNING "DMA irq '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_out_irq_description);
+ /* Make sure we never try to use DMA out */
+ /* for the port again. */
+ info->dma_out_enabled = 0;
+ } else if (cris_request_dma(info->dma_out_nbr,
+ info->dma_out_irq_description,
+ DMA_VERBOSE_ON_ERROR,
+ info->dma_owner)) {
+ free_irq(info->dma_out_irq_nbr, info);
+ printk(KERN_WARNING "DMA '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_out_irq_description);
+ /* Make sure we never try to use DMA out */
+ /* for the port again. */
+ info->dma_out_enabled = 0;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ else
+ printk(KERN_DEBUG "DMA irq '%s' allocated\n",
+ info->dma_out_irq_description);
+#endif
+ }
+ }
+
+ /*
* Start up the serial port
*/
retval = startup(info);
- if (retval)
+ if (retval) {
+ if (allocated_resources)
+ deinit_port(info);
+
+ /* FIXME Decrease count info->count here too? */
return retval;
+ }
+
retval = block_til_ready(tty, filp, info);
if (retval) {
@@ -4604,6 +4193,9 @@ rs_open(struct tty_struct *tty, struct file * filp)
printk("rs_open returning after block_til_ready with %d\n",
retval);
#endif
+ if (allocated_resources)
+ deinit_port(info);
+
return retval;
}
@@ -4793,6 +4385,8 @@ static const struct tty_operations rs_ops = {
.send_xchar = rs_send_xchar,
.wait_until_sent = rs_wait_until_sent,
.read_proc = rs_read_proc,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset
};
static int __init
@@ -4810,9 +4404,27 @@ rs_init(void)
/* Setup the timed flush handler system */
#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER)
- init_timer(&flush_timer);
- flush_timer.function = timed_flush_handler;
- mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
+ setup_timer(&flush_timer, timed_flush_handler, 0);
+ mod_timer(&flush_timer, jiffies + 5);
+#endif
+
+#if defined(CONFIG_ETRAX_RS485)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
+ if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit,
+ rs485_pa_bit)) {
+ printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
+ "RS485 pin\n");
+ return -EBUSY;
+ }
+#endif
+#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
+ if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit,
+ rs485_port_g_bit)) {
+ printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
+ "RS485 pin\n");
+ return -EBUSY;
+ }
+#endif
#endif
/* Initialize the tty_driver structure */
@@ -4839,6 +4451,16 @@ rs_init(void)
/* do some initializing for the separate ports */
for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
+ if (info->enabled) {
+ if (cris_request_io_interface(info->io_if,
+ info->io_if_description)) {
+ printk(KERN_CRIT "ETRAX100LX async serial: "
+ "Could not allocate IO pins for "
+ "%s, port %d\n",
+ info->io_if_description, i);
+ info->enabled = 0;
+ }
+ }
info->uses_dma_in = 0;
info->uses_dma_out = 0;
info->line = i;
@@ -4872,7 +4494,7 @@ rs_init(void)
info->rs485.delay_rts_before_send = 0;
info->rs485.enabled = 0;
#endif
- INIT_WORK(&info->work, do_softint, info);
+ INIT_WORK(&info->work, do_softint);
if (info->enabled) {
printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
@@ -4890,64 +4512,17 @@ rs_init(void)
#endif
#ifndef CONFIG_SVINTO_SIM
+#ifndef CONFIG_ETRAX_KGDB
/* Not needed in simulator. May only complicate stuff. */
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
- if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL))
- panic("irq8");
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
- if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL))
- panic("irq22");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
- if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL))
- panic("irq23");
-#endif
-#endif
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
- if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL))
- panic("irq24");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
- if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL))
- panic("irq25");
-#endif
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- /* DMA Shared with par0 (and SCSI0 and ATA) */
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
- if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL))
- panic("irq18");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
- if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL))
- panic("irq19");
-#endif
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
- if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL))
- panic("irq20");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
- if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL))
- panic("irq21");
-#endif
-#endif
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "serial ", driver))
+ panic("%s: Failed to request irq8", __FUNCTION__);
-#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED,
- "fast serial dma timeout", NULL)) {
- printk(KERN_CRIT "err: timer1 irq\n");
- }
#endif
#endif /* CONFIG_SVINTO_SIM */
- debug_write_function = rs_debug_write_function;
+
return 0;
}
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
new file mode 100644
index 00000000000..ccd0f32b737
--- /dev/null
+++ b/drivers/serial/crisv10.h
@@ -0,0 +1,146 @@
+/*
+ * serial.h: Arch-dep definitions for the Etrax100 serial driver.
+ *
+ * Copyright (C) 1998-2007 Axis Communications AB
+ */
+
+#ifndef _ETRAX_SERIAL_H
+#define _ETRAX_SERIAL_H
+
+#include <linux/circ_buf.h>
+#include <asm/termios.h>
+#include <asm/dma.h>
+#include <asm/arch/io_interface_mux.h>
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+#define SERIAL_RECV_DESCRIPTORS 8
+
+struct etrax_recv_buffer {
+ struct etrax_recv_buffer *next;
+ unsigned short length;
+ unsigned char error;
+ unsigned char pad;
+
+ unsigned char buffer[0];
+};
+
+struct e100_serial {
+ int baud;
+ volatile u8 *port; /* R_SERIALx_CTRL */
+ u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */
+
+ /* Output registers */
+ volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
+ volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */
+ volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */
+ const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */
+
+ /* Input registers */
+ volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
+ volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */
+ volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */
+ volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */
+
+ int flags; /* defined in tty.h */
+
+ u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
+ u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
+ u8 iseteop; /* bit number for R_SET_EOP for the input dma */
+ int enabled; /* Set to 1 if the port is enabled in HW config */
+
+ u8 dma_out_enabled; /* Set to 1 if DMA should be used */
+ u8 dma_in_enabled; /* Set to 1 if DMA should be used */
+
+ /* end of fields defined in rs_table[] in .c-file */
+ int dma_owner;
+ unsigned int dma_in_nbr;
+ unsigned int dma_out_nbr;
+ unsigned int dma_in_irq_nbr;
+ unsigned int dma_out_irq_nbr;
+ unsigned long dma_in_irq_flags;
+ unsigned long dma_out_irq_flags;
+ char *dma_in_irq_description;
+ char *dma_out_irq_description;
+
+ enum cris_io_interface io_if;
+ char *io_if_description;
+
+ u8 uses_dma_in; /* Set to 1 if DMA is used */
+ u8 uses_dma_out; /* Set to 1 if DMA is used */
+ u8 forced_eop; /* a fifo eop has been forced */
+ int baud_base; /* For special baudrates */
+ int custom_divisor; /* For special baudrates */
+ struct etrax_dma_descr tr_descr;
+ struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS];
+ int cur_rec_descr;
+
+ volatile int tr_running; /* 1 if output is running */
+
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int type; /* PORT_ETRAX */
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ struct circ_buf xmit;
+ struct etrax_recv_buffer *first_recv_buffer;
+ struct etrax_recv_buffer *last_recv_buffer;
+ unsigned int recv_cnt;
+ unsigned int max_recv_cnt;
+
+ struct work_struct work;
+ struct async_icount icount; /* error-statistics etc.*/
+ struct ktermios normal_termios;
+ struct ktermios callout_termios;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ unsigned long char_time_usec; /* The time for 1 char, in usecs */
+ unsigned long flush_time_usec; /* How often we should flush */
+ unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */
+ unsigned long last_tx_active; /* Last tx time in jiffies */
+ unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */
+ unsigned long last_rx_active; /* Last rx time in jiffies */
+
+ int break_detected_cnt;
+ int errorcode;
+
+#ifdef CONFIG_ETRAX_RS485
+ struct rs485_control rs485; /* RS-485 support */
+#endif
+};
+
+/* this PORT is not in the standard serial.h. it's not actually used for
+ * anything since we only have one type of async serial-port anyway in this
+ * system.
+ */
+
+#define PORT_ETRAX 1
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+#endif /* __KERNEL__ */
+
+#endif /* !_ETRAX_SERIAL_H */
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index f3257f708ef..9c95bc0398a 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -45,8 +45,6 @@
#include "ip22zilog.h"
-void ip22_do_break(void);
-
/*
* On IP22 we need to delay after register accesses but we do not need to
* flush writes.
@@ -81,12 +79,9 @@ struct uart_ip22zilog_port {
#define IP22ZILOG_FLAG_REGS_HELD 0x00000040
#define IP22ZILOG_FLAG_TX_STOPPED 0x00000080
#define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100
+#define IP22ZILOG_FLAG_RESET_DONE 0x00000200
- unsigned int cflag;
-
- /* L1-A keyboard break state. */
- int kbd_id;
- int l1_down;
+ unsigned int tty_break;
unsigned char parity_mask;
unsigned char prev_status;
@@ -250,13 +245,26 @@ static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up,
}
}
-static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
- struct zilog_channel *channel)
+#define Rx_BRK 0x0100 /* BREAK event software flag. */
+#define Rx_SYS 0x0200 /* SysRq event software flag. */
+
+static struct tty_struct *ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
+ struct zilog_channel *channel)
{
- struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */
+ struct tty_struct *tty;
+ unsigned char ch, flag;
+ unsigned int r1;
+
+ tty = NULL;
+ if (up->port.info != NULL &&
+ up->port.info->tty != NULL)
+ tty = up->port.info->tty;
- while (1) {
- unsigned char ch, r1, flag;
+ for (;;) {
+ ch = readb(&channel->control);
+ ZSDELAY();
+ if (!(ch & Rx_CH_AV))
+ break;
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -265,43 +273,26 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
ZS_WSYNC(channel);
}
- ch = readb(&channel->control);
- ZSDELAY();
-
- /* This funny hack depends upon BRK_ABRT not interfering
- * with the other bits we care about in R1.
- */
- if (ch & BRK_ABRT)
- r1 |= BRK_ABRT;
-
ch = readb(&channel->data);
ZSDELAY();
ch &= up->parity_mask;
- if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) {
- /* Wait for BREAK to deassert to avoid potentially
- * confusing the PROM.
- */
- while (1) {
- ch = readb(&channel->control);
- ZSDELAY();
- if (!(ch & BRK_ABRT))
- break;
- }
- ip22_do_break();
- return;
- }
+ /* Handle the null char got when BREAK is removed. */
+ if (!ch)
+ r1 |= up->tty_break;
/* A real serial line, record the character and status. */
flag = TTY_NORMAL;
up->port.icount.rx++;
- if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
- if (r1 & BRK_ABRT) {
- r1 &= ~(PAR_ERR | CRC_ERR);
+ if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | Rx_SYS | Rx_BRK)) {
+ up->tty_break = 0;
+
+ if (r1 & (Rx_SYS | Rx_BRK)) {
up->port.icount.brk++;
- if (uart_handle_break(&up->port))
- goto next_char;
+ if (r1 & Rx_SYS)
+ continue;
+ r1 &= ~(PAR_ERR | CRC_ERR);
}
else if (r1 & PAR_ERR)
up->port.icount.parity++;
@@ -310,30 +301,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
if (r1 & Rx_OVR)
up->port.icount.overrun++;
r1 &= up->port.read_status_mask;
- if (r1 & BRK_ABRT)
+ if (r1 & Rx_BRK)
flag = TTY_BREAK;
else if (r1 & PAR_ERR)
flag = TTY_PARITY;
else if (r1 & CRC_ERR)
flag = TTY_FRAME;
}
- if (uart_handle_sysrq_char(&up->port, ch))
- goto next_char;
- if (up->port.ignore_status_mask == 0xff ||
- (r1 & up->port.ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
+ if (uart_handle_sysrq_char(&up->port, ch))
+ continue;
- if (r1 & Rx_OVR)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- next_char:
- ch = readb(&channel->control);
- ZSDELAY();
- if (!(ch & Rx_CH_AV))
- break;
+ if (tty)
+ uart_insert_char(&up->port, r1, Rx_OVR, ch, flag);
}
-
- tty_flip_buffer_push(tty);
+ return tty;
}
static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
@@ -348,6 +330,15 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
ZSDELAY();
ZS_WSYNC(channel);
+ if (up->curregs[R15] & BRKIE) {
+ if ((status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) {
+ if (uart_handle_break(&up->port))
+ up->tty_break = Rx_SYS;
+ else
+ up->tty_break = Rx_BRK;
+ }
+ }
+
if (ZS_WANTS_MODEM_STATUS(up)) {
if (status & SYNC)
up->port.icount.dsr++;
@@ -356,10 +347,10 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
* But it does not tell us which bit has changed, we have to keep
* track of this ourselves.
*/
- if ((status & DCD) ^ up->prev_status)
+ if ((status ^ up->prev_status) ^ DCD)
uart_handle_dcd_change(&up->port,
(status & DCD));
- if ((status & CTS) ^ up->prev_status)
+ if ((status ^ up->prev_status) ^ CTS)
uart_handle_cts_change(&up->port,
(status & CTS));
@@ -447,19 +438,21 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
while (up) {
struct zilog_channel *channel
= ZILOG_CHANNEL_FROM_PORT(&up->port);
+ struct tty_struct *tty;
unsigned char r3;
spin_lock(&up->port.lock);
r3 = read_zsreg(channel, R3);
/* Channel A */
+ tty = NULL;
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
writeb(RES_H_IUS, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
if (r3 & CHARxIP)
- ip22zilog_receive_chars(up, channel);
+ tty = ip22zilog_receive_chars(up, channel);
if (r3 & CHAEXT)
ip22zilog_status_handle(up, channel);
if (r3 & CHATxIP)
@@ -467,18 +460,22 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
}
spin_unlock(&up->port.lock);
+ if (tty)
+ tty_flip_buffer_push(tty);
+
/* Channel B */
up = up->next;
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
spin_lock(&up->port.lock);
+ tty = NULL;
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
writeb(RES_H_IUS, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
if (r3 & CHBRxIP)
- ip22zilog_receive_chars(up, channel);
+ tty = ip22zilog_receive_chars(up, channel);
if (r3 & CHBEXT)
ip22zilog_status_handle(up, channel);
if (r3 & CHBTxIP)
@@ -486,6 +483,9 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
}
spin_unlock(&up->port.lock);
+ if (tty)
+ tty_flip_buffer_push(tty);
+
up = up->next;
}
@@ -681,11 +681,46 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&port->lock, flags);
}
+static void __ip22zilog_reset(struct uart_ip22zilog_port *up)
+{
+ struct zilog_channel *channel;
+ int i;
+
+ if (up->flags & IP22ZILOG_FLAG_RESET_DONE)
+ return;
+
+ /* Let pending transmits finish. */
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+ for (i = 0; i < 1000; i++) {
+ unsigned char stat = read_zsreg(channel, R1);
+ if (stat & ALL_SNT)
+ break;
+ udelay(100);
+ }
+
+ if (!ZS_IS_CHANNEL_A(up)) {
+ up++;
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+ }
+ write_zsreg(channel, R9, FHWRES);
+ ZSDELAY_LONG();
+ (void) read_zsreg(channel, R0);
+
+ up->flags |= IP22ZILOG_FLAG_RESET_DONE;
+ up->next->flags |= IP22ZILOG_FLAG_RESET_DONE;
+}
+
static void __ip22zilog_startup(struct uart_ip22zilog_port *up)
{
struct zilog_channel *channel;
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+
+ __ip22zilog_reset(up);
+
+ __load_zsregs(channel, up->curregs);
+ /* set master interrupt enable */
+ write_zsreg(channel, R9, up->curregs[R9]);
up->prev_status = readb(&channel->control);
/* Enable receiver and transmitter. */
@@ -859,8 +894,6 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
else
up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS;
- up->cflag = termios->c_cflag;
-
ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
uart_update_timeout(port, termios->c_cflag, baud);
@@ -992,74 +1025,29 @@ ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
spin_unlock_irqrestore(&up->port.lock, flags);
}
-void
-ip22serial_console_termios(struct console *con, char *options)
-{
- int baud = 9600, bits = 8, cflag;
- int parity = 'n';
- int flow = 'n';
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- cflag = CREAD | HUPCL | CLOCAL;
-
- switch (baud) {
- case 150: cflag |= B150; break;
- case 300: cflag |= B300; break;
- case 600: cflag |= B600; break;
- case 1200: cflag |= B1200; break;
- case 2400: cflag |= B2400; break;
- case 4800: cflag |= B4800; break;
- case 9600: cflag |= B9600; break;
- case 19200: cflag |= B19200; break;
- case 38400: cflag |= B38400; break;
- default: baud = 9600; cflag |= B9600; break;
- }
-
- con->cflag = cflag | CS8; /* 8N1 */
-
- uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud);
-}
-
static int __init ip22zilog_console_setup(struct console *con, char *options)
{
struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
unsigned long flags;
- int baud, brg;
-
- printk("Console: ttyS%d (IP22-Zilog)\n", con->index);
+ int baud = 9600, bits = 8;
+ int parity = 'n';
+ int flow = 'n';
- /* Get firmware console settings. */
- ip22serial_console_termios(con, options);
+ up->flags |= IP22ZILOG_FLAG_IS_CONS;
- /* Firmware console speed is limited to 150-->38400 baud so
- * this hackish cflag thing is OK.
- */
- switch (con->cflag & CBAUD) {
- case B150: baud = 150; break;
- case B300: baud = 300; break;
- case B600: baud = 600; break;
- case B1200: baud = 1200; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- default: case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- };
-
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+ printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index);
spin_lock_irqsave(&up->port.lock, flags);
- up->curregs[R15] = BRKIE;
- ip22zilog_convert_to_zs(up, con->cflag, 0, brg);
+ up->curregs[R15] |= BRKIE;
__ip22zilog_startup(up);
spin_unlock_irqrestore(&up->port.lock, flags);
- return 0;
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ return uart_set_options(&up->port, con, baud, parity, bits, flow);
}
static struct uart_driver ip22zilog_reg;
@@ -1140,25 +1128,10 @@ static void __init ip22zilog_prepare(void)
up[(chip * 2) + 1].port.line = (chip * 2) + 1;
up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A;
}
-}
-
-static void __init ip22zilog_init_hw(void)
-{
- int i;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- unsigned long flags;
- int baud, brg;
- spin_lock_irqsave(&up->port.lock, flags);
-
- if (ZS_IS_CHANNEL_A(up)) {
- write_zsreg(channel, R9, FHWRES);
- ZSDELAY_LONG();
- (void) read_zsreg(channel, R0);
- }
+ for (channel = 0; channel < NUM_CHANNELS; channel++) {
+ struct uart_ip22zilog_port *up = &ip22zilog_port_table[channel];
+ int brg;
/* Normal serial TTY. */
up->parity_mask = 0xff;
@@ -1169,16 +1142,10 @@ static void __init ip22zilog_init_hw(void)
up->curregs[R9] = NV | MIE;
up->curregs[R10] = NRZ;
up->curregs[R11] = TCBR | RCBR;
- baud = 9600;
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+ brg = BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR);
up->curregs[R12] = (brg & 0xff);
up->curregs[R13] = (brg >> 8) & 0xff;
up->curregs[R14] = BRENAB;
- __load_zsregs(channel, up->curregs);
- /* set master interrupt enable */
- write_zsreg(channel, R9, up->curregs[R9]);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
}
}
@@ -1195,8 +1162,6 @@ static int __init ip22zilog_ports_init(void)
panic("IP22-Zilog: Unable to register zs interrupt handler.\n");
}
- ip22zilog_init_hw();
-
ret = uart_register_driver(&ip22zilog_reg);
if (ret == 0) {
int i;
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index af3a011b2b2..352fcb8926a 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -585,11 +585,11 @@ serial_pxa_type(struct uart_port *port)
return up->name;
}
-#ifdef CONFIG_SERIAL_PXA_CONSOLE
-
static struct uart_pxa_port *serial_pxa_ports[4];
static struct uart_driver serial_pxa_reg;
+#ifdef CONFIG_SERIAL_PXA_CONSOLE
+
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/*
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index e89ae29645d..d24621ce799 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -77,7 +77,6 @@
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
# define SCSPTR0 0xA4400000 /* 16 bit SCIF */
-# define SCI_NPORTS 2
# define SCIF_ORER 0x0001 /* overrun error bit */
# define PACR 0xa4050100
# define PBCR 0xa4050102
@@ -102,12 +101,6 @@
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-# define SCSPTR1 0xffe00020 /* 16 bit SCIF */
-# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001 /* overrun error bit */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
# include <asm/hardware.h>
# define SCIF_BASE_ADDR 0x01030000
@@ -116,8 +109,7 @@
# define SCIF_LSR2_OFFS 0x0000024
# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
# define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
-# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,
- TE=1,RE=1,REIE=1 */
+# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
@@ -577,15 +569,6 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
return 1;
}
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return ctrl_inw(SCSPTR1)&0x0001 ? 1 : 0; /* SCIF */
- else
- return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
-
-}
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
static inline int sci_rxd_in(struct uart_port *port)
{
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index dfef83f1496..a85f2d31a68 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -329,12 +329,14 @@ static struct uart_ops ulite_ops = {
static void ulite_console_wait_tx(struct uart_port *port)
{
int i;
+ u8 val;
- /* wait up to 10ms for the character(s) to be sent */
- for (i = 0; i < 10000; i++) {
- if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY)
+ /* Spin waiting for TX fifo to have space available */
+ for (i = 0; i < 100000; i++) {
+ val = readb(port->membase + ULITE_STATUS);
+ if ((val & ULITE_STATUS_TXFULL) == 0)
break;
- udelay(1);
+ cpu_relax();
}
}
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 7d873b3b051..4d0282b821b 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -107,16 +107,17 @@ int superhyway_add_devices(struct superhyway_bus *bus,
static int __init superhyway_init(void)
{
struct superhyway_bus *bus;
- int ret = 0;
+ int ret;
- device_register(&superhyway_bus_device);
+ ret = device_register(&superhyway_bus_device);
+ if (unlikely(ret))
+ return ret;
for (bus = superhyway_channels; bus->ops; bus++)
ret |= superhyway_scan_bus(bus);
return ret;
}
-
postcore_initcall(superhyway_init);
static const struct superhyway_device_id *
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a77ede598d3..abf05048c63 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -61,7 +61,7 @@ config SPI_ATMEL
config SPI_BFIN
tristate "SPI controller driver for ADI Blackfin5xx"
- depends on SPI_MASTER && BFIN
+ depends on SPI_MASTER && BLACKFIN
help
This is the SPI controller master driver for Blackfin 5xx processor.
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 0d342dcdd30..ff6a14bf128 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi)
/* chipselect must have been muxed as GPIO (e.g. in board setup) */
npcs_pin = (unsigned int)spi->controller_data;
if (!spi->controller_state) {
- ret = gpio_request(npcs_pin, "spi_npcs");
+ ret = gpio_request(npcs_pin, spi->dev.bus_id);
if (ret)
return ret;
spi->controller_state = (void *)npcs_pin;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 89769ce16f8..b31f4431849 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -457,10 +457,11 @@ done:
EXPORT_SYMBOL_GPL(spi_register_master);
-static int __unregister(struct device *dev, void *unused)
+static int __unregister(struct device *dev, void *master_dev)
{
/* note: before about 2.6.14-rc1 this would corrupt memory: */
- spi_unregister_device(to_spi_device(dev));
+ if (dev != master_dev)
+ spi_unregister_device(to_spi_device(dev));
return 0;
}
@@ -478,7 +479,8 @@ void spi_unregister_master(struct spi_master *master)
{
int dummy;
- dummy = device_for_each_child(master->dev.parent, NULL, __unregister);
+ dummy = device_for_each_child(master->dev.parent, &master->dev,
+ __unregister);
device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index 0fa25e2e80f..109d82c1abc 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -96,6 +96,7 @@ static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
static int s3c2410_spigpio_probe(struct platform_device *dev)
{
+ struct s3c2410_spigpio_info *info;
struct spi_master *master;
struct s3c2410_spigpio *sp;
int ret;
@@ -113,10 +114,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
platform_set_drvdata(dev, sp);
/* copy in the plkatform data */
- sp->info = dev->dev.platform_data;
+ info = sp->info = dev->dev.platform_data;
/* setup spi bitbang adaptor */
sp->bitbang.master = spi_master_get(master);
+ sp->bitbang.master->bus_num = info->bus_num;
sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
@@ -124,13 +126,18 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
- /* set state of spi pins */
- s3c2410_gpio_setpin(sp->info->pin_clk, 0);
- s3c2410_gpio_setpin(sp->info->pin_mosi, 0);
+ /* set state of spi pins, always assume that the clock is
+ * available, but do check the MOSI and MISO. */
+ s3c2410_gpio_setpin(info->pin_clk, 0);
+ s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT);
- s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT);
- s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT);
- s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT);
+ if (info->pin_mosi < S3C2410_GPH10) {
+ s3c2410_gpio_setpin(info->pin_mosi, 0);
+ s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT);
+ }
+
+ if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10)
+ s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT);
ret = spi_bitbang_start(&sp->bitbang);
if (ret)
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
index cc5094f37dd..363ac8e6882 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi_txx9.c
@@ -24,6 +24,7 @@
#include <linux/spi/spi.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/io.h>
#include <asm/gpio.h>
@@ -74,7 +75,6 @@ struct txx9spi {
struct list_head queue;
wait_queue_head_t waitq;
void __iomem *membase;
- int irq;
int baseclk;
struct clk *clk;
u32 max_speed_hz, min_speed_hz;
@@ -350,12 +350,12 @@ static int __init txx9spi_probe(struct platform_device *dev)
struct resource *res;
int ret = -ENODEV;
u32 mcr;
+ int irq;
master = spi_alloc_master(&dev->dev, sizeof(*c));
if (!master)
return ret;
c = spi_master_get_devdata(master);
- c->irq = -1;
platform_set_drvdata(dev, master);
INIT_WORK(&c->work, txx9spi_work);
@@ -381,32 +381,36 @@ static int __init txx9spi_probe(struct platform_device *dev)
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res)
- goto exit;
- c->membase = ioremap(res->start, res->end - res->start + 1);
+ goto exit_busy;
+ if (!devm_request_mem_region(&dev->dev,
+ res->start, res->end - res->start + 1,
+ "spi_txx9"))
+ goto exit_busy;
+ c->membase = devm_ioremap(&dev->dev,
+ res->start, res->end - res->start + 1);
if (!c->membase)
- goto exit;
+ goto exit_busy;
/* enter config mode */
mcr = txx9spi_rd(c, TXx9_SPMCR);
mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
- c->irq = platform_get_irq(dev, 0);
- if (c->irq < 0)
- goto exit;
- ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
- if (ret) {
- c->irq = -1;
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ goto exit_busy;
+ ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0,
+ "spi_txx9", c);
+ if (ret)
goto exit;
- }
c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id);
if (!c->workqueue)
- goto exit;
+ goto exit_busy;
c->last_chipselect = -1;
dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
- (unsigned long long)res->start, c->irq,
+ (unsigned long long)res->start, irq,
(c->baseclk + 500000) / 1000000);
master->bus_num = dev->id;
@@ -418,13 +422,11 @@ static int __init txx9spi_probe(struct platform_device *dev)
if (ret)
goto exit;
return 0;
+exit_busy:
+ ret = -EBUSY;
exit:
if (c->workqueue)
destroy_workqueue(c->workqueue);
- if (c->irq >= 0)
- free_irq(c->irq, c);
- if (c->membase)
- iounmap(c->membase);
if (c->clk) {
clk_disable(c->clk);
clk_put(c->clk);
@@ -442,8 +444,6 @@ static int __exit txx9spi_remove(struct platform_device *dev)
spi_unregister_master(master);
platform_set_drvdata(dev, NULL);
destroy_workqueue(c->workqueue);
- free_irq(c->irq, c);
- iounmap(c->membase);
clk_disable(c->clk);
clk_put(c->clk);
spi_master_put(master);
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
index 6da58ca48b3..455991fbe28 100644
--- a/drivers/spi/tle62x0.c
+++ b/drivers/spi/tle62x0.c
@@ -107,8 +107,11 @@ static ssize_t tle62x0_status_show(struct device *dev,
mutex_lock(&st->lock);
ret = tle62x0_read(st);
-
dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+ if (ret < 0) {
+ mutex_unlock(&st->lock);
+ return ret;
+ }
for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
fault <<= 8;
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index c12a741b557..85a20546e82 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -440,6 +440,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
break;
case SSB_BUSTYPE_PCMCIA:
#ifdef CONFIG_SSB_PCMCIAHOST
+ sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
dev->parent = &bus->host_pcmcia->dev;
#endif
break;
@@ -1147,7 +1148,10 @@ static int __init ssb_modinit(void)
return err;
}
-subsys_initcall(ssb_modinit);
+/* ssb must be initialized after PCI but before the ssb drivers.
+ * That means we must use some initcall between subsys_initcall
+ * and device_initcall. */
+fs_initcall(ssb_modinit);
static void __exit ssb_modexit(void)
{
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index b6abee846f0..bb44a76b3eb 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -63,17 +63,17 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
err = pcmcia_access_configuration_register(pdev, &reg);
if (err != CS_SUCCESS)
goto error;
- read_addr |= (reg.Value & 0xF) << 12;
+ read_addr |= ((u32)(reg.Value & 0x0F)) << 12;
reg.Offset = 0x30;
err = pcmcia_access_configuration_register(pdev, &reg);
if (err != CS_SUCCESS)
goto error;
- read_addr |= reg.Value << 16;
+ read_addr |= ((u32)reg.Value) << 16;
reg.Offset = 0x32;
err = pcmcia_access_configuration_register(pdev, &reg);
if (err != CS_SUCCESS)
goto error;
- read_addr |= reg.Value << 24;
+ read_addr |= ((u32)reg.Value) << 24;
cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
if (cur_core == coreidx)
@@ -152,28 +152,29 @@ error:
goto out_unlock;
}
-/* These are the main device register access functions.
- * do_select_core is inline to have the likely hotpath inline.
- * All unlikely codepaths are out-of-line. */
-static inline int do_select_core(struct ssb_bus *bus,
- struct ssb_device *dev,
- u16 *offset)
+static int select_core_and_segment(struct ssb_device *dev,
+ u16 *offset)
{
+ struct ssb_bus *bus = dev->bus;
int err;
- u8 need_seg = (*offset >= 0x800) ? 1 : 0;
+ u8 need_segment;
+
+ if (*offset >= 0x800) {
+ *offset -= 0x800;
+ need_segment = 1;
+ } else
+ need_segment = 0;
if (unlikely(dev != bus->mapped_device)) {
err = ssb_pcmcia_switch_core(bus, dev);
if (unlikely(err))
return err;
}
- if (unlikely(need_seg != bus->mapped_pcmcia_seg)) {
- err = ssb_pcmcia_switch_segment(bus, need_seg);
+ if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {
+ err = ssb_pcmcia_switch_segment(bus, need_segment);
if (unlikely(err))
return err;
}
- if (need_seg == 1)
- *offset -= 0x800;
return 0;
}
@@ -181,32 +182,31 @@ static inline int do_select_core(struct ssb_bus *bus,
static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
- u16 x;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return 0xFFFF;
- x = readw(bus->mmio + offset);
- return x;
+ return readw(bus->mmio + offset);
}
static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
- u32 x;
+ u32 lo, hi;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return 0xFFFFFFFF;
- x = readl(bus->mmio + offset);
+ lo = readw(bus->mmio + offset);
+ hi = readw(bus->mmio + offset + 2);
- return x;
+ return (lo | (hi << 16));
}
static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
{
struct ssb_bus *bus = dev->bus;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return;
writew(value, bus->mmio + offset);
}
@@ -215,12 +215,12 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
{
struct ssb_bus *bus = dev->bus;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return;
- readw(bus->mmio + offset);
- writew(value >> 16, bus->mmio + offset + 2);
- readw(bus->mmio + offset);
- writew(value, bus->mmio + offset);
+ writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3);
+ writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2);
+ writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1);
+ writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0);
}
/* Not "static", as it's used in main.c */
diff --git a/drivers/usb/README b/drivers/usb/README
index 3c843412855..284f46b3e1c 100644
--- a/drivers/usb/README
+++ b/drivers/usb/README
@@ -39,12 +39,12 @@ first subdirectory in the list below that it fits into.
image/ - This is for still image drivers, like scanners or
digital cameras.
-input/ - This is for any driver that uses the input subsystem,
+../input/ - This is for any driver that uses the input subsystem,
like keyboard, mice, touchscreens, tablets, etc.
-media/ - This is for multimedia drivers, like video cameras,
+../media/ - This is for multimedia drivers, like video cameras,
radios, and any other drivers that talk to the v4l
subsystem.
-net/ - This is for network drivers.
+../net/ - This is for network drivers.
serial/ - This is for USB to serial drivers.
storage/ - This is for USB mass-storage drivers.
class/ - This is for all USB device drivers that do not fit
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 8586817698a..c51f8e9312e 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -585,9 +585,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
- if (!dev)
- return -ENODEV;
-
/* driver is often null here; dev_dbg() would oops */
pr_debug ("usb %s: uevent\n", dev->bus_id);
@@ -631,14 +628,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
- if (add_uevent_var(env, "BUSNUM=%03d",
- usb_dev->bus->busnum))
- return -ENOMEM;
-
- if (add_uevent_var(env, "DEVNUM=%03d",
- usb_dev->devnum))
- return -ENOMEM;
-
return 0;
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fea8256a18d..d5ed3fa9e30 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1311,8 +1311,8 @@ void usb_hcd_flush_endpoint(struct usb_device *udev,
hcd = bus_to_hcd(udev->bus);
/* No more submits can occur */
-rescan:
spin_lock_irq(&hcd_urb_list_lock);
+rescan:
list_for_each_entry (urb, &ep->urb_list, urb_list) {
int is_in;
@@ -1345,6 +1345,7 @@ rescan:
usb_put_urb (urb);
/* list contents may have changed */
+ spin_lock(&hcd_urb_list_lock);
goto rescan;
}
spin_unlock_irq(&hcd_urb_list_lock);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 036c3dea855..13b326a1337 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -335,7 +335,7 @@ static void kick_khubd(struct usb_hub *hub)
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
spin_lock_irqsave(&hub_event_lock, flags);
- if (!hub->disconnected & list_empty(&hub->event_list)) {
+ if (!hub->disconnected && list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
wake_up(&khubd_wait);
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 316a746e008..fcd40ecbeec 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
struct usb_host_interface *alt;
int ret;
int manual = 0;
- int changed;
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
@@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
*/
/* prevent submissions using previous endpoint settings */
- changed = (iface->cur_altsetting != alt);
- if (changed && device_is_registered(&iface->dev))
+ if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
usb_remove_sysfs_intf_files(iface);
usb_disable_interface(dev, iface);
@@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* (Likewise, EP0 never "halts" on well designed devices.)
*/
usb_enable_interface(dev, iface);
- if (changed && device_is_registered(&iface->dev))
+ if (device_is_registered(&iface->dev))
usb_create_sysfs_intf_files(iface);
return 0;
@@ -1348,34 +1346,10 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
struct usb_interface *intf;
struct usb_host_interface *alt;
- if (!dev)
- return -ENODEV;
-
- /* driver is often null here; dev_dbg() would oops */
- pr_debug ("usb %s: uevent\n", dev->bus_id);
-
intf = to_usb_interface(dev);
usb_dev = interface_to_usbdev(intf);
alt = intf->cur_altsetting;
-#ifdef CONFIG_USB_DEVICEFS
- if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
- usb_dev->bus->busnum, usb_dev->devnum))
- return -ENOMEM;
-#endif
-
- if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice)))
- return -ENOMEM;
-
- if (add_uevent_var(env, "TYPE=%d/%d/%d",
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol))
- return -ENOMEM;
-
if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass,
@@ -1641,12 +1615,6 @@ free_interfaces:
intf->dev.bus_id, ret);
continue;
}
-
- /* The driver's probe method can call usb_set_interface(),
- * which would mean the interface's sysfs files are already
- * created. Just in case, we'll remove them first.
- */
- usb_remove_sysfs_intf_files(intf);
usb_create_sysfs_intf_files(intf);
}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index b04afd06e50..32bd130b1ee 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
+ if (intf->sysfs_files_created)
+ return 0;
retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
if (retval)
return retval;
@@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
if (intf->intf_assoc)
retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
usb_create_intf_ep_files(intf, udev);
+ intf->sysfs_files_created = 1;
return 0;
}
@@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
{
struct device *dev = &intf->dev;
+ if (!intf->sysfs_files_created)
+ return;
usb_remove_intf_ep_files(intf);
device_remove_file(dev, &dev_attr_interface);
sysfs_remove_group(&dev->kobj, &intf_attr_grp);
sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
+ intf->sysfs_files_created = 0;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index c4a6f1095b8..8f142370103 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -192,9 +192,34 @@ static void usb_release_dev(struct device *dev)
kfree(udev);
}
+#ifdef CONFIG_HOTPLUG
+static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct usb_device *usb_dev;
+
+ usb_dev = to_usb_device(dev);
+
+ if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum))
+ return -ENOMEM;
+
+ return 0;
+}
+
+#else
+
+static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_HOTPLUG */
+
struct device_type usb_device_type = {
.name = "usb_device",
.release = usb_release_dev,
+ .uevent = usb_dev_uevent,
};
#ifdef CONFIG_PM
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 87c4f50dfb6..d377154658b 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1241,14 +1241,14 @@ static void pullup_enable(struct omap_udc *udc)
udc->gadget.dev.parent->power.power_state = PMSG_ON;
udc->gadget.dev.power.power_state = PMSG_ON;
UDC_SYSCON1_REG |= UDC_PULLUP_EN;
- if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx())
+ if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
OTG_CTRL_REG |= OTG_BSESSVLD;
UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
}
static void pullup_disable(struct omap_udc *udc)
{
- if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx())
+ if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
OTG_CTRL_REG &= ~OTG_BSESSVLD;
UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
@@ -1386,7 +1386,7 @@ static void update_otg(struct omap_udc *udc)
{
u16 devstat;
- if (!gadget_is_otg(udc->gadget))
+ if (!gadget_is_otg(&udc->gadget))
return;
if (OTG_CTRL_REG & OTG_ID)
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index e3e90f8a75e..4ce050c3d13 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -52,10 +52,10 @@
#include <asm/arch/irqs.h>
#include <asm/arch/hardware.h>
-#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-udc.h>
-#include <asm/arch/udc.h>
+
+#include <asm/plat-s3c24xx/regs-udc.h>
+#include <asm/plat-s3c24xx/udc.h>
#include <asm/mach-types.h>
@@ -1511,7 +1511,11 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
unsigned int value;
dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ /* some cpus cannot read from an line configured to IRQ! */
+ s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT);
value = s3c2410_gpio_getpin(udc_info->vbus_pin);
+ s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2);
if (udc_info->vbus_pin_inverted)
value = !value;
@@ -1872,9 +1876,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
if (udc_info && udc_info->vbus_pin > 0) {
irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
retval = request_irq(irq, s3c2410_udc_vbus_irq,
- IRQF_DISABLED | IRQF_TRIGGER_RISING
- | IRQF_TRIGGER_FALLING,
- gadget_name, udc);
+ IRQF_DISABLED | IRQF_TRIGGER_RISING
+ | IRQF_TRIGGER_FALLING | IRQF_SHARED,
+ gadget_name, udc);
if (retval != 0) {
dev_err(dev, "can't get vbus irq %i, err %d\n",
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 177e78ed241..49a91c5ee51 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -156,7 +156,7 @@ config USB_OHCI_HCD_PCI
config USB_OHCI_HCD_SSB
bool "OHCI support for Broadcom SSB OHCI core"
- depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL
+ depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
default n
---help---
Support for the Sonics Silicon Backplane (SSB) attached
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c1514442883..5f2d74ed5ad 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -575,12 +575,15 @@ static int ehci_run (struct usb_hcd *hcd)
* from the companions to the EHCI controller. If any of the
* companions are in the middle of a port reset at the time, it
* could cause trouble. Write-locking ehci_cf_port_reset_rwsem
- * guarantees that no resets are in progress.
+ * guarantees that no resets are in progress. After we set CF,
+ * a short delay lets the hardware catch up; new resets shouldn't
+ * be started before the port switching actions could complete.
*/
down_write(&ehci_cf_port_reset_rwsem);
hcd->state = HC_STATE_RUNNING;
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+ msleep(5);
up_write(&ehci_cf_port_reset_rwsem);
temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 91e999c9f68..bc207e3c21f 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -819,7 +819,7 @@ static int mts_usb_probe(struct usb_interface *intf,
goto out_kfree2;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
- if (scsi_add_host(new_desc->host, NULL)) {
+ if (scsi_add_host(new_desc->host, &dev->dev)) {
err_retval = -EIO;
goto out_host_put;
}
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index c567aa7a41e..5a2c44e4c1f 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -79,12 +79,22 @@ MODULE_DEVICE_TABLE(usb, device_table);
#define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */
+/*
+ * The locking scheme is a vanilla 3-lock:
+ * adu_device.buflock: A spinlock, covers what IRQs touch.
+ * adutux_mutex: A Static lock to cover open_count. It would also cover
+ * any globals, but we don't have them in 2.6.
+ * adu_device.mtx: A mutex to hold across sleepers like copy_from_user.
+ * It covers all of adu_device, except the open_count
+ * and what .buflock covers.
+ */
+
/* Structure to hold all of our device specific stuff */
struct adu_device {
- struct mutex mtx; /* locks this structure */
+ struct mutex mtx;
struct usb_device* udev; /* save off the usb device pointer */
struct usb_interface* interface;
- unsigned char minor; /* the starting minor number for this device */
+ unsigned int minor; /* the starting minor number for this device */
char serial_number[8];
int open_count; /* number of times this port has been opened */
@@ -107,8 +117,11 @@ struct adu_device {
char* interrupt_out_buffer;
struct usb_endpoint_descriptor* interrupt_out_endpoint;
struct urb* interrupt_out_urb;
+ int out_urb_finished;
};
+static DEFINE_MUTEX(adutux_mutex);
+
static struct usb_driver adu_driver;
static void adu_debug_data(int level, const char *function, int size,
@@ -132,27 +145,31 @@ static void adu_debug_data(int level, const char *function, int size,
*/
static void adu_abort_transfers(struct adu_device *dev)
{
- dbg(2," %s : enter", __FUNCTION__);
+ unsigned long flags;
- if (dev == NULL) {
- dbg(1," %s : dev is null", __FUNCTION__);
- goto exit;
- }
+ dbg(2," %s : enter", __FUNCTION__);
if (dev->udev == NULL) {
dbg(1," %s : udev is null", __FUNCTION__);
goto exit;
}
- dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state);
- if (dev->udev->state == USB_STATE_NOTATTACHED) {
- dbg(1," %s : udev is not attached", __FUNCTION__);
- goto exit;
- }
-
/* shutdown transfer */
- usb_unlink_urb(dev->interrupt_in_urb);
- usb_unlink_urb(dev->interrupt_out_urb);
+
+ /* XXX Anchor these instead */
+ spin_lock_irqsave(&dev->buflock, flags);
+ if (!dev->read_urb_finished) {
+ spin_unlock_irqrestore(&dev->buflock, flags);
+ usb_kill_urb(dev->interrupt_in_urb);
+ } else
+ spin_unlock_irqrestore(&dev->buflock, flags);
+
+ spin_lock_irqsave(&dev->buflock, flags);
+ if (!dev->out_urb_finished) {
+ spin_unlock_irqrestore(&dev->buflock, flags);
+ usb_kill_urb(dev->interrupt_out_urb);
+ } else
+ spin_unlock_irqrestore(&dev->buflock, flags);
exit:
dbg(2," %s : leave", __FUNCTION__);
@@ -162,8 +179,6 @@ static void adu_delete(struct adu_device *dev)
{
dbg(2, "%s enter", __FUNCTION__);
- adu_abort_transfers(dev);
-
/* free data structures */
usb_free_urb(dev->interrupt_in_urb);
usb_free_urb(dev->interrupt_out_urb);
@@ -239,7 +254,10 @@ static void adu_interrupt_out_callback(struct urb *urb)
goto exit;
}
- wake_up_interruptible(&dev->write_wait);
+ spin_lock(&dev->buflock);
+ dev->out_urb_finished = 1;
+ wake_up(&dev->write_wait);
+ spin_unlock(&dev->buflock);
exit:
adu_debug_data(5, __FUNCTION__, urb->actual_length,
@@ -252,12 +270,17 @@ static int adu_open(struct inode *inode, struct file *file)
struct adu_device *dev = NULL;
struct usb_interface *interface;
int subminor;
- int retval = 0;
+ int retval;
dbg(2,"%s : enter", __FUNCTION__);
subminor = iminor(inode);
+ if ((retval = mutex_lock_interruptible(&adutux_mutex))) {
+ dbg(2, "%s : mutex lock failed", __FUNCTION__);
+ goto exit_no_lock;
+ }
+
interface = usb_find_interface(&adu_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d",
@@ -267,54 +290,54 @@ static int adu_open(struct inode *inode, struct file *file)
}
dev = usb_get_intfdata(interface);
- if (!dev) {
+ if (!dev || !dev->udev) {
retval = -ENODEV;
goto exit_no_device;
}
- /* lock this device */
- if ((retval = mutex_lock_interruptible(&dev->mtx))) {
- dbg(2, "%s : mutex lock failed", __FUNCTION__);
+ /* check that nobody else is using the device */
+ if (dev->open_count) {
+ retval = -EBUSY;
goto exit_no_device;
}
- /* increment our usage count for the device */
++dev->open_count;
dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
/* save device in the file's private structure */
file->private_data = dev;
- if (dev->open_count == 1) {
- /* initialize in direction */
- dev->read_buffer_length = 0;
+ /* initialize in direction */
+ dev->read_buffer_length = 0;
- /* fixup first read by having urb waiting for it */
- usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
- usb_rcvintpipe(dev->udev,
- dev->interrupt_in_endpoint->bEndpointAddress),
- dev->interrupt_in_buffer,
- le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
- adu_interrupt_in_callback, dev,
- dev->interrupt_in_endpoint->bInterval);
- /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
- dev->read_urb_finished = 0;
- retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
- if (retval)
- --dev->open_count;
- }
- mutex_unlock(&dev->mtx);
+ /* fixup first read by having urb waiting for it */
+ usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+ usb_rcvintpipe(dev->udev,
+ dev->interrupt_in_endpoint->bEndpointAddress),
+ dev->interrupt_in_buffer,
+ le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+ adu_interrupt_in_callback, dev,
+ dev->interrupt_in_endpoint->bInterval);
+ dev->read_urb_finished = 0;
+ if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL))
+ dev->read_urb_finished = 1;
+ /* we ignore failure */
+ /* end of fixup for first read */
+
+ /* initialize out direction */
+ dev->out_urb_finished = 1;
+
+ retval = 0;
exit_no_device:
+ mutex_unlock(&adutux_mutex);
+exit_no_lock:
dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
-
return retval;
}
-static int adu_release_internal(struct adu_device *dev)
+static void adu_release_internal(struct adu_device *dev)
{
- int retval = 0;
-
dbg(2," %s : enter", __FUNCTION__);
/* decrement our usage count for the device */
@@ -326,12 +349,11 @@ static int adu_release_internal(struct adu_device *dev)
}
dbg(2," %s : leave", __FUNCTION__);
- return retval;
}
static int adu_release(struct inode *inode, struct file *file)
{
- struct adu_device *dev = NULL;
+ struct adu_device *dev;
int retval = 0;
dbg(2," %s : enter", __FUNCTION__);
@@ -343,15 +365,13 @@ static int adu_release(struct inode *inode, struct file *file)
}
dev = file->private_data;
-
if (dev == NULL) {
dbg(1," %s : object is NULL", __FUNCTION__);
retval = -ENODEV;
goto exit;
}
- /* lock our device */
- mutex_lock(&dev->mtx); /* not interruptible */
+ mutex_lock(&adutux_mutex); /* not interruptible */
if (dev->open_count <= 0) {
dbg(1," %s : device not opened", __FUNCTION__);
@@ -359,19 +379,15 @@ static int adu_release(struct inode *inode, struct file *file)
goto exit;
}
+ adu_release_internal(dev);
if (dev->udev == NULL) {
/* the device was unplugged before the file was released */
- mutex_unlock(&dev->mtx);
- adu_delete(dev);
- dev = NULL;
- } else {
- /* do the work */
- retval = adu_release_internal(dev);
+ if (!dev->open_count) /* ... and we're the last user */
+ adu_delete(dev);
}
exit:
- if (dev)
- mutex_unlock(&dev->mtx);
+ mutex_unlock(&adutux_mutex);
dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
return retval;
}
@@ -393,12 +409,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
dev = file->private_data;
dbg(2," %s : dev=%p", __FUNCTION__, dev);
- /* lock this object */
+
if (mutex_lock_interruptible(&dev->mtx))
return -ERESTARTSYS;
/* verify that the device wasn't unplugged */
- if (dev->udev == NULL || dev->minor == 0) {
+ if (dev->udev == NULL) {
retval = -ENODEV;
err("No device or device unplugged %d", retval);
goto exit;
@@ -452,7 +468,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
should_submit = 1;
} else {
/* even the primary was empty - we may need to do IO */
- if (dev->interrupt_in_urb->status == -EINPROGRESS) {
+ if (!dev->read_urb_finished) {
/* somebody is doing IO */
spin_unlock_irqrestore(&dev->buflock, flags);
dbg(2," %s : submitted already", __FUNCTION__);
@@ -460,6 +476,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
/* we must initiate input */
dbg(2," %s : initiate input", __FUNCTION__);
dev->read_urb_finished = 0;
+ spin_unlock_irqrestore(&dev->buflock, flags);
usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
usb_rcvintpipe(dev->udev,
@@ -469,15 +486,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
adu_interrupt_in_callback,
dev,
dev->interrupt_in_endpoint->bInterval);
- retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
- if (!retval) {
- spin_unlock_irqrestore(&dev->buflock, flags);
- dbg(2," %s : submitted OK", __FUNCTION__);
- } else {
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+ if (retval) {
+ dev->read_urb_finished = 1;
if (retval == -ENOMEM) {
retval = bytes_read ? bytes_read : -ENOMEM;
}
- spin_unlock_irqrestore(&dev->buflock, flags);
dbg(2," %s : submit failed", __FUNCTION__);
goto exit;
}
@@ -486,10 +500,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
/* we wait for I/O to complete */
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&dev->read_wait, &wait);
- if (!dev->read_urb_finished)
+ spin_lock_irqsave(&dev->buflock, flags);
+ if (!dev->read_urb_finished) {
+ spin_unlock_irqrestore(&dev->buflock, flags);
timeout = schedule_timeout(COMMAND_TIMEOUT);
- else
+ } else {
+ spin_unlock_irqrestore(&dev->buflock, flags);
set_current_state(TASK_RUNNING);
+ }
remove_wait_queue(&dev->read_wait, &wait);
if (timeout <= 0) {
@@ -509,19 +527,23 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
retval = bytes_read;
/* if the primary buffer is empty then use it */
- if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) {
+ spin_lock_irqsave(&dev->buflock, flags);
+ if (should_submit && dev->read_urb_finished) {
+ dev->read_urb_finished = 0;
+ spin_unlock_irqrestore(&dev->buflock, flags);
usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
usb_rcvintpipe(dev->udev,
dev->interrupt_in_endpoint->bEndpointAddress),
- dev->interrupt_in_buffer,
- le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
- adu_interrupt_in_callback,
- dev,
- dev->interrupt_in_endpoint->bInterval);
- /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
- dev->read_urb_finished = 0;
- usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+ dev->interrupt_in_buffer,
+ le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+ adu_interrupt_in_callback,
+ dev,
+ dev->interrupt_in_endpoint->bInterval);
+ if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL) != 0)
+ dev->read_urb_finished = 1;
/* we ignore failure */
+ } else {
+ spin_unlock_irqrestore(&dev->buflock, flags);
}
exit:
@@ -535,24 +557,24 @@ exit:
static ssize_t adu_write(struct file *file, const __user char *buffer,
size_t count, loff_t *ppos)
{
+ DECLARE_WAITQUEUE(waita, current);
struct adu_device *dev;
size_t bytes_written = 0;
size_t bytes_to_write;
size_t buffer_size;
+ unsigned long flags;
int retval;
- int timeout = 0;
dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
dev = file->private_data;
- /* lock this object */
retval = mutex_lock_interruptible(&dev->mtx);
if (retval)
goto exit_nolock;
/* verify that the device wasn't unplugged */
- if (dev->udev == NULL || dev->minor == 0) {
+ if (dev->udev == NULL) {
retval = -ENODEV;
err("No device or device unplugged %d", retval);
goto exit;
@@ -564,42 +586,37 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
goto exit;
}
-
while (count > 0) {
- if (dev->interrupt_out_urb->status == -EINPROGRESS) {
- timeout = COMMAND_TIMEOUT;
+ add_wait_queue(&dev->write_wait, &waita);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_lock_irqsave(&dev->buflock, flags);
+ if (!dev->out_urb_finished) {
+ spin_unlock_irqrestore(&dev->buflock, flags);
- while (timeout > 0) {
- if (signal_pending(current)) {
+ mutex_unlock(&dev->mtx);
+ if (signal_pending(current)) {
dbg(1," %s : interrupted", __FUNCTION__);
+ set_current_state(TASK_RUNNING);
retval = -EINTR;
- goto exit;
+ goto exit_onqueue;
}
- mutex_unlock(&dev->mtx);
- timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
+ if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
+ dbg(1, "%s - command timed out.", __FUNCTION__);
+ retval = -ETIMEDOUT;
+ goto exit_onqueue;
+ }
+ remove_wait_queue(&dev->write_wait, &waita);
retval = mutex_lock_interruptible(&dev->mtx);
if (retval) {
retval = bytes_written ? bytes_written : retval;
goto exit_nolock;
}
- if (timeout > 0) {
- break;
- }
- dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout);
- }
-
-
- dbg(1," %s : final timeout: %d", __FUNCTION__, timeout);
-
- if (timeout == 0) {
- dbg(1, "%s - command timed out.", __FUNCTION__);
- retval = -ETIMEDOUT;
- goto exit;
- }
-
- dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
+ dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
} else {
+ spin_unlock_irqrestore(&dev->buflock, flags);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&dev->write_wait, &waita);
dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
/* write the data into interrupt_out_buffer from userspace */
@@ -622,11 +639,12 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
bytes_to_write,
adu_interrupt_out_callback,
dev,
- dev->interrupt_in_endpoint->bInterval);
- /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+ dev->interrupt_out_endpoint->bInterval);
dev->interrupt_out_urb->actual_length = bytes_to_write;
+ dev->out_urb_finished = 0;
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval < 0) {
+ dev->out_urb_finished = 1;
err("Couldn't submit interrupt_out_urb %d", retval);
goto exit;
}
@@ -637,16 +655,17 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
bytes_written += bytes_to_write;
}
}
-
- retval = bytes_written;
+ mutex_unlock(&dev->mtx);
+ return bytes_written;
exit:
- /* unlock the device */
mutex_unlock(&dev->mtx);
exit_nolock:
-
dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+ return retval;
+exit_onqueue:
+ remove_wait_queue(&dev->write_wait, &waita);
return retval;
}
@@ -831,25 +850,22 @@ static void adu_disconnect(struct usb_interface *interface)
dbg(2," %s : enter", __FUNCTION__);
dev = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
+ mutex_lock(&dev->mtx); /* not interruptible */
+ dev->udev = NULL; /* poison */
minor = dev->minor;
-
- /* give back our minor */
usb_deregister_dev(interface, &adu_class);
- dev->minor = 0;
+ mutex_unlock(&dev->mtx);
- mutex_lock(&dev->mtx); /* not interruptible */
+ mutex_lock(&adutux_mutex);
+ usb_set_intfdata(interface, NULL);
/* if the device is not opened, then we clean up right now */
dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
- if (!dev->open_count) {
- mutex_unlock(&dev->mtx);
+ if (!dev->open_count)
adu_delete(dev);
- } else {
- dev->udev = NULL;
- mutex_unlock(&dev->mtx);
- }
+
+ mutex_unlock(&adutux_mutex);
dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
(minor - ADU_MINOR_BASE));
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 49c5c5c4c43..06cb71942dc 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -144,12 +144,14 @@ static void led_disconnect(struct usb_interface *interface)
struct usb_led *dev;
dev = usb_get_intfdata (interface);
- usb_set_intfdata (interface, NULL);
device_remove_file(&interface->dev, &dev_attr_blue);
device_remove_file(&interface->dev, &dev_attr_red);
device_remove_file(&interface->dev, &dev_attr_green);
+ /* first remove the files, then set the pointer to NULL */
+ usb_set_intfdata (interface, NULL);
+
usb_put_dev(dev->udev);
kfree(dev);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 9eb4a65ee4d..d41531139c5 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -327,6 +327,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
+ unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -339,11 +340,11 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
/* Throttle the device if requested by tty */
- spin_lock(&port->lock);
+ spin_lock_irqsave(&port->lock, flags);
if (!(port->throttled = port->throttle_req))
/* Handle data and continue reading from device */
flush_and_resubmit_read_urb(port);
- spin_unlock(&port->lock);
+ spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 6bfdba6a213..feba9679ace 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1227,8 +1227,8 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
-
- dbg("%s - port%d.", __FUNCTION__, port->number);
+
+ dbg("%s - port%d.", __FUNCTION__, port->number);
/* Set some sane defaults */
p_priv->rts_state = 1;
@@ -1249,7 +1249,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
urb->dev = serial->dev;
/* make sure endpoint data toggle is synchronized with the device */
-
+
usb_clear_halt(urb->dev, urb->pipe);
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
@@ -1265,7 +1265,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
}
- /* get the terminal config for the setup message now so we don't
+ /* get the terminal config for the setup message now so we don't
* need to send 2 of them */
cflag = port->tty->termios->c_cflag;
@@ -1274,7 +1274,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
baud_rate = tty_get_baud_rate(port->tty);
- /* If no match or invalid, leave as default */
+ /* If no match or invalid, leave as default */
if (baud_rate >= 0
&& d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index a5ced7e08cb..c29c9127113 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2711,7 +2711,7 @@ static int mos7840_startup(struct usb_serial *serial)
status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
if (status < 0) {
dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
- return -1;
+ goto error;
} else
dbg("ZLP_REG5 Writing success status%d\n", status);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2cd3f1d4b68..cf8add91de0 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -86,6 +86,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
+ { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index ed603e3decd..d31f5d29998 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -104,3 +104,6 @@
#define WS002IN_VENDOR_ID 0x11f6
#define WS002IN_PRODUCT_ID 0x2001
+/* Corega CG-USBRS232R Serial Adapter */
+#define COREGA_VENDOR_ID 0x07aa
+#define COREGA_PRODUCT_ID 0x002a
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 833f6e1e372..605ebccdcd5 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -136,6 +136,8 @@ static struct usb_device_id id_table_3port [] = {
{ USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
+ { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
+ { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
{ USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
{ USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 1ba19eaa197..836a34ae6ec 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -177,6 +177,10 @@ static int slave_configure(struct scsi_device *sdev)
* is an occasional series of retries that will all fail. */
sdev->retry_hwerror = 1;
+ /* USB disks should allow restart. Some drives spin down
+ * automatically, requiring a START-STOP UNIT command. */
+ sdev->allow_restart = 1;
+
} else {
/* Non-disk-type devices don't need to blacklist any pages
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 22ab2380367..2c27721bd25 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -342,11 +342,11 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100,
US_FL_FIX_CAPACITY),
/* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */
-UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200,
- "NIKON",
- "NIKON DSC D200",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY),
+UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200,
+ "NIKON",
+ "NIKON DSC D200",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
/* Reported by Emil Larsson <emil@swip.net> */
UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101,
@@ -731,6 +731,13 @@ UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102,
US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
#endif
+/* Reported by RTE <raszilki@yandex.ru> */
+UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141,
+ "JetFlash",
+ "TS1GJF2A/120",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/* Fabrizio Fellini <fello@libero.it> */
UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210,
"Fujifilm",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc4b60f899c..5b3dbcfcda4 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -503,7 +503,7 @@ config FB_VALKYRIE
config FB_CT65550
bool "Chips 65550 display support"
- depends on (FB = y) && PPC32
+ depends on (FB = y) && PPC32 && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -641,6 +641,17 @@ config FB_VESA
You will get a boot time penguin logo at no additional cost. Please
read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
+config FB_EFI
+ bool "EFI-based Framebuffer Support"
+ depends on (FB = y) && X86
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the EFI frame buffer device driver. If the firmware on
+ your platform is UEFI2.0, select Y to add support for
+ Graphics Output Protocol for early console messages to appear.
+
config FB_IMAC
bool "Intel-based Macintosh Framebuffer Support"
depends on (FB = y) && X86 && EFI
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 59d6c45a910..83e02b3429b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -118,6 +118,7 @@ obj-$(CONFIG_FB_OMAP) += omap/
obj-$(CONFIG_FB_UVESA) += uvesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_IMAC) += imacfb.o
+obj-$(CONFIG_FB_EFI) += efifb.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 235b618b411..11a3a222dfc 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -268,6 +268,10 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
/* Turn off the LCD controller and the DMA controller */
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+ /* Wait for the LCDC core to become idle */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
+ msleep(10);
+
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
if (info->var.bits_per_pixel == 1)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 1e32b3d13f2..62867cb63fe 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -202,6 +202,7 @@ static struct pci_device_id radeonfb_pci_table[] = {
CHIP_DEF(PCI_CHIP_RV380_3154, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
CHIP_DEF(PCI_CHIP_RV370_5B60, RV380, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV370_5B62, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV370_5B63, RV380, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV370_5B64, RV380, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV370_5B65, RV380, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV370_5460, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 267422f6625..b87ed37ac0c 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
config VGA_CONSOLE
bool "VGA text console" if EMBEDDED || !X86
- depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BFIN
+ depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BLACKFIN
default y
help
Saying Y here will allow you to use Linux in text mode through a
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 5fb8675e0d6..d0e4cb61826 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -874,6 +874,8 @@ static int cyber2000fb_set_par(struct fb_info *info)
default:
BUG();
}
+ break;
+
case 24:/* TRUECOLOUR, 16m */
hw.co_pixfmt = CO_PIXFMT_24BPP;
hw.width *= 3;
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
new file mode 100644
index 00000000000..bd779ae44b1
--- /dev/null
+++ b/drivers/video/efifb.c
@@ -0,0 +1,232 @@
+/*
+ * Framebuffer driver for EFI/UEFI based system
+ *
+ * (c) 2006 Edgar Hucek <gimli@dark-green.com>
+ * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
+
+#include <video/vga.h>
+
+static struct fb_var_screeninfo efifb_defined __initdata = {
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .right_margin = 32,
+ .upper_margin = 16,
+ .lower_margin = 4,
+ .vsync_len = 4,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo efifb_fix __initdata = {
+ .id = "EFI VGA",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .accel = FB_ACCEL_NONE,
+ .visual = FB_VISUAL_TRUECOLOR,
+};
+
+static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ /*
+ * Set a single color register. The values supplied are
+ * already rounded down to the hardware's capabilities
+ * (according to the entries in the `var' structure). Return
+ * != 0 for invalid regno.
+ */
+
+ if (regno >= info->cmap.len)
+ return 1;
+
+ if (regno < 16) {
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ ((u32 *)(info->pseudo_palette))[regno] =
+ (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ }
+ return 0;
+}
+
+static struct fb_ops efifb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = efifb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int __init efifb_probe(struct platform_device *dev)
+{
+ struct fb_info *info;
+ int err;
+ unsigned int size_vmode;
+ unsigned int size_remap;
+ unsigned int size_total;
+
+ efifb_fix.smem_start = screen_info.lfb_base;
+ efifb_defined.bits_per_pixel = screen_info.lfb_depth;
+ efifb_defined.xres = screen_info.lfb_width;
+ efifb_defined.yres = screen_info.lfb_height;
+ efifb_fix.line_length = screen_info.lfb_linelength;
+
+ /* size_vmode -- that is the amount of memory needed for the
+ * used video mode, i.e. the minimum amount of
+ * memory we need. */
+ size_vmode = efifb_defined.yres * efifb_fix.line_length;
+
+ /* size_total -- all video memory we have. Used for
+ * entries, ressource allocation and bounds
+ * checking. */
+ size_total = screen_info.lfb_size;
+ if (size_total < size_vmode)
+ size_total = size_vmode;
+
+ /* size_remap -- the amount of video memory we are going to
+ * use for efifb. With modern cards it is no
+ * option to simply use size_total as that
+ * wastes plenty of kernel address space. */
+ size_remap = size_vmode * 2;
+ if (size_remap < size_vmode)
+ size_remap = size_vmode;
+ if (size_remap > size_total)
+ size_remap = size_total;
+ efifb_fix.smem_len = size_remap;
+
+ if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb"))
+ /* We cannot make this fatal. Sometimes this comes from magic
+ spaces our resource handlers simply don't know about */
+ printk(KERN_WARNING
+ "efifb: cannot reserve video memory at 0x%lx\n",
+ efifb_fix.smem_start);
+
+ info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+ if (!info) {
+ err = -ENOMEM;
+ goto err_release_mem;
+ }
+ info->pseudo_palette = info->par;
+ info->par = NULL;
+
+ info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
+ if (!info->screen_base) {
+ printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
+ "0x%x @ 0x%lx\n",
+ efifb_fix.smem_len, efifb_fix.smem_start);
+ err = -EIO;
+ goto err_unmap;
+ }
+
+ printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
+ "using %dk, total %dk\n",
+ efifb_fix.smem_start, info->screen_base,
+ size_remap/1024, size_total/1024);
+ printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+ efifb_defined.xres, efifb_defined.yres,
+ efifb_defined.bits_per_pixel, efifb_fix.line_length,
+ screen_info.pages);
+
+ efifb_defined.xres_virtual = efifb_defined.xres;
+ efifb_defined.yres_virtual = efifb_fix.smem_len /
+ efifb_fix.line_length;
+ printk(KERN_INFO "efifb: scrolling: redraw\n");
+ efifb_defined.yres_virtual = efifb_defined.yres;
+
+ /* some dummy values for timing to make fbset happy */
+ efifb_defined.pixclock = 10000000 / efifb_defined.xres *
+ 1000 / efifb_defined.yres;
+ efifb_defined.left_margin = (efifb_defined.xres / 8) & 0xf8;
+ efifb_defined.hsync_len = (efifb_defined.xres / 8) & 0xf8;
+
+ efifb_defined.red.offset = screen_info.red_pos;
+ efifb_defined.red.length = screen_info.red_size;
+ efifb_defined.green.offset = screen_info.green_pos;
+ efifb_defined.green.length = screen_info.green_size;
+ efifb_defined.blue.offset = screen_info.blue_pos;
+ efifb_defined.blue.length = screen_info.blue_size;
+ efifb_defined.transp.offset = screen_info.rsvd_pos;
+ efifb_defined.transp.length = screen_info.rsvd_size;
+
+ printk(KERN_INFO "efifb: %s: "
+ "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+ "Truecolor",
+ screen_info.rsvd_size,
+ screen_info.red_size,
+ screen_info.green_size,
+ screen_info.blue_size,
+ screen_info.rsvd_pos,
+ screen_info.red_pos,
+ screen_info.green_pos,
+ screen_info.blue_pos);
+
+ efifb_fix.ypanstep = 0;
+ efifb_fix.ywrapstep = 0;
+
+ info->fbops = &efifb_ops;
+ info->var = efifb_defined;
+ info->fix = efifb_fix;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ err = -ENOMEM;
+ goto err_unmap;
+ }
+ if (register_framebuffer(info) < 0) {
+ err = -EINVAL;
+ goto err_fb_dealoc;
+ }
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+ return 0;
+
+err_fb_dealoc:
+ fb_dealloc_cmap(&info->cmap);
+err_unmap:
+ iounmap(info->screen_base);
+ framebuffer_release(info);
+err_release_mem:
+ release_mem_region(efifb_fix.smem_start, size_total);
+ return err;
+}
+
+static struct platform_driver efifb_driver = {
+ .probe = efifb_probe,
+ .driver = {
+ .name = "efifb",
+ },
+};
+
+static struct platform_device efifb_device = {
+ .name = "efifb",
+};
+
+static int __init efifb_init(void)
+{
+ int ret;
+
+ if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+ return -ENODEV;
+
+ ret = platform_driver_register(&efifb_driver);
+
+ if (!ret) {
+ ret = platform_device_register(&efifb_device);
+ if (ret)
+ platform_driver_unregister(&efifb_driver);
+ }
+ return ret;
+}
+module_init(efifb_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c
index f836137a0ed..a0df63289b5 100644
--- a/drivers/video/fb_ddc.c
+++ b/drivers/video/fb_ddc.c
@@ -56,13 +56,12 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
int i, j;
algo_data->setscl(algo_data->data, 1);
- algo_data->setscl(algo_data->data, 0);
for (i = 0; i < 3; i++) {
/* For some old monitors we need the
* following process to initialize/stop DDC
*/
- algo_data->setsda(algo_data->data, 0);
+ algo_data->setsda(algo_data->data, 1);
msleep(13);
algo_data->setscl(algo_data->data, 1);
@@ -97,14 +96,15 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
algo_data->setsda(algo_data->data, 1);
msleep(15);
algo_data->setscl(algo_data->data, 0);
+ algo_data->setsda(algo_data->data, 0);
if (edid)
break;
}
/* Release the DDC lines when done or the Apple Cinema HD display
* will switch off
*/
- algo_data->setsda(algo_data->data, 0);
- algo_data->setscl(algo_data->data, 0);
+ algo_data->setsda(algo_data->data, 1);
+ algo_data->setscl(algo_data->data, 1);
return edid;
}
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index b9b572b293d..2e552d5bbb5 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -183,8 +183,8 @@ static struct fb_videomode default_mode_LCD __initdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-struct fb_videomode *default_mode = &default_mode_CRT;
-struct fb_var_screeninfo *default_var = &default_var_CRT;
+struct fb_videomode *default_mode __initdata = &default_mode_CRT;
+struct fb_var_screeninfo *default_var __initdata = &default_var_CRT;
static int flat_panel_enabled = 0;
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 6c227f9592a..ca13c48d19b 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -33,7 +33,7 @@ void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
#define MSR_LX_GLD_CONFIG 0x48002001
#define MSR_LX_GLCP_DOTPLL 0x4c000015
-#define MSR_LX_DF_PADSEL 0x48000011
+#define MSR_LX_DF_PADSEL 0x48002011
#define MSR_LX_DC_SPARE 0x80000011
#define MSR_LX_DF_GLCONFIG 0x48002001
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
index 6455fd2a39f..9366ef2bb5f 100644
--- a/drivers/video/imacfb.c
+++ b/drivers/video/imacfb.c
@@ -234,10 +234,6 @@ static int __init imacfb_probe(struct platform_device *dev)
size_remap = size_total;
imacfb_fix.smem_len = size_remap;
-#ifndef __i386__
- screen_info.imacpm_seg = 0;
-#endif
-
if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
printk(KERN_WARNING
"imacfb: cannot reserve video memory at 0x%lx\n",
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index b3463ddcfd6..9c56c492a69 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -51,7 +51,6 @@
#define L1GPU_DISPLAY_SYNC_HSYNC 1
#define L1GPU_DISPLAY_SYNC_VSYNC 2
-#define DDR_SIZE (0) /* used no ddr */
#define GPU_CMD_BUF_SIZE (64 * 1024)
#define GPU_IOIF (0x0d000000UL)
#define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64)
@@ -727,7 +726,7 @@ static int ps3fb_blank(int blank, struct fb_info *info)
static int ps3fb_get_vblank(struct fb_vblank *vblank)
{
- memset(vblank, 0, sizeof(&vblank));
+ memset(vblank, 0, sizeof(*vblank));
vblank->flags = FB_VBLANK_HAVE_VSYNC;
return 0;
}
@@ -1060,6 +1059,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
u64 xdr_lpar;
int status, res_index;
struct task_struct *task;
+ unsigned long max_ps3fb_size;
status = ps3_open_hv_device(dev);
if (status) {
@@ -1085,8 +1085,15 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
ps3fb_set_sync(&dev->core);
+ max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;
+ if (ps3fb_videomemory.size > max_ps3fb_size) {
+ dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n",
+ max_ps3fb_size);
+ ps3fb_videomemory.size = max_ps3fb_size;
+ }
+
/* get gpu context handle */
- status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
+ status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0,
&ps3fb.memory_handle, &ddr_lpar);
if (status) {
dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index a5333c19078..b829dc7c5ed 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -540,7 +540,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
int ret = 0;
u8 revision;
- dbg("probe called: device is %p\n", dev);
+ dbg("probe called: device is %p\n", pdev);
printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
@@ -753,8 +753,11 @@ static struct platform_driver s1d13xxxfb_driver = {
static int __init
s1d13xxxfb_init(void)
{
+
+#ifndef MODULE
if (fb_get_options("s1d13xxxfb", NULL))
return -ENODEV;
+#endif
return platform_driver_register(&s1d13xxxfb_driver);
}
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index bc7d2368373..37bd24b8d83 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1248,7 +1248,6 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
if(found_mode) {
ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
} else {
ivideo->sisfb_mode_idx = -1;
}
@@ -1260,6 +1259,8 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
return -EINVAL;
}
+ ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
+
if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
ivideo->refresh_rate = 60;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index b983d262ab7..d1d6c0facd5 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -926,8 +926,10 @@ static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count,
int start, struct fb_info *info)
{
struct uvesafb_ktask *task;
+#ifdef CONFIG_X86
struct uvesafb_par *par = info->par;
int i = par->mode_idx;
+#endif
int err = 0;
/*
@@ -1103,11 +1105,11 @@ static int uvesafb_pan_display(struct fb_var_screeninfo *var,
static int uvesafb_blank(int blank, struct fb_info *info)
{
- struct uvesafb_par *par = info->par;
struct uvesafb_ktask *task;
int err = 1;
-
#ifdef CONFIG_X86
+ struct uvesafb_par *par = info->par;
+
if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
int loop = 10000;
u8 seq = 0, crtc17 = 0;
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 15d7787dea8..69d7ea02cd4 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -96,10 +96,23 @@ static int virtio_dev_probe(struct device *_d)
return err;
}
+static int virtio_dev_remove(struct device *_d)
+{
+ struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+ struct virtio_driver *drv = container_of(dev->dev.driver,
+ struct virtio_driver, driver);
+
+ dev->config->set_status(dev, dev->config->get_status(dev)
+ & ~VIRTIO_CONFIG_S_DRIVER);
+ drv->remove(dev);
+ return 0;
+}
+
int register_virtio_driver(struct virtio_driver *driver)
{
driver->driver.bus = &virtio_bus;
driver->driver.probe = virtio_dev_probe;
+ driver->driver.remove = virtio_dev_remove;
return driver_register(&driver->driver);
}
EXPORT_SYMBOL_GPL(register_virtio_driver);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 0e4baca21b8..1dc04b6684e 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -53,7 +53,7 @@ struct vring_virtqueue
unsigned int num_added;
/* Last used index we've seen. */
- unsigned int last_used_idx;
+ u16 last_used_idx;
/* How to notify other side. FIXME: commonalize hcalls! */
void (*notify)(struct virtqueue *vq);
@@ -277,11 +277,17 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
struct vring_virtqueue *vq;
unsigned int i;
+ /* We assume num is a power of 2. */
+ if (num & (num - 1)) {
+ dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
+ return NULL;
+ }
+
vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL);
if (!vq)
return NULL;
- vring_init(&vq->vring, num, pages);
+ vring_init(&vq->vring, num, pages, PAGE_SIZE);
vq->vq.callback = callback;
vq->vq.vdev = vdev;
vq->vq.vq_ops = &vring_vq_ops;
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 299e274d241..b63b5e044a4 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -233,7 +233,7 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
{
int count, err;
- memset(st, 0, sizeof(st));
+ memset(st, 0, sizeof(*st));
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index 067c07be928..e6c4390d8bd 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -60,6 +60,20 @@ static int zorro_device_probe(struct device *dev)
}
+static int zorro_device_remove(struct device *dev)
+{
+ struct zorro_dev *z = to_zorro_dev(dev);
+ struct zorro_driver *drv = to_zorro_driver(dev->driver);
+
+ if (drv) {
+ if (drv->remove)
+ drv->remove(z);
+ z->driver = NULL;
+ }
+ return 0;
+}
+
+
/**
* zorro_register_driver - register a new Zorro driver
* @drv: the driver structure to register
@@ -128,6 +142,7 @@ struct bus_type zorro_bus_type = {
.name = "zorro",
.match = zorro_bus_match,
.probe = zorro_device_probe,
+ .remove = zorro_device_remove,
};