summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/Kconfig6
-rw-r--r--drivers/acpi/ac.c2
-rw-r--r--drivers/acpi/battery.c6
-rw-r--r--drivers/acpi/bus.c4
-rw-r--r--drivers/acpi/button.c4
-rw-r--r--drivers/acpi/cm_sbs.c46
-rw-r--r--drivers/acpi/dispatcher/dsinit.c10
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c23
-rw-r--r--drivers/acpi/dispatcher/dswexec.c4
-rw-r--r--drivers/acpi/dock.c1
-rw-r--r--drivers/acpi/ec.c2
-rw-r--r--drivers/acpi/event.c2
-rw-r--r--drivers/acpi/events/evregion.c44
-rw-r--r--drivers/acpi/events/evxface.c44
-rw-r--r--drivers/acpi/events/evxfregn.c13
-rw-r--r--drivers/acpi/executer/exconfig.c1
-rw-r--r--drivers/acpi/executer/exconvrt.c3
-rw-r--r--drivers/acpi/executer/exmutex.c4
-rw-r--r--drivers/acpi/executer/exsystem.c8
-rw-r--r--drivers/acpi/fan.c2
-rw-r--r--drivers/acpi/hotkey.c10
-rw-r--r--drivers/acpi/namespace/nsalloc.c13
-rw-r--r--drivers/acpi/osl.c90
-rw-r--r--drivers/acpi/parser/psutils.c2
-rw-r--r--drivers/acpi/pci_link.c7
-rw-r--r--drivers/acpi/power.c2
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/sleep/proc.c6
-rw-r--r--drivers/acpi/system.c6
-rw-r--r--drivers/acpi/tables/tbget.c12
-rw-r--r--drivers/acpi/tables/tbinstal.c21
-rw-r--r--drivers/acpi/tables/tbrsdt.c27
-rw-r--r--drivers/acpi/tables/tbxface.c32
-rw-r--r--drivers/acpi/thermal.c27
-rw-r--r--drivers/acpi/utilities/utalloc.c2
-rw-r--r--drivers/acpi/utilities/utdebug.c4
-rw-r--r--drivers/acpi/utilities/utdelete.c13
-rw-r--r--drivers/acpi/utilities/utmisc.c25
-rw-r--r--drivers/acpi/utilities/utmutex.c8
-rw-r--r--drivers/acpi/utilities/utstate.c7
-rw-r--r--drivers/atm/Kconfig2
-rw-r--r--drivers/base/Kconfig2
-rw-r--r--drivers/base/bus.c5
-rw-r--r--drivers/base/core.c30
-rw-r--r--drivers/block/aoe/aoechr.c2
-rw-r--r--drivers/bluetooth/bcm203x.c1
-rw-r--r--drivers/bluetooth/hci_ldisc.c4
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/char/hvsi.c2
-rw-r--r--drivers/char/ip2/ip2main.c7
-rw-r--r--drivers/char/mem.c4
-rw-r--r--drivers/char/pc8736x_gpio.c46
-rw-r--r--drivers/char/rtc.c47
-rw-r--r--drivers/char/snsc_event.c15
-rw-r--r--drivers/char/specialix.c6
-rw-r--r--drivers/edac/edac_mc.c687
-rw-r--r--drivers/hwmon/abituguru.c21
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c6
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c8
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c4
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c17
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.h2
-rw-r--r--drivers/i2c/busses/i2c-powermac.c4
-rw-r--r--drivers/i2c/busses/scx200_acb.c20
-rw-r--r--drivers/i2c/chips/pca9539.c12
-rw-r--r--drivers/i2c/i2c-core.c4
-rw-r--r--drivers/ide/legacy/ide-cs.c81
-rw-r--r--drivers/ide/pci/generic.c8
-rw-r--r--drivers/isdn/hisax/asuscom.c6
-rw-r--r--drivers/isdn/hisax/avm_a1.c2
-rw-r--r--drivers/isdn/hisax/avm_pci.c8
-rw-r--r--drivers/isdn/hisax/bkm_a4t.c4
-rw-r--r--drivers/isdn/hisax/bkm_a8.c16
-rw-r--r--drivers/isdn/hisax/config.c2
-rw-r--r--drivers/isdn/hisax/diva.c14
-rw-r--r--drivers/isdn/hisax/enternow_pci.c4
-rw-r--r--drivers/isdn/hisax/gazel.c8
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c2
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c4
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c4
-rw-r--r--drivers/isdn/hisax/hfc_pci.c6
-rw-r--r--drivers/isdn/hisax/hfcscard.c6
-rw-r--r--drivers/isdn/hisax/icc.c8
-rw-r--r--drivers/isdn/hisax/icc.h2
-rw-r--r--drivers/isdn/hisax/ipacx.c18
-rw-r--r--drivers/isdn/hisax/isurf.c4
-rw-r--r--drivers/isdn/hisax/ix1_micro.c6
-rw-r--r--drivers/isdn/hisax/jade.c6
-rw-r--r--drivers/isdn/hisax/mic.c2
-rw-r--r--drivers/isdn/hisax/netjet.c2
-rw-r--r--drivers/isdn/hisax/niccy.c4
-rw-r--r--drivers/isdn/hisax/nj_s.c4
-rw-r--r--drivers/isdn/hisax/nj_u.c4
-rw-r--r--drivers/isdn/hisax/s0box.c2
-rw-r--r--drivers/isdn/hisax/saphir.c2
-rw-r--r--drivers/isdn/hisax/sportster.c4
-rw-r--r--drivers/isdn/hisax/teleint.c2
-rw-r--r--drivers/isdn/hisax/teles0.c2
-rw-r--r--drivers/isdn/hisax/telespci.c4
-rw-r--r--drivers/isdn/hisax/w6692.c10
-rw-r--r--drivers/isdn/i4l/isdn_common.c12
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c2
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-net48xx.c115
-rw-r--r--drivers/macintosh/Kconfig5
-rw-r--r--drivers/macintosh/macio_asic.c2
-rw-r--r--drivers/macintosh/smu.c53
-rw-r--r--drivers/md/md.c86
-rw-r--r--drivers/md/raid1.c5
-rw-r--r--drivers/md/raid10.c4
-rw-r--r--drivers/md/raid5.c84
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c4
-rw-r--r--drivers/media/dvb/frontends/or51211.c2
-rw-r--r--drivers/media/dvb/frontends/sp8870.c2
-rw-r--r--drivers/media/dvb/frontends/sp887x.c2
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c3
-rw-r--r--drivers/message/i2o/core.h3
-rw-r--r--drivers/message/i2o/i2o_config.c4
-rw-r--r--drivers/mfd/ucb1x00-core.c2
-rw-r--r--drivers/mfd/ucb1x00.h1
-rw-r--r--drivers/net/3c59x.c166
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c5
-rw-r--r--drivers/net/bnx2.c2
-rw-r--r--drivers/net/chelsio/sge.c2
-rw-r--r--drivers/net/e1000/e1000.h10
-rw-r--r--drivers/net/e1000/e1000_ethtool.c141
-rw-r--r--drivers/net/e1000/e1000_hw.c1772
-rw-r--r--drivers/net/e1000/e1000_hw.h398
-rw-r--r--drivers/net/e1000/e1000_main.c385
-rw-r--r--drivers/net/e1000/e1000_osdep.h13
-rw-r--r--drivers/net/e1000/e1000_param.c199
-rw-r--r--drivers/net/forcedeth.c51
-rw-r--r--drivers/net/hamradio/bpqether.c7
-rw-r--r--drivers/net/irda/ali-ircc.c3
-rw-r--r--drivers/net/irda/smsc-ircc2.c2
-rw-r--r--drivers/net/ixgb/ixgb_main.c6
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/myri10ge/myri10ge.c15
-rw-r--r--drivers/net/s2io.c285
-rw-r--r--drivers/net/s2io.h5
-rw-r--r--drivers/net/sk98lin/h/xmac_ii.h2
-rw-r--r--drivers/net/skge.h4
-rw-r--r--drivers/net/sky2.c45
-rw-r--r--drivers/net/sky2.h2
-rw-r--r--drivers/net/smc91x.h18
-rw-r--r--drivers/net/tg3.c2
-rw-r--r--drivers/net/typhoon.c4
-rw-r--r--drivers/net/wan/c101.c26
-rw-r--r--drivers/net/wan/hd6457x.c26
-rw-r--r--drivers/net/wan/hdlc_cisco.c14
-rw-r--r--drivers/net/wan/hdlc_fr.c14
-rw-r--r--drivers/net/wan/hdlc_generic.c65
-rw-r--r--drivers/net/wan/wanxl.c5
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c2
-rw-r--r--drivers/net/wireless/spectrum_cs.c37
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c12
-rw-r--r--drivers/pci/hotplug/Kconfig5
-rw-r--r--drivers/pci/msi.c4
-rw-r--r--drivers/pci/pci.c11
-rw-r--r--drivers/pci/pci.h10
-rw-r--r--drivers/pci/probe.c1
-rw-r--r--drivers/pci/quirks.c108
-rw-r--r--drivers/pcmcia/Kconfig2
-rw-r--r--drivers/s390/block/dasd_devmap.c8
-rw-r--r--drivers/s390/block/dasd_eckd.c20
-rw-r--r--drivers/s390/block/dasd_fba.c4
-rw-r--r--drivers/s390/block/dasd_genhd.c8
-rw-r--r--drivers/s390/block/dasd_ioctl.c2
-rw-r--r--drivers/s390/block/xpram.c63
-rw-r--r--drivers/s390/char/con3215.c2
-rw-r--r--drivers/s390/char/ctrlchar.c2
-rw-r--r--drivers/s390/char/defkeymap.c6
-rw-r--r--drivers/s390/char/fs3270.c12
-rw-r--r--drivers/s390/char/keyboard.c6
-rw-r--r--drivers/s390/char/raw3270.c34
-rw-r--r--drivers/s390/char/raw3270.h2
-rw-r--r--drivers/s390/char/tape_34xx.c6
-rw-r--r--drivers/s390/char/tty3270.c24
-rw-r--r--drivers/s390/char/vmlogrdr.c6
-rw-r--r--drivers/s390/char/vmwatchdog.c2
-rw-r--r--drivers/s390/cio/ccwgroup.c2
-rw-r--r--drivers/s390/cio/chsc.c34
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/cio.h3
-rw-r--r--drivers/s390/cio/cmf.c4
-rw-r--r--drivers/s390/cio/css.c36
-rw-r--r--drivers/s390/cio/css.h4
-rw-r--r--drivers/s390/cio/device.c14
-rw-r--r--drivers/s390/cio/device_fsm.c85
-rw-r--r--drivers/s390/cio/device_pgid.c122
-rw-r--r--drivers/s390/cio/device_status.c7
-rw-r--r--drivers/s390/cio/qdio.c2
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/net/iucv.c2
-rw-r--r--drivers/s390/net/netiucv.c2
-rw-r--r--drivers/s390/net/qeth_main.c20
-rw-r--r--drivers/s390/net/qeth_sys.c4
-rw-r--r--drivers/s390/net/smsgiucv.c14
-rw-r--r--drivers/s390/s390mach.c10
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c2
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c47
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h1
-rw-r--r--drivers/serial/sunsu.c35
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/class/cdc-acm.c49
-rw-r--r--drivers/usb/core/Kconfig3
-rw-r--r--drivers/usb/core/hub.c10
-rw-r--r--drivers/usb/core/inode.c2
-rw-r--r--drivers/usb/gadget/epautoconf.c16
-rw-r--r--drivers/usb/gadget/ether.c8
-rw-r--r--drivers/usb/gadget/file_storage.c2
-rw-r--r--drivers/usb/gadget/rndis.c2
-rw-r--r--drivers/usb/gadget/rndis.h2
-rw-r--r--drivers/usb/gadget/serial.c2
-rw-r--r--drivers/usb/gadget/zero.c2
-rw-r--r--drivers/usb/host/ehci-au1xxx.c23
-rw-r--r--drivers/usb/host/ehci-hcd.c7
-rw-r--r--drivers/usb/host/ohci-au1xxx.c7
-rw-r--r--drivers/usb/host/ohci-ep93xx.c225
-rw-r--r--drivers/usb/host/ohci-hcd.c5
-rw-r--r--drivers/usb/host/ohci-hub.c4
-rw-r--r--drivers/usb/host/pci-quirks.c8
-rw-r--r--drivers/usb/input/hid-core.c4
-rw-r--r--drivers/usb/misc/Kconfig10
-rw-r--r--drivers/usb/misc/Makefile2
-rw-r--r--drivers/usb/misc/cy7c63.c244
-rw-r--r--drivers/usb/misc/cypress_cy7c63.c279
-rw-r--r--drivers/usb/misc/usblcd.c6
-rw-r--r--drivers/usb/mon/mon_text.c7
-rw-r--r--drivers/usb/net/rtl8150.c3
-rw-r--r--drivers/usb/serial/Kconfig11
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/airprime.c2
-rw-r--r--drivers/usb/serial/anydata.c4
-rw-r--r--drivers/usb/serial/ark3116.c2
-rw-r--r--drivers/usb/serial/belkin_sa.c2
-rw-r--r--drivers/usb/serial/bus.c2
-rw-r--r--drivers/usb/serial/console.c3
-rw-r--r--drivers/usb/serial/cp2101.c2
-rw-r--r--drivers/usb/serial/cyberjack.c2
-rw-r--r--drivers/usb/serial/cypress_m8.c2
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/empeg.c2
-rw-r--r--drivers/usb/serial/ezusb.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c108
-rw-r--r--drivers/usb/serial/ftdi_sio.h15
-rw-r--r--drivers/usb/serial/funsoft.c2
-rw-r--r--drivers/usb/serial/garmin_gps.c3
-rw-r--r--drivers/usb/serial/generic.c3
-rw-r--r--drivers/usb/serial/hp4x.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c2
-rw-r--r--drivers/usb/serial/io_ti.c2
-rw-r--r--drivers/usb/serial/ipaq.c25
-rw-r--r--drivers/usb/serial/ipw.c4
-rw-r--r--drivers/usb/serial/ir-usb.c2
-rw-r--r--drivers/usb/serial/keyspan.c2
-rw-r--r--drivers/usb/serial/keyspan_pda.c3
-rw-r--r--drivers/usb/serial/kl5kusb105.c2
-rw-r--r--drivers/usb/serial/kobil_sct.c2
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/navman.c2
-rw-r--r--drivers/usb/serial/omninet.c2
-rw-r--r--drivers/usb/serial/option.c8
-rw-r--r--drivers/usb/serial/pl2303.c4
-rw-r--r--drivers/usb/serial/pl2303.h5
-rw-r--r--drivers/usb/serial/safe_serial.c2
-rw-r--r--drivers/usb/serial/sierra.c75
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c2
-rw-r--r--drivers/usb/serial/usb-serial.c25
-rw-r--r--drivers/usb/serial/usb-serial.h300
-rw-r--r--drivers/usb/serial/visor.c39
-rw-r--r--drivers/usb/serial/whiteheat.c2
-rw-r--r--drivers/usb/storage/scsiglue.c12
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h60
-rw-r--r--drivers/usb/storage/usb.c29
-rw-r--r--drivers/usb/storage/usb.h4
-rw-r--r--drivers/video/68328fb.c1
-rw-r--r--drivers/video/S3triofb.c1
-rw-r--r--drivers/video/amifb.c1
-rw-r--r--drivers/video/arcfb.c1
-rw-r--r--drivers/video/asiliantfb.c1
-rw-r--r--drivers/video/atafb.c1
-rw-r--r--drivers/video/aty/aty128fb.c67
-rw-r--r--drivers/video/aty/atyfb_base.c53
-rw-r--r--drivers/video/aty/radeon_base.c1
-rw-r--r--drivers/video/chipsfb.c4
-rw-r--r--drivers/video/cirrusfb.c1
-rw-r--r--drivers/video/console/dummycon.c2
-rw-r--r--drivers/video/console/fbcon.c1
-rw-r--r--drivers/video/console/mdacon.c1
-rw-r--r--drivers/video/console/newport_con.c1
-rw-r--r--drivers/video/console/promcon.c1
-rw-r--r--drivers/video/console/softcursor.c1
-rw-r--r--drivers/video/console/sticon.c1
-rw-r--r--drivers/video/console/vgacon.c2
-rw-r--r--drivers/video/controlfb.c1
-rw-r--r--drivers/video/cyber2000fb.c1
-rw-r--r--drivers/video/cyberfb.c1
-rw-r--r--drivers/video/dnfb.c1
-rw-r--r--drivers/video/epson1355fb.c1
-rw-r--r--drivers/video/fbcmap.c1
-rw-r--r--drivers/video/fbmem.c2
-rw-r--r--drivers/video/fbmon.c1
-rw-r--r--drivers/video/g364fb.c1
-rw-r--r--drivers/video/geode/gx1fb_core.c1
-rw-r--r--drivers/video/geode/gxfb_core.c1
-rw-r--r--drivers/video/hgafb.c1
-rw-r--r--drivers/video/hitfb.c1
-rw-r--r--drivers/video/hpfb.c1
-rw-r--r--drivers/video/i810/i810_main.c1
-rw-r--r--drivers/video/igafb.c1
-rw-r--r--drivers/video/imacfb.c2
-rw-r--r--drivers/video/imsttfb.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c2
-rw-r--r--drivers/video/intelfb/intelfbhw.c1
-rw-r--r--drivers/video/kyro/fbdev.c1
-rw-r--r--drivers/video/macfb.c1
-rw-r--r--drivers/video/matrox/matroxfb_base.h1
-rw-r--r--drivers/video/maxinefb.c1
-rw-r--r--drivers/video/modedb.c1
-rw-r--r--drivers/video/neofb.c1
-rw-r--r--drivers/video/nvidia/nv_backlight.c32
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nvidia.c12
-rw-r--r--drivers/video/offb.c1
-rw-r--r--drivers/video/platinumfb.c1
-rw-r--r--drivers/video/pm2fb.c1
-rw-r--r--drivers/video/pm3fb.c1
-rw-r--r--drivers/video/pmag-aa-fb.c1
-rw-r--r--drivers/video/pvr2fb.c1
-rw-r--r--drivers/video/q40fb.c1
-rw-r--r--drivers/video/retz3fb.c1
-rw-r--r--drivers/video/riva/fbdev.c45
-rw-r--r--drivers/video/s3c2410fb.c1
-rw-r--r--drivers/video/savage/savagefb_driver.c1
-rw-r--r--drivers/video/sis/sis_main.c6
-rw-r--r--drivers/video/skeletonfb.c1
-rw-r--r--drivers/video/sun3fb.c1
-rw-r--r--drivers/video/tdfxfb.c1
-rw-r--r--drivers/video/tgafb.c1
-rw-r--r--drivers/video/tx3912fb.c1
-rw-r--r--drivers/video/valkyriefb.c1
-rw-r--r--drivers/video/vesafb.c2
-rw-r--r--drivers/video/vfb.c1
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--drivers/video/virgefb.c1
-rw-r--r--drivers/w1/masters/ds2482.c2
-rw-r--r--drivers/w1/w1_io.h36
355 files changed, 5639 insertions, 3143 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index fef7bab12244..56c5ba874623 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -107,7 +107,6 @@ config ACPI_BUTTON
config ACPI_VIDEO
tristate "Video"
depends on X86
- default y
help
This driver implement the ACPI Extensions For Display Adapters
for integrated graphics devices on motherboard, as specified in
@@ -135,8 +134,7 @@ config ACPI_FAN
config ACPI_DOCK
tristate "Dock"
- depends on !ACPI_IBM_DOCK
- default y
+ depends on EXPERIMENTAL
help
This driver adds support for ACPI controlled docking stations
@@ -214,6 +212,7 @@ config ACPI_IBM
config ACPI_IBM_DOCK
bool "Legacy Docking Station Support"
depends on ACPI_IBM
+ depends on ACPI_DOCK=n
default n
---help---
Allows the ibm_acpi driver to handle docking station events.
@@ -357,7 +356,6 @@ config ACPI_SBS
tristate "Smart Battery System (EXPERIMENTAL)"
depends on X86 && I2C
depends on EXPERIMENTAL
- default y
help
This driver adds support for the Smart Battery System.
Depends on I2C (Device Drivers ---> I2C support)
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 24ccf81d135f..96309b9660da 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -72,7 +72,7 @@ struct acpi_ac {
unsigned long state;
};
-static struct file_operations acpi_ac_fops = {
+static const struct file_operations acpi_ac_fops = {
.open = acpi_ac_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 24bf4dca88cc..6e5221707d97 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -557,7 +557,7 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
}
-static struct file_operations acpi_battery_info_ops = {
+static const struct file_operations acpi_battery_info_ops = {
.open = acpi_battery_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
@@ -565,7 +565,7 @@ static struct file_operations acpi_battery_info_ops = {
.owner = THIS_MODULE,
};
-static struct file_operations acpi_battery_state_ops = {
+static const struct file_operations acpi_battery_state_ops = {
.open = acpi_battery_state_open_fs,
.read = seq_read,
.llseek = seq_lseek,
@@ -573,7 +573,7 @@ static struct file_operations acpi_battery_state_ops = {
.owner = THIS_MODULE,
};
-static struct file_operations acpi_battery_alarm_ops = {
+static const struct file_operations acpi_battery_alarm_ops = {
.open = acpi_battery_alarm_open_fs,
.read = seq_read,
.write = acpi_battery_write_alarm,
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ea5a0496a4fd..b2977695e120 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -192,8 +192,8 @@ int acpi_bus_set_power(acpi_handle handle, int state)
/* Make sure this is a valid target state */
if (!device->flags.power_manageable) {
- printk(KERN_DEBUG "Device `[%s]' is not power manageable",
- device->kobj.name);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable",
+ device->kobj.name));
return -ENODEV;
}
/*
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index fd1ba05eab68..5ef885e82c78 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -87,14 +87,14 @@ struct acpi_button {
unsigned long pushed;
};
-static struct file_operations acpi_button_info_fops = {
+static const struct file_operations acpi_button_info_fops = {
.open = acpi_button_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
-static struct file_operations acpi_button_state_fops = {
+static const struct file_operations acpi_button_state_fops = {
.open = acpi_button_state_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index 574a75a166c5..a01ce6700bfe 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -39,50 +39,43 @@ ACPI_MODULE_NAME("cm_sbs")
static struct proc_dir_entry *acpi_ac_dir;
static struct proc_dir_entry *acpi_battery_dir;
-static struct semaphore cm_sbs_sem;
+static DEFINE_MUTEX(cm_sbs_mutex);
-static int lock_ac_dir_cnt = 0;
-static int lock_battery_dir_cnt = 0;
+static int lock_ac_dir_cnt;
+static int lock_battery_dir_cnt;
struct proc_dir_entry *acpi_lock_ac_dir(void)
{
-
- down(&cm_sbs_sem);
- if (!acpi_ac_dir) {
+ mutex_lock(&cm_sbs_mutex);
+ if (!acpi_ac_dir)
acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
- }
if (acpi_ac_dir) {
lock_ac_dir_cnt++;
} else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Cannot create %s\n", ACPI_AC_CLASS));
}
- up(&cm_sbs_sem);
+ mutex_unlock(&cm_sbs_mutex);
return acpi_ac_dir;
}
-
EXPORT_SYMBOL(acpi_lock_ac_dir);
void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
{
-
- down(&cm_sbs_sem);
- if (acpi_ac_dir_param) {
+ mutex_lock(&cm_sbs_mutex);
+ if (acpi_ac_dir_param)
lock_ac_dir_cnt--;
- }
if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
acpi_ac_dir = 0;
}
- up(&cm_sbs_sem);
+ mutex_unlock(&cm_sbs_mutex);
}
-
EXPORT_SYMBOL(acpi_unlock_ac_dir);
struct proc_dir_entry *acpi_lock_battery_dir(void)
{
-
- down(&cm_sbs_sem);
+ mutex_lock(&cm_sbs_mutex);
if (!acpi_battery_dir) {
acpi_battery_dir =
proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
@@ -93,39 +86,28 @@ struct proc_dir_entry *acpi_lock_battery_dir(void)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Cannot create %s\n", ACPI_BATTERY_CLASS));
}
- up(&cm_sbs_sem);
+ mutex_unlock(&cm_sbs_mutex);
return acpi_battery_dir;
}
-
EXPORT_SYMBOL(acpi_lock_battery_dir);
void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
{
-
- down(&cm_sbs_sem);
- if (acpi_battery_dir_param) {
+ mutex_lock(&cm_sbs_mutex);
+ if (acpi_battery_dir_param)
lock_battery_dir_cnt--;
- }
if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
&& acpi_battery_dir) {
remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
acpi_battery_dir = 0;
}
- up(&cm_sbs_sem);
+ mutex_unlock(&cm_sbs_mutex);
return;
}
-
EXPORT_SYMBOL(acpi_unlock_battery_dir);
static int __init acpi_cm_sbs_init(void)
{
-
- if (acpi_disabled)
- return 0;
-
- init_MUTEX(&cm_sbs_sem);
-
return 0;
}
-
subsys_initcall(acpi_cm_sbs_init);
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index daf51b5b5875..1888c055d10f 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -116,16 +116,6 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
case ACPI_TYPE_METHOD:
- /*
- * Set the execution data width (32 or 64) based upon the
- * revision number of the parent ACPI table.
- * TBD: This is really for possible future support of integer width
- * on a per-table basis. Currently, we just use a global for the width.
- */
- if (info->table_desc->pointer->revision == 1) {
- node->flags |= ANOBJ_DATA_WIDTH_32;
- }
-
info->method_count++;
break;
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index a39a33f4847a..cf888add3191 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -134,7 +134,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc)
union acpi_operand_object *mutex_desc;
acpi_status status;
- ACPI_FUNCTION_NAME(ds_create_method_mutex);
+ ACPI_FUNCTION_TRACE(ds_create_method_mutex);
/* Create the new mutex object */
@@ -493,7 +493,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
- (char *)&walk_state->method_node->name,
+ acpi_ut_get_node_name(walk_state->method_node),
walk_state->method_call_op, return_desc));
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
@@ -610,6 +610,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
acpi_os_release_mutex(method_desc->method.mutex->mutex.
os_mutex);
+ method_desc->method.mutex->mutex.owner_thread = NULL;
}
}
@@ -620,27 +621,11 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
*/
method_node = walk_state->method_node;
- /* Lock namespace for possible update */
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_VOID;
- }
-
- /*
- * Delete any namespace entries created immediately underneath
- * the method
- */
- if (method_node && method_node->child) {
- acpi_ns_delete_namespace_subtree(method_node);
- }
-
/*
- * Delete any namespace entries created anywhere else within
+ * Delete any namespace objects created anywhere within
* the namespace by the execution of this method
*/
acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id);
- status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}
/* Decrement the thread count on the method */
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index b1ded62d0df1..d7a616c3104e 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -313,10 +313,10 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
/*
- * Most operators with arguments.
+ * Most operators with arguments (except create_xxx_field operators)
* Start a new result/operand state
*/
- if (walk_state->opcode != AML_CREATE_FIELD_OP) {
+ if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) {
status = acpi_ds_result_stack_push(walk_state);
}
break;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 510a94524298..1c0a39d8b04e 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -627,6 +627,7 @@ static int dock_add(acpi_handle handle)
INIT_LIST_HEAD(&dock_station->hotplug_devices);
spin_lock_init(&dock_station->dd_lock);
spin_lock_init(&dock_station->hp_lock);
+ ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
/* Find dependent devices */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 8c5d7df7d343..e5d796362854 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -929,7 +929,7 @@ static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_ec_read_info, PDE(inode)->data);
}
-static struct file_operations acpi_ec_info_ops = {
+static const struct file_operations acpi_ec_info_ops = {
.open = acpi_ec_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index a901b23e95e7..959a893c8d1f 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -99,7 +99,7 @@ static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
return 0;
}
-static struct file_operations acpi_system_event_ops = {
+static const struct file_operations acpi_system_event_ops = {
.open = acpi_system_open_event,
.read = acpi_system_read_event,
.release = acpi_system_close_event,
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 094a17e4c86d..21caae04fe85 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -528,34 +528,40 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
}
}
- /* Call the setup handler with the deactivate notification */
+ /*
+ * If the region has been activated, call the setup handler
+ * with the deactivate notification
+ */
+ if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
+ region_setup = handler_obj->address_space.setup;
+ status =
+ region_setup(region_obj,
+ ACPI_REGION_DEACTIVATE,
+ handler_obj->address_space.
+ context, region_context);
- region_setup = handler_obj->address_space.setup;
- status =
- region_setup(region_obj, ACPI_REGION_DEACTIVATE,
- handler_obj->address_space.context,
- region_context);
+ /* Init routine may fail, Just ignore errors */
- /* Init routine may fail, Just ignore errors */
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "from region handler - deactivate, [%s]",
+ acpi_ut_get_region_name
+ (region_obj->region.
+ space_id)));
+ }
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "from region init, [%s]",
- acpi_ut_get_region_name
- (region_obj->region.space_id)));
+ region_obj->region.flags &=
+ ~(AOPOBJ_SETUP_COMPLETE);
}
- region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
-
/*
* Remove handler reference in the region
*
- * NOTE: this doesn't mean that the region goes away
- * The region is just inaccessible as indicated to
- * the _REG method
+ * NOTE: this doesn't mean that the region goes away, the region
+ * is just inaccessible as indicated to the _REG method
*
- * If the region is on the handler's list
- * this better be the region's handler
+ * If the region is on the handler's list, this must be the
+ * region's handler
*/
region_obj->region.handler = NULL;
acpi_ut_remove_reference(handler_obj);
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 4f948df17ab9..923fd2b46955 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -428,7 +428,7 @@ acpi_remove_notify_handler(acpi_handle device,
node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
- goto unlock;
+ goto unlock_and_exit;
}
/* Root Object */
@@ -442,7 +442,7 @@ acpi_remove_notify_handler(acpi_handle device,
((handler_type & ACPI_DEVICE_NOTIFY) &&
!acpi_gbl_device_notify.handler)) {
status = AE_NOT_EXIST;
- goto unlock;
+ goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
@@ -474,7 +474,7 @@ acpi_remove_notify_handler(acpi_handle device,
if (!acpi_ev_is_notify_object(node)) {
status = AE_TYPE;
- goto unlock;
+ goto unlock_and_exit;
}
/* Check for an existing internal object */
@@ -482,17 +482,21 @@ acpi_remove_notify_handler(acpi_handle device,
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
- goto unlock;
+ goto unlock_and_exit;
}
/* Object exists - make sure there's an existing handler */
if (handler_type & ACPI_SYSTEM_NOTIFY) {
notify_obj = obj_desc->common_notify.system_notify;
- if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
+ if (!notify_obj) {
+ status = AE_NOT_EXIST;
+ goto unlock_and_exit;
+ }
+
+ if (notify_obj->notify.handler != handler) {
status = AE_BAD_PARAMETER;
- goto unlock;
+ goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
@@ -510,10 +514,14 @@ acpi_remove_notify_handler(acpi_handle device,
if (handler_type & ACPI_DEVICE_NOTIFY) {
notify_obj = obj_desc->common_notify.device_notify;
- if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
+ if (!notify_obj) {
+ status = AE_NOT_EXIST;
+ goto unlock_and_exit;
+ }
+
+ if (notify_obj->notify.handler != handler) {
status = AE_BAD_PARAMETER;
- goto unlock;
+ goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
@@ -530,9 +538,9 @@ acpi_remove_notify_handler(acpi_handle device,
}
}
-unlock:
+ unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-exit:
+ exit:
if (ACPI_FAILURE(status))
ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler"));
return_ACPI_STATUS(status);
@@ -586,7 +594,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
- goto unlock;
+ goto unlock_and_exit;
}
/* Make sure that there isn't a handler there already */
@@ -594,7 +602,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_HANDLER) {
status = AE_ALREADY_EXISTS;
- goto unlock;
+ goto unlock_and_exit;
}
/* Allocate and init handler object */
@@ -602,7 +610,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
if (!handler) {
status = AE_NO_MEMORY;
- goto unlock;
+ goto unlock_and_exit;
}
handler->address = address;
@@ -613,7 +621,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
- goto unlock;
+ goto unlock_and_exit;
}
/* Install the handler */
@@ -628,9 +636,9 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-unlock:
+ unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
-exit:
+ exit:
if (ACPI_FAILURE(status))
ACPI_EXCEPTION((AE_INFO, status,
"Installing notify handler failed"));
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index e8b86a0baad0..83b12a9afa32 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -155,7 +155,11 @@ acpi_remove_address_space_handler(acpi_handle device,
/* Convert and validate the device handle */
node = acpi_ns_map_handle_to_node(device);
- if (!node) {
+ if (!node ||
+ ((node->type != ACPI_TYPE_DEVICE) &&
+ (node->type != ACPI_TYPE_PROCESSOR) &&
+ (node->type != ACPI_TYPE_THERMAL) &&
+ (node != acpi_gbl_root_node))) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
@@ -178,6 +182,13 @@ acpi_remove_address_space_handler(acpi_handle device,
if (handler_obj->address_space.space_id == space_id) {
+ /* Handler must be the same as the installed handler */
+
+ if (handler_obj->address_space.handler != handler) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
/* Matched space_id, first dereference this in the Regions */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 83fed079a276..c8341fa5fe01 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -502,7 +502,6 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
* (Offset contains the table_id)
*/
acpi_ns_delete_namespace_by_owner(table_info->owner_id);
- acpi_ut_release_owner_id(&table_info->owner_id);
/* Delete the table itself */
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index b732e399b1ef..544e81a6a438 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -170,6 +170,9 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_NO_MEMORY);
}
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(result)));
+
/* Save the Result */
return_desc->integer.value = result;
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index d8ac2877cf05..3a39c2e8e104 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -267,9 +267,9 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
&& (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) {
ACPI_ERROR((AE_INFO,
"Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
- walk_state->thread->thread_id,
+ (u32) walk_state->thread->thread_id,
acpi_ut_get_node_name(obj_desc->mutex.node),
- obj_desc->mutex.owner_thread->thread_id));
+ (u32) obj_desc->mutex.owner_thread->thread_id));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index 6b5d1e6ce94b..28aef3e69ecc 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -60,7 +60,7 @@ ACPI_MODULE_NAME("exsystem")
*
* DESCRIPTION: Implements a semaphore wait with a check to see if the
* semaphore is available immediately. If it is not, the
- * interpreter is released.
+ * interpreter is released before waiting.
*
******************************************************************************/
acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
@@ -110,9 +110,9 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
*
* RETURN: Status
*
- * DESCRIPTION: Implements a semaphore wait with a check to see if the
- * semaphore is available immediately. If it is not, the
- * interpreter is released.
+ * DESCRIPTION: Implements a mutex wait with a check to see if the
+ * mutex is available immediately. If it is not, the
+ * interpreter is released before waiting.
*
******************************************************************************/
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index daed2460924d..045c89477e59 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -120,7 +120,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
return count;
}
-static struct file_operations acpi_fan_state_ops = {
+static const struct file_operations acpi_fan_state_ops = {
.open = acpi_fan_state_open_fs,
.read = seq_read,
.write = acpi_fan_write_state,
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index fd81a0f5222f..32c9d88fd196 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -184,7 +184,7 @@ static union acpi_hotkey *get_hotkey_by_event(struct
*hotkey_list, int event);
/* event based config */
-static struct file_operations hotkey_config_fops = {
+static const struct file_operations hotkey_config_fops = {
.open = hotkey_open_config,
.read = seq_read,
.write = hotkey_write_config,
@@ -193,7 +193,7 @@ static struct file_operations hotkey_config_fops = {
};
/* polling based config */
-static struct file_operations hotkey_poll_config_fops = {
+static const struct file_operations hotkey_poll_config_fops = {
.open = hotkey_poll_open_config,
.read = seq_read,
.write = hotkey_write_config,
@@ -202,7 +202,7 @@ static struct file_operations hotkey_poll_config_fops = {
};
/* hotkey driver info */
-static struct file_operations hotkey_info_fops = {
+static const struct file_operations hotkey_info_fops = {
.open = hotkey_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
@@ -210,7 +210,7 @@ static struct file_operations hotkey_info_fops = {
};
/* action */
-static struct file_operations hotkey_action_fops = {
+static const struct file_operations hotkey_action_fops = {
.open = hotkey_action_open_fs,
.read = seq_read,
.write = hotkey_execute_aml_method,
@@ -219,7 +219,7 @@ static struct file_operations hotkey_action_fops = {
};
/* polling results */
-static struct file_operations hotkey_polling_fops = {
+static const struct file_operations hotkey_polling_fops = {
.open = hotkey_polling_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index dc3f0739a46b..55b407aae266 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -386,14 +386,17 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
* specific ID. Used to delete entire ACPI tables. All
* reference counts are updated.
*
+ * MUTEX: Locks namespace during deletion walk.
+ *
******************************************************************************/
void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
{
struct acpi_namespace_node *child_node;
struct acpi_namespace_node *deletion_node;
- u32 level;
struct acpi_namespace_node *parent_node;
+ u32 level;
+ acpi_status status;
ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id);
@@ -401,6 +404,13 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
return_VOID;
}
+ /* Lock namespace for possible update */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_VOID;
+ }
+
deletion_node = NULL;
parent_node = acpi_gbl_root_node;
child_node = NULL;
@@ -469,5 +479,6 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
}
}
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_VOID;
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index eedb05c6dc7b..b7d1514cd199 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -36,7 +36,6 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
-#include <linux/kthread.h>
#include <acpi/acpi.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
@@ -136,16 +135,6 @@ void acpi_os_vprintf(const char *fmt, va_list args)
#endif
}
-
-extern int acpi_in_resume;
-void *acpi_os_allocate(acpi_size size)
-{
- if (acpi_in_resume)
- return kmalloc(size, GFP_ATOMIC);
- else
- return kmalloc(size, GFP_KERNEL);
-}
-
acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
{
if (efi_enabled) {
@@ -593,16 +582,6 @@ static void acpi_os_execute_deferred(void *context)
return;
}
-static int acpi_os_execute_thread(void *context)
-{
- struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
- if (dpc) {
- dpc->function(dpc->context);
- kfree(dpc);
- }
- do_exit(0);
-}
-
/*******************************************************************************
*
* FUNCTION: acpi_os_execute
@@ -624,10 +603,16 @@ acpi_status acpi_os_execute(acpi_execute_type type,
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct work_struct *task;
- struct task_struct *p;
+
+ ACPI_FUNCTION_TRACE("os_queue_for_execution");
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Scheduling function [%p(%p)] for deferred execution.\n",
+ function, context));
if (!function)
- return AE_BAD_PARAMETER;
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+
/*
* Allocate/initialize DPC structure. Note that this memory will be
* freed by the callee. The kernel handles the tq_struct list in a
@@ -638,34 +623,27 @@ acpi_status acpi_os_execute(acpi_execute_type type,
* We can save time and code by allocating the DPC and tq_structs
* from the same memory.
*/
- if (type == OSL_NOTIFY_HANDLER) {
- dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL);
- } else {
- dpc = kmalloc(sizeof(struct acpi_os_dpc) +
- sizeof(struct work_struct), GFP_ATOMIC);
- }
+
+ dpc =
+ kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
+ GFP_ATOMIC);
if (!dpc)
- return AE_NO_MEMORY;
+ return_ACPI_STATUS(AE_NO_MEMORY);
+
dpc->function = function;
dpc->context = context;
- if (type == OSL_NOTIFY_HANDLER) {
- p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify");
- if (!IS_ERR(p)) {
- wake_up_process(p);
- } else {
- status = AE_NO_MEMORY;
- kfree(dpc);
- }
- } else {
- task = (void *)(dpc + 1);
- INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
- if (!queue_work(kacpid_wq, task)) {
- status = AE_ERROR;
- kfree(dpc);
- }
+ task = (void *)(dpc + 1);
+ INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
+
+ if (!queue_work(kacpid_wq, task)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Call to queue_work() failed.\n"));
+ kfree(dpc);
+ status = AE_ERROR;
}
- return status;
+
+ return_ACPI_STATUS(status);
}
EXPORT_SYMBOL(acpi_os_execute);
@@ -1115,26 +1093,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
return (AE_OK);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_os_acquire_object
- *
- * PARAMETERS: Cache - Handle to cache object
- * ReturnObject - Where the object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Return a zero-filled object.
- *
- ******************************************************************************/
-
-void *acpi_os_acquire_object(acpi_cache_t * cache)
-{
- void *object = kmem_cache_zalloc(cache, GFP_KERNEL);
- WARN_ON(!object);
- return object;
-}
-
/******************************************************************************
*
* FUNCTION: acpi_os_validate_interface
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index 182474ae8ce9..d405387b7414 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -139,12 +139,10 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
/* The generic op (default) is by far the most common (16 to 1) */
op = acpi_os_acquire_object(acpi_gbl_ps_node_cache);
- memset(op, 0, sizeof(struct acpi_parse_obj_common));
} else {
/* Extended parseop */
op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache);
- memset(op, 0, sizeof(struct acpi_parse_obj_named));
}
/* Initialize the Op */
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 8197c0e40769..7f3e7e77e794 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -780,11 +780,6 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link)
return 0;
}
-/*
- * FIXME: this is a workaround to avoid nasty warning. It will be removed
- * after every device calls pci_disable_device in .resume.
- */
-int acpi_in_resume;
static int irqrouter_resume(struct sys_device *dev)
{
struct list_head *node = NULL;
@@ -794,7 +789,6 @@ static int irqrouter_resume(struct sys_device *dev)
/* Make sure SCI is enabled again (Apple firmware bug?) */
acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1, ACPI_MTX_DO_NOT_LOCK);
- acpi_in_resume = 1;
list_for_each(node, &acpi_link.entries) {
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
@@ -803,7 +797,6 @@ static int irqrouter_resume(struct sys_device *dev)
}
acpi_pci_link_resume(link);
}
- acpi_in_resume = 0;
return 0;
}
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 5d3447f4582c..fec225d1b6b7 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -80,7 +80,7 @@ struct acpi_power_resource {
static struct list_head acpi_power_resource_list;
-static struct file_operations acpi_power_fops = {
+static const struct file_operations acpi_power_fops = {
.open = acpi_power_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 52674323b14d..b13d64415b7a 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -102,7 +102,7 @@ static struct acpi_driver acpi_processor_driver = {
#define INSTALL_NOTIFY_HANDLER 1
#define UNINSTALL_NOTIFY_HANDLER 2
-static struct file_operations acpi_processor_info_fops = {
+static const struct file_operations acpi_processor_info_fops = {
.open = acpi_processor_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 8e9c26aae8fe..71066066d626 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1070,7 +1070,7 @@ static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
PDE(inode)->data);
}
-static struct file_operations acpi_processor_power_fops = {
+static const struct file_operations acpi_processor_power_fops = {
.open = acpi_processor_power_open_fs,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 4696a85a98b9..34962578039d 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -434,7 +434,7 @@ acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
PDE(inode)->data);
}
-static struct file_operations acpi_system_wakeup_device_fops = {
+static const struct file_operations acpi_system_wakeup_device_fops = {
.open = acpi_system_wakeup_device_open_fs,
.read = seq_read,
.write = acpi_system_write_wakeup_device,
@@ -443,7 +443,7 @@ static struct file_operations acpi_system_wakeup_device_fops = {
};
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
-static struct file_operations acpi_system_sleep_fops = {
+static const struct file_operations acpi_system_sleep_fops = {
.open = acpi_system_sleep_open_fs,
.read = seq_read,
.write = acpi_system_write_sleep,
@@ -452,7 +452,7 @@ static struct file_operations acpi_system_sleep_fops = {
};
#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
-static struct file_operations acpi_system_alarm_fops = {
+static const struct file_operations acpi_system_alarm_fops = {
.open = acpi_system_alarm_open_fs,
.read = seq_read,
.write = acpi_system_write_alarm,
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index c3bb7faad75e..d86dcb3c2366 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -57,7 +57,7 @@ static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_system_read_info, PDE(inode)->data);
}
-static struct file_operations acpi_system_info_ops = {
+static const struct file_operations acpi_system_info_ops = {
.open = acpi_system_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
@@ -67,7 +67,7 @@ static struct file_operations acpi_system_info_ops = {
static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
loff_t *);
-static struct file_operations acpi_system_dsdt_ops = {
+static const struct file_operations acpi_system_dsdt_ops = {
.read = acpi_system_read_dsdt,
};
@@ -94,7 +94,7 @@ acpi_system_read_dsdt(struct file *file,
static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t,
loff_t *);
-static struct file_operations acpi_system_fadt_ops = {
+static const struct file_operations acpi_system_fadt_ops = {
.read = acpi_system_read_fadt,
};
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 99eacceff563..7856db759af0 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -320,6 +320,16 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
ACPI_FUNCTION_TRACE(tb_get_this_table);
+ /* Validate minimum length */
+
+ if (header->length < sizeof(struct acpi_table_header)) {
+ ACPI_ERROR((AE_INFO,
+ "Table length (%X) is smaller than minimum (%X)",
+ header->length, sizeof(struct acpi_table_header)));
+
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
+ }
+
/*
* Flags contains the current processor mode (Virtual or Physical
* addressing) The pointer_type is either Logical or Physical
@@ -356,7 +366,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
*/
status = acpi_os_map_memory(address->pointer.physical,
(acpi_size) header->length,
- (void *)&full_table);
+ ACPI_CAST_PTR(void, &full_table));
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X",
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 7ca2df75bb11..1668a232fb67 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -256,7 +256,7 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
status = acpi_ut_allocate_owner_id(&table_desc->owner_id);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto error_exit1;
}
/* Install the table into the global data structure */
@@ -274,8 +274,8 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
* at this location, so return an error.
*/
if (list_head->next) {
- ACPI_FREE(table_desc);
- return_ACPI_STATUS(AE_ALREADY_EXISTS);
+ status = AE_ALREADY_EXISTS;
+ goto error_exit2;
}
table_desc->next = list_head->next;
@@ -335,6 +335,17 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
table_info->owner_id = table_desc->owner_id;
table_info->installed_desc = table_desc;
return_ACPI_STATUS(AE_OK);
+
+ /* Error exit with cleanup */
+
+ error_exit2:
+
+ acpi_ut_release_owner_id(&table_desc->owner_id);
+
+ error_exit1:
+
+ ACPI_FREE(table_desc);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -525,6 +536,10 @@ struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc
acpi_tb_delete_single_table(table_desc);
+ /* Free the owner ID associated with this table */
+
+ acpi_ut_release_owner_id(&table_desc->owner_id);
+
/* Free the table descriptor */
next_desc = table_desc->next;
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index abcb08c2592a..0ad3dbb9ebca 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -183,6 +183,17 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
ACPI_FUNCTION_ENTRY();
+ /* Validate minimum length */
+
+ if (table_ptr->length < sizeof(struct acpi_table_header)) {
+ ACPI_ERROR((AE_INFO,
+ "RSDT/XSDT length (%X) is smaller than minimum (%X)",
+ table_ptr->length,
+ sizeof(struct acpi_table_header)));
+
+ return (AE_INVALID_TABLE_LENGTH);
+ }
+
/* Search for appropriate signature, RSDT or XSDT */
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
@@ -210,7 +221,7 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
ACPI_ERROR((AE_INFO, "Looking for XSDT"));
}
- ACPI_DUMP_BUFFER((char *)table_ptr, 48);
+ ACPI_DUMP_BUFFER(ACPI_CAST_PTR(char, table_ptr), 48);
return (AE_BAD_SIGNATURE);
}
@@ -258,7 +269,7 @@ acpi_status acpi_tb_get_table_rsdt(void)
status = acpi_tb_validate_rsdt(table_info.pointer);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto error_cleanup;
}
/* Get the number of tables defined in the RSDT or XSDT */
@@ -270,14 +281,14 @@ acpi_status acpi_tb_get_table_rsdt(void)
status = acpi_tb_convert_to_xsdt(&table_info);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto error_cleanup;
}
/* Save the table pointers and allocation info */
status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto error_cleanup;
}
acpi_gbl_XSDT =
@@ -285,4 +296,12 @@ acpi_status acpi_tb_get_table_rsdt(void)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
return_ACPI_STATUS(status);
+
+ error_cleanup:
+
+ /* Free table allocated by acpi_tb_get_table */
+
+ acpi_tb_delete_single_table(&table_info);
+
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 4e91f2984815..7767987be15a 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -134,8 +134,8 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables)
* RETURN: Status
*
* DESCRIPTION: This function is called to load a table from the caller's
- * buffer. The buffer must contain an entire ACPI Table including
- * a valid header. The header fields will be verified, and if it
+ * buffer. The buffer must contain an entire ACPI Table including
+ * a valid header. The header fields will be verified, and if it
* is determined that the table is invalid, the call will fail.
*
******************************************************************************/
@@ -245,15 +245,18 @@ acpi_status acpi_unload_table(acpi_table_type table_type)
/* Find all tables of the requested type */
table_desc = acpi_gbl_table_lists[table_type].next;
+ if (!table_desc) {
+ return_ACPI_STATUS(AE_NOT_EXIST);
+ }
+
while (table_desc) {
/*
- * Delete all namespace entries owned by this table. Note that these
- * entries can appear anywhere in the namespace by virtue of the AML
- * "Scope" operator. Thus, we need to track ownership by an ID, not
+ * Delete all namespace objects owned by this table. Note that these
+ * objects can appear anywhere in the namespace by virtue of the AML
+ * "Scope" operator. Thus, we need to track ownership by an ID, not
* simply a position within the hierarchy
*/
acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
- acpi_ut_release_owner_id(&table_desc->owner_id);
table_desc = table_desc->next;
}
@@ -275,12 +278,12 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table)
* see acpi_gbl_acpi_table_flag
* out_table_header - pointer to the struct acpi_table_header if successful
*
- * DESCRIPTION: This function is called to get an ACPI table header. The caller
+ * DESCRIPTION: This function is called to get an ACPI table header. The caller
* supplies an pointer to a data area sufficient to contain an ACPI
* struct acpi_table_header structure.
*
* The header contains a length field that can be used to determine
- * the size of the buffer needed to contain the entire table. This
+ * the size of the buffer needed to contain the entire table. This
* function is not valid for the RSD PTR table since it does not
* have a standard header and is fixed length.
*
@@ -322,7 +325,8 @@ acpi_get_table_header(acpi_table_type table_type,
/* Copy the header to the caller's buffer */
- ACPI_MEMCPY((void *)out_table_header, (void *)tbl_ptr,
+ ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header),
+ ACPI_CAST_PTR(void, tbl_ptr),
sizeof(struct acpi_table_header));
return_ACPI_STATUS(status);
@@ -344,10 +348,10 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_header)
*
* RETURN: Status
*
- * DESCRIPTION: This function is called to get an ACPI table. The caller
+ * DESCRIPTION: This function is called to get an ACPI table. The caller
* supplies an out_buffer large enough to contain the entire ACPI
- * table. The caller should call the acpi_get_table_header function
- * first to determine the buffer size needed. Upon completion
+ * table. The caller should call the acpi_get_table_header function
+ * first to determine the buffer size needed. Upon completion
* the out_buffer->Length field will indicate the number of bytes
* copied into the out_buffer->buf_ptr buffer. This table will be
* a complete table including the header.
@@ -417,7 +421,9 @@ acpi_get_table(acpi_table_type table_type,
/* Copy the table to the buffer */
- ACPI_MEMCPY((void *)ret_buffer->pointer, (void *)tbl_ptr, table_length);
+ ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer),
+ ACPI_CAST_PTR(void, tbl_ptr), table_length);
+
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 503c0b99db12..5753d06b7860 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -176,21 +176,21 @@ struct acpi_thermal {
struct timer_list timer;
};
-static struct file_operations acpi_thermal_state_fops = {
+static const struct file_operations acpi_thermal_state_fops = {
.open = acpi_thermal_state_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
-static struct file_operations acpi_thermal_temp_fops = {
+static const struct file_operations acpi_thermal_temp_fops = {
.open = acpi_thermal_temp_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
-static struct file_operations acpi_thermal_trip_fops = {
+static const struct file_operations acpi_thermal_trip_fops = {
.open = acpi_thermal_trip_open_fs,
.read = seq_read,
.write = acpi_thermal_write_trip_points,
@@ -198,7 +198,7 @@ static struct file_operations acpi_thermal_trip_fops = {
.release = single_release,
};
-static struct file_operations acpi_thermal_cooling_fops = {
+static const struct file_operations acpi_thermal_cooling_fops = {
.open = acpi_thermal_cooling_open_fs,
.read = seq_read,
.write = acpi_thermal_write_cooling_mode,
@@ -206,7 +206,7 @@ static struct file_operations acpi_thermal_cooling_fops = {
.release = single_release,
};
-static struct file_operations acpi_thermal_polling_fops = {
+static const struct file_operations acpi_thermal_polling_fops = {
.open = acpi_thermal_polling_open_fs,
.read = seq_read,
.write = acpi_thermal_write_polling,
@@ -1359,13 +1359,28 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
static int acpi_thermal_resume(struct acpi_device *device, int state)
{
struct acpi_thermal *tz = NULL;
+ int i;
if (!device || !acpi_driver_data(device))
return -EINVAL;
tz = (struct acpi_thermal *)acpi_driver_data(device);
- acpi_thermal_check(tz);
+ acpi_thermal_get_temperature(tz);
+
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+ if (tz->trips.active[i].flags.valid) {
+ tz->temperature = tz->trips.active[i].temperature;
+ tz->trips.active[i].flags.enabled = 0;
+
+ acpi_thermal_active(tz);
+
+ tz->state.active |= tz->trips.active[i].flags.enabled;
+ tz->state.active_index = i;
+ }
+ }
+
+ acpi_thermal_check(tz);
return AE_OK;
}
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 5cff17dc78b3..f6cbc0b1bfd0 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -285,6 +285,7 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
return (status);
}
+#ifdef NOT_USED_BY_LINUX
/*******************************************************************************
*
* FUNCTION: acpi_ut_allocate
@@ -360,3 +361,4 @@ void *acpi_ut_allocate_zeroed(acpi_size size,
return (allocation);
}
+#endif
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index 5ec1cfcc611d..bb1eaf9aa653 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -47,7 +47,7 @@
ACPI_MODULE_NAME("utdebug")
#ifdef ACPI_DEBUG_OUTPUT
-static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF;
+static acpi_thread_id acpi_gbl_prev_thread_id;
static char *acpi_gbl_fn_entry_str = "----Entry";
static char *acpi_gbl_fn_exit_str = "----Exit-";
@@ -181,7 +181,7 @@ acpi_ut_debug_print(u32 requested_debug_level,
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf
("\n**** Context Switch from TID %X to TID %X ****\n\n",
- acpi_gbl_prev_thread_id, thread_id);
+ (u32) acpi_gbl_prev_thread_id, (u32) thread_id);
}
acpi_gbl_prev_thread_id = thread_id;
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 38ebe1c54330..9d3f1149ba21 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -447,11 +447,16 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
*/
switch (ACPI_GET_OBJECT_TYPE(object)) {
case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_POWER:
+ case ACPI_TYPE_THERMAL:
- acpi_ut_update_ref_count(object->device.system_notify,
- action);
- acpi_ut_update_ref_count(object->device.device_notify,
- action);
+ /* Update the notify objects for these types (if present) */
+
+ acpi_ut_update_ref_count(object->common_notify.
+ system_notify, action);
+ acpi_ut_update_ref_count(object->common_notify.
+ device_notify, action);
break;
case ACPI_TYPE_PACKAGE:
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 33268310c738..6d8a8211be90 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -65,7 +65,7 @@ ACPI_MODULE_NAME("utmisc")
u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
{
- /* Ignore tables that contain AML */
+ /* These are the only tables that contain executable AML */
if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) ||
ACPI_COMPARE_NAME(table->signature, PSDT_SIG) ||
@@ -419,10 +419,15 @@ void acpi_ut_set_integer_width(u8 revision)
{
if (revision <= 1) {
+
+ /* 32-bit case */
+
acpi_gbl_integer_bit_width = 32;
acpi_gbl_integer_nybble_width = 8;
acpi_gbl_integer_byte_width = 4;
} else {
+ /* 64-bit case (ACPI 2.0+) */
+
acpi_gbl_integer_bit_width = 64;
acpi_gbl_integer_nybble_width = 16;
acpi_gbl_integer_byte_width = 8;
@@ -502,6 +507,7 @@ acpi_ut_display_init_pathname(u8 type,
* FUNCTION: acpi_ut_valid_acpi_char
*
* PARAMETERS: Char - The character to be examined
+ * Position - Byte position (0-3)
*
* RETURN: TRUE if the character is valid, FALSE otherwise
*
@@ -609,7 +615,9 @@ acpi_name acpi_ut_repair_name(acpi_name name)
*
* RETURN: Status and Converted value
*
- * DESCRIPTION: Convert a string into an unsigned value.
+ * DESCRIPTION: Convert a string into an unsigned value. Performs either a
+ * 32-bit or 64-bit conversion, depending on the current mode
+ * of the interpreter.
* NOTE: Does not support Octal strings, not needed.
*
******************************************************************************/
@@ -627,7 +635,7 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
u8 sign_of0x = 0;
u8 term = 0;
- ACPI_FUNCTION_TRACE(ut_stroul64);
+ ACPI_FUNCTION_TRACE_STR(ut_stroul64, string);
switch (base) {
case ACPI_ANY_BASE:
@@ -675,11 +683,13 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
}
}
+ /*
+ * Perform a 32-bit or 64-bit conversion, depending upon the current
+ * execution mode of the interpreter
+ */
dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
- /* At least one character in the string here */
-
- /* Main loop: convert the string to a 64-bit integer */
+ /* Main loop: convert the string to a 32- or 64-bit integer */
while (*string) {
if (ACPI_IS_DIGIT(*string)) {
@@ -754,6 +764,9 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
all_done:
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(return_value)));
+
*ret_integer = return_value;
return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index dfc8f30ca892..c39062a047cd 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -244,14 +244,14 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %X attempting to acquire Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name(mutex_id)));
+ (u32) this_thread_id, acpi_ut_get_mutex_name(mutex_id)));
status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
ACPI_WAIT_FOREVER);
if (ACPI_SUCCESS(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %X acquired Mutex [%s]\n",
- this_thread_id,
+ (u32) this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
acpi_gbl_mutex_info[mutex_id].use_count++;
@@ -259,7 +259,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
} else {
ACPI_EXCEPTION((AE_INFO, status,
"Thread %X could not acquire Mutex [%X]",
- this_thread_id, mutex_id));
+ (u32) this_thread_id, mutex_id));
}
return (status);
@@ -285,7 +285,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
this_thread_id = acpi_os_get_thread_id();
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %X releasing Mutex [%s]\n", this_thread_id,
+ "Thread %X releasing Mutex [%s]\n", (u32) this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
if (mutex_id > ACPI_MAX_MUTEX) {
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
index 0f5c5bb5deff..eaa13d05c859 100644
--- a/drivers/acpi/utilities/utstate.c
+++ b/drivers/acpi/utilities/utstate.c
@@ -199,6 +199,13 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void)
state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD;
state->thread.thread_id = acpi_os_get_thread_id();
+ /* Check for invalid thread ID - zero is very bad, it will break things */
+
+ if (!state->thread.thread_id) {
+ ACPI_ERROR((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId"));
+ state->thread.thread_id = (acpi_thread_id) 1;
+ }
+
return_PTR((struct acpi_thread_state *)state);
}
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index 01a9f1cb7743..cfa5af883e13 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -398,7 +398,7 @@ config ATM_FORE200E_USE_TASKLET
default n
help
This defers work to be done by the interrupt handler to a
- tasklet instead of hanlding everything at interrupt time. This
+ tasklet instead of handling everything at interrupt time. This
may improve the responsive of the host.
config ATM_FORE200E_TX_RETRY
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 80502dc6ed66..0b4e22436935 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -20,7 +20,7 @@ config PREVENT_FIRMWARE_BUILD
config FW_LOADER
tristate "Userspace firmware loading support"
- select HOTPLUG
+ depends on HOTPLUG
---help---
This option is provided for the case where no in-kernel-tree modules
require userspace firmware loading support, but a module built outside
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 83fa8b291a59..2e954d07175a 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -129,7 +129,7 @@ static struct kobj_type ktype_bus = {
};
-decl_subsys(bus, &ktype_bus, NULL);
+static decl_subsys(bus, &ktype_bus, NULL);
#ifdef CONFIG_HOTPLUG
@@ -598,12 +598,13 @@ void put_bus(struct bus_type * bus)
*
* Note that kset_find_obj increments bus' reference count.
*/
-
+#if 0
struct bus_type * find_bus(char * name)
{
struct kobject * k = kset_find_obj(&bus_subsys.kset, name);
return k ? to_bus(k) : NULL;
}
+#endif /* 0 */
/**
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b21f864c9ce8..be6b5bc0677d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -559,20 +559,20 @@ static void device_create_release(struct device *dev)
/**
* device_create - creates a device and registers it with sysfs
- * @cs: pointer to the struct class that this device should be registered to.
- * @parent: pointer to the parent struct device of this new device, if any.
- * @dev: the dev_t for the char device to be added.
- * @fmt: string for the class device's name
+ * @class: pointer to the struct class that this device should be registered to
+ * @parent: pointer to the parent struct device of this new device, if any
+ * @devt: the dev_t for the char device to be added
+ * @fmt: string for the device's name
+ *
+ * This function can be used by char device classes. A struct device
+ * will be created in sysfs, registered to the specified class.
*
- * This function can be used by char device classes. A struct
- * device will be created in sysfs, registered to the specified
- * class.
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly
- * created struct device will be a child of that device in sysfs. The
- * pointer to the struct device will be returned from the call. Any
- * further sysfs files that might be required can be created using this
+ * If a pointer to a parent struct device is passed in, the newly created
+ * struct device will be a child of that device in sysfs.
+ * The pointer to the struct device will be returned from the call.
+ * Any further sysfs files that might be required can be created using this
* pointer.
*
* Note: the struct class passed to this function must have previously
@@ -620,11 +620,11 @@ EXPORT_SYMBOL_GPL(device_create);
/**
* device_destroy - removes a device that was created with device_create()
- * @class: the pointer to the struct class that this device was registered * with.
- * @dev: the dev_t of the device that was previously registered.
+ * @class: pointer to the struct class that this device was registered with
+ * @devt: the dev_t of the device that was previously registered
*
- * This call unregisters and cleans up a class device that was created with a
- * call to class_device_create()
+ * This call unregisters and cleans up a device that was created with a
+ * call to device_create().
*/
void device_destroy(struct class *class, dev_t devt)
{
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 5327f553b4f5..1bc1cf9603f1 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -162,7 +162,7 @@ aoechr_open(struct inode *inode, struct file *filp)
{
int n, i;
- n = MINOR(inode->i_rdev);
+ n = iminor(inode);
filp->private_data = (void *) (unsigned long) n;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 6f67141f4de0..13ba729cdd57 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -234,6 +234,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
if (!data->fw_data) {
BT_ERR("Can't allocate memory for firmware image");
+ release_firmware(firmware);
usb_free_urb(data->urb);
kfree(data->buffer);
kfree(data);
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 1994270c16e1..93ba25b7ea32 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -191,7 +191,7 @@ static int hci_uart_flush(struct hci_dev *hdev)
/* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty);
- if (tty->driver->flush_buffer)
+ if (tty->driver && tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
@@ -290,7 +290,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
- if (tty->driver->flush_buffer)
+ if (tty->driver && tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
return 0;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index ca27ee89240b..d239cf8b20bd 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1837,7 +1837,7 @@ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = s->type;
- cgc.cmd[9] = cgc.buflen = 0xff;
+ cgc.cmd[9] = cgc.buflen & 0xff;
if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 56612a2dca6b..41db8060e8f7 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -1299,7 +1299,7 @@ static int __init hvsi_console_init(void)
hp->inbuf_end = hp->inbuf;
hp->state = HVSI_CLOSED;
hp->vtermno = *vtermno;
- hp->virq = irq_create_mapping(NULL, irq[0], 0);
+ hp->virq = irq_create_mapping(NULL, irq[0]);
if (hp->virq == NO_IRQ) {
printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
__FUNCTION__, irq[0]);
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 518ece7ac656..7907ae88c2f4 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -3186,3 +3186,10 @@ ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned lo
MODULE_LICENSE("GPL");
+
+static struct pci_device_id ip2main_pci_tbl[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index e97c32ceb796..917b20402664 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -95,7 +95,7 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t count)
return 1;
}
-static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size)
+static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
return 1;
}
@@ -242,7 +242,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
size_t size = vma->vm_end - vma->vm_start;
- if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size))
+ if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
return -EINVAL;
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 4005ee0aa11e..11bd78c80628 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -3,18 +3,18 @@
National Semiconductor PC8736x GPIO driver. Allows a user space
process to play with the GPIO pins.
- Copyright (c) 2005 Jim Cromie <jim.cromie@gmail.com>
+ Copyright (c) 2005,2006 Jim Cromie <jim.cromie@gmail.com>
adapted from linux/drivers/char/scx200_gpio.c
Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>,
*/
-#include <linux/config.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/mutex.h>
@@ -25,7 +25,7 @@
#define DEVNAME "pc8736x_gpio"
MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
-MODULE_DESCRIPTION("NatSemi PC-8736x GPIO Pin Driver");
+MODULE_DESCRIPTION("NatSemi/Winbond PC-8736x GPIO Pin Driver");
MODULE_LICENSE("GPL");
static int major; /* default to dynamic major */
@@ -38,14 +38,14 @@ static u8 pc8736x_gpio_shadow[4];
#define SIO_BASE1 0x2E /* 1st command-reg to check */
#define SIO_BASE2 0x4E /* alt command-reg to check */
-#define SIO_BASE_OFFSET 0x20
#define SIO_SID 0x20 /* SuperI/O ID Register */
#define SIO_SID_VALUE 0xe9 /* Expected value in SuperI/O ID Register */
#define SIO_CF1 0x21 /* chip config, bit0 is chip enable */
-#define PC8736X_GPIO_SIZE 16
+#define PC8736X_GPIO_RANGE 16 /* ioaddr range */
+#define PC8736X_GPIO_CT 32 /* minors matching 4 8 bit ports */
#define SIO_UNIT_SEL 0x7 /* unit select reg */
#define SIO_UNIT_ACT 0x30 /* unit enable */
@@ -231,7 +231,7 @@ static int pc8736x_gpio_open(struct inode *inode, struct file *file)
dev_dbg(&pdev->dev, "open %d\n", m);
- if (m > 63)
+ if (m >= PC8736X_GPIO_CT)
return -EINVAL;
return nonseekable_open(inode, file);
}
@@ -255,9 +255,12 @@ static void __init pc8736x_init_shadow(void)
}
+static struct cdev pc8736x_gpio_cdev;
+
static int __init pc8736x_gpio_init(void)
{
- int rc = 0;
+ int rc;
+ dev_t devid;
pdev = platform_device_alloc(DEVNAME, 0);
if (!pdev)
@@ -297,7 +300,7 @@ static int __init pc8736x_gpio_init(void)
pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
| superio_inb(SIO_BASE_LADDR));
- if (!request_region(pc8736x_gpio_base, 16, DEVNAME)) {
+ if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) {
rc = -ENODEV;
dev_err(&pdev->dev, "GPIO ioport %x busy\n",
pc8736x_gpio_base);
@@ -305,10 +308,17 @@ static int __init pc8736x_gpio_init(void)
}
dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);
- rc = register_chrdev(major, DEVNAME, &pc8736x_gpio_fops);
+ if (major) {
+ devid = MKDEV(major, 0);
+ rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME);
+ } else {
+ rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME);
+ major = MAJOR(devid);
+ }
+
if (rc < 0) {
dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc);
- goto undo_platform_dev_add;
+ goto undo_request_region;
}
if (!major) {
major = rc;
@@ -316,8 +326,15 @@ static int __init pc8736x_gpio_init(void)
}
pc8736x_init_shadow();
+
+ /* ignore minor errs, and succeed */
+ cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fops);
+ cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT);
+
return 0;
+undo_request_region:
+ release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
undo_platform_dev_add:
platform_device_del(pdev);
undo_platform_dev_alloc:
@@ -328,11 +345,14 @@ undo_platform_dev_alloc:
static void __exit pc8736x_gpio_cleanup(void)
{
- dev_dbg(&pdev->dev, " cleanup\n");
+ dev_dbg(&pdev->dev, "cleanup\n");
- release_region(pc8736x_gpio_base, 16);
+ cdev_del(&pc8736x_gpio_cdev);
+ unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT);
+ release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
- unregister_chrdev(major, DEVNAME);
+ platform_device_del(pdev);
+ platform_device_put(pdev);
}
EXPORT_SYMBOL(pc8736x_access);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index cc7bd1a3095b..6e6a7c7a7eff 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -46,13 +46,12 @@
* 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init
* 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
* CONFIG_HPET_EMULATE_RTC
+ * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly.
* 1.12ac Alan Cox: Allow read access to the day of week register
*/
#define RTC_VERSION "1.12ac"
-#define RTC_IO_EXTENT 0x8
-
/*
* Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
* interrupts disabled. Due to the index-port/data-port (0x70/0x71)
@@ -337,7 +336,15 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
if (rtc_has_irq == 0)
return -EIO;
- if (count < sizeof(unsigned))
+ /*
+ * Historically this function used to assume that sizeof(unsigned long)
+ * is the same in userspace and kernelspace. This lead to problems
+ * for configurations with multiple ABIs such a the MIPS o32 and 64
+ * ABIs supported on the same kernel. So now we support read of both
+ * 4 and 8 bytes and assume that's the sizeof(unsigned long) in the
+ * userspace ABI.
+ */
+ if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
return -EINVAL;
add_wait_queue(&rtc_wait, &wait);
@@ -368,10 +375,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
schedule();
} while (1);
- if (count < sizeof(unsigned long))
- retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int);
+ if (count == sizeof(unsigned int))
+ retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int);
else
retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long);
+ if (!retval)
+ retval = count;
out:
current->state = TASK_RUNNING;
remove_wait_queue(&rtc_wait, &wait);
@@ -923,6 +932,9 @@ static int __init rtc_init(void)
struct sparc_isa_device *isa_dev;
#endif
#endif
+#ifndef __sparc__
+ void *r;
+#endif
#ifdef __sparc__
for_each_ebus(ebus) {
@@ -964,8 +976,13 @@ found:
}
no_irq:
#else
- if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) {
- printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0));
+ 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");
+ if (!r) {
+ printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
+ (long)(RTC_PORT(0)));
return -EIO;
}
@@ -979,7 +996,10 @@ no_irq:
if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
+ if (RTC_IOMAPPED)
+ release_region(RTC_PORT(0), RTC_IO_EXTENT);
+ else
+ release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
return -EIO;
}
hpet_rtc_timer_init();
@@ -1079,7 +1099,10 @@ static void __exit rtc_exit (void)
if (rtc_has_irq)
free_irq (rtc_irq, &rtc_port);
#else
- release_region (RTC_PORT (0), RTC_IO_EXTENT);
+ if (RTC_IOMAPPED)
+ release_region(RTC_PORT(0), RTC_IO_EXTENT);
+ else
+ release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
#ifdef RTC_IRQ
if (rtc_has_irq)
free_irq (RTC_IRQ, NULL);
@@ -1222,7 +1245,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
{
- unsigned long uip_watchdog = jiffies;
+ unsigned long uip_watchdog = jiffies, flags;
unsigned char ctrl;
#ifdef CONFIG_MACH_DECSTATION
unsigned int real_year;
@@ -1249,7 +1272,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
* RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is
* only updated by the RTC when initially set to a non-zero value.
*/
- spin_lock_irq(&rtc_lock);
+ spin_lock_irqsave(&rtc_lock, flags);
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
@@ -1263,7 +1286,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
real_year = CMOS_READ(RTC_DEC_YEAR);
#endif
ctrl = CMOS_READ(RTC_CONTROL);
- spin_unlock_irq(&rtc_lock);
+ spin_unlock_irqrestore(&rtc_lock, flags);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index 8b2210b633df..d12d4f629cec 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -220,20 +220,7 @@ scdrv_dispatch_event(char *event, int len)
" Sending SIGPWR to init...\n");
/* give a SIGPWR signal to init proc */
-
- /* first find init's task */
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if (p->pid == 1)
- break;
- }
- if (p) {
- force_sig(SIGPWR, p);
- } else {
- printk(KERN_ERR "Failed to signal init!\n");
- snsc_shutting_down = 0; /* so can try again (?) */
- }
- read_unlock(&tasklist_lock);
+ kill_proc(1, SIGPWR, 0);
} else {
/* print to system log */
printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index cb2859249d49..a1d303f9a33d 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -2584,6 +2584,12 @@ static void __exit specialix_exit_module(void)
func_exit();
}
+static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
+
module_init(specialix_init_module);
module_exit(specialix_exit_module);
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 3a7cfe88b169..4bde30bb3be7 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1,6 +1,6 @@
/*
* edac_mc kernel module
- * (C) 2005 Linux Networx (http://lnxi.com)
+ * (C) 2005, 2006 Linux Networx (http://lnxi.com)
* This file may be distributed under the terms of the
* GNU General Public License.
*
@@ -33,13 +33,8 @@
#include <asm/edac.h>
#include "edac_mc.h"
-#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__
+#define EDAC_MC_VERSION "Ver: 2.0.1 " __DATE__
-/* For now, disable the EDAC sysfs code. The sysfs interface that EDAC
- * presents to user space needs more thought, and is likely to change
- * substantially.
- */
-#define DISABLE_EDAC_SYSFS
#ifdef CONFIG_EDAC_DEBUG
/* Values of 0 to 4 will generate output */
@@ -64,31 +59,12 @@ static int check_pci_parity = 0; /* default YES check PCI parity */
static int panic_on_pci_parity; /* default no panic on PCI Parity */
static atomic_t pci_parity_count = ATOMIC_INIT(0);
-/* Structure of the whitelist and blacklist arrays */
-struct edac_pci_device_list {
- unsigned int vendor; /* Vendor ID */
- unsigned int device; /* Deviice ID */
-};
-
-#define MAX_LISTED_PCI_DEVICES 32
-
-/* List of PCI devices (vendor-id:device-id) that should be skipped */
-static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
-static int pci_blacklist_count;
-
-/* List of PCI devices (vendor-id:device-id) that should be scanned */
-static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
-static int pci_whitelist_count ;
-
-#ifndef DISABLE_EDAC_SYSFS
static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */
static struct completion edac_pci_kobj_complete;
-#endif /* DISABLE_EDAC_SYSFS */
#endif /* CONFIG_PCI */
/* START sysfs data and methods */
-#ifndef DISABLE_EDAC_SYSFS
static const char *mem_types[] = {
[MEM_EMPTY] = "Empty",
@@ -147,18 +123,10 @@ static struct completion edac_memctrl_kobj_complete;
* /sys/devices/system/edac/mc;
* data structures and methods
*/
-#if 0
-static ssize_t memctrl_string_show(void *ptr, char *buffer)
-{
- char *value = (char*) ptr;
- return sprintf(buffer, "%s\n", value);
-}
-#endif
-
static ssize_t memctrl_int_show(void *ptr, char *buffer)
{
int *value = (int*) ptr;
- return sprintf(buffer, "%d\n", *value);
+ return sprintf(buffer, "%u\n", *value);
}
static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
@@ -224,11 +192,6 @@ struct memctrl_dev_attribute attr_##_name = { \
.store = _store, \
};
-/* cwrow<id> attribute f*/
-#if 0
-MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
-#endif
-
/* csrow<id> control files */
MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
@@ -257,8 +220,6 @@ static struct kobj_type ktype_memctrl = {
.default_attrs = (struct attribute **) memctrl_attr,
};
-#endif /* DISABLE_EDAC_SYSFS */
-
/* Initialize the main sysfs entries for edac:
* /sys/devices/system/edac
*
@@ -268,11 +229,6 @@ static struct kobj_type ktype_memctrl = {
* !0 FAILURE
*/
static int edac_sysfs_memctrl_setup(void)
-#ifdef DISABLE_EDAC_SYSFS
-{
- return 0;
-}
-#else
{
int err=0;
@@ -304,7 +260,6 @@ static int edac_sysfs_memctrl_setup(void)
return err;
}
-#endif /* DISABLE_EDAC_SYSFS */
/*
* MC teardown:
@@ -312,7 +267,6 @@ static int edac_sysfs_memctrl_setup(void)
*/
static void edac_sysfs_memctrl_teardown(void)
{
-#ifndef DISABLE_EDAC_SYSFS
debugf0("MC: " __FILE__ ": %s()\n", __func__);
/* Unregister the MC's kobject and wait for reference count to reach
@@ -324,144 +278,9 @@ static void edac_sysfs_memctrl_teardown(void)
/* Unregister the 'edac' object */
sysdev_class_unregister(&edac_class);
-#endif /* DISABLE_EDAC_SYSFS */
}
#ifdef CONFIG_PCI
-
-#ifndef DISABLE_EDAC_SYSFS
-
-/*
- * /sys/devices/system/edac/pci;
- * data structures and methods
- */
-
-struct list_control {
- struct edac_pci_device_list *list;
- int *count;
-};
-
-#if 0
-/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
-static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
-{
- struct list_control *listctl;
- struct edac_pci_device_list *list;
- char *p = buffer;
- int len=0;
- int i;
-
- listctl = ptr;
- list = listctl->list;
-
- for (i = 0; i < *(listctl->count); i++, list++ ) {
- if (len > 0)
- len += snprintf(p + len, (PAGE_SIZE-len), ",");
-
- len += snprintf(p + len,
- (PAGE_SIZE-len),
- "%x:%x",
- list->vendor,list->device);
- }
-
- len += snprintf(p + len,(PAGE_SIZE-len), "\n");
- return (ssize_t) len;
-}
-
-/**
- *
- * Scan string from **s to **e looking for one 'vendor:device' tuple
- * where each field is a hex value
- *
- * return 0 if an entry is NOT found
- * return 1 if an entry is found
- * fill in *vendor_id and *device_id with values found
- *
- * In both cases, make sure *s has been moved forward toward *e
- */
-static int parse_one_device(const char **s,const char **e,
- unsigned int *vendor_id, unsigned int *device_id)
-{
- const char *runner, *p;
-
- /* if null byte, we are done */
- if (!**s) {
- (*s)++; /* keep *s moving */
- return 0;
- }
-
- /* skip over newlines & whitespace */
- if ((**s == '\n') || isspace(**s)) {
- (*s)++;
- return 0;
- }
-
- if (!isxdigit(**s)) {
- (*s)++;
- return 0;
- }
-
- /* parse vendor_id */
- runner = *s;
-
- while (runner < *e) {
- /* scan for vendor:device delimiter */
- if (*runner == ':') {
- *vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
- runner = p + 1;
- break;
- }
-
- runner++;
- }
-
- if (!isxdigit(*runner)) {
- *s = ++runner;
- return 0;
- }
-
- /* parse device_id */
- if (runner < *e) {
- *device_id = simple_strtol((char*)runner, (char**)&p, 16);
- runner = p;
- }
-
- *s = runner;
- return 1;
-}
-
-static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
- size_t count)
-{
- struct list_control *listctl;
- struct edac_pci_device_list *list;
- unsigned int vendor_id, device_id;
- const char *s, *e;
- int *index;
-
- s = (char*)buffer;
- e = s + count;
- listctl = ptr;
- list = listctl->list;
- index = listctl->count;
- *index = 0;
-
- while (*index < MAX_LISTED_PCI_DEVICES) {
- if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
- list[ *index ].vendor = vendor_id;
- list[ *index ].device = device_id;
- (*index)++;
- }
-
- /* check for all data consume */
- if (s >= e)
- break;
- }
-
- return count;
-}
-
-#endif
static ssize_t edac_pci_int_show(void *ptr, char *buffer)
{
int *value = ptr;
@@ -529,31 +348,6 @@ struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
.store = _store, \
};
-#if 0
-static struct list_control pci_whitelist_control = {
- .list = pci_whitelist,
- .count = &pci_whitelist_count
-};
-
-static struct list_control pci_blacklist_control = {
- .list = pci_blacklist,
- .count = &pci_blacklist_count
-};
-
-/* whitelist attribute */
-EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
- &pci_whitelist_control,
- S_IRUGO|S_IWUSR,
- edac_pci_list_string_show,
- edac_pci_list_string_store);
-
-EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
- &pci_blacklist_control,
- S_IRUGO|S_IWUSR,
- edac_pci_list_string_show,
- edac_pci_list_string_store);
-#endif
-
/* PCI Parity control files */
EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show,
edac_pci_int_store);
@@ -582,18 +376,11 @@ static struct kobj_type ktype_edac_pci = {
.default_attrs = (struct attribute **) edac_pci_attr,
};
-#endif /* DISABLE_EDAC_SYSFS */
-
/**
* edac_sysfs_pci_setup()
*
*/
static int edac_sysfs_pci_setup(void)
-#ifdef DISABLE_EDAC_SYSFS
-{
- return 0;
-}
-#else
{
int err;
@@ -617,16 +404,13 @@ static int edac_sysfs_pci_setup(void)
return err;
}
-#endif /* DISABLE_EDAC_SYSFS */
static void edac_sysfs_pci_teardown(void)
{
-#ifndef DISABLE_EDAC_SYSFS
debugf0("%s()\n", __func__);
init_completion(&edac_pci_kobj_complete);
kobject_unregister(&edac_pci_kobj);
wait_for_completion(&edac_pci_kobj_complete);
-#endif
}
@@ -756,36 +540,6 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
}
/*
- * check_dev_on_list: Scan for a PCI device on a white/black list
- * @list: an EDAC &edac_pci_device_list white/black list pointer
- * @free_index: index of next free entry on the list
- * @pci_dev: PCI Device pointer
- *
- * see if list contains the device.
- *
- * Returns: 0 not found
- * 1 found on list
- */
-static int check_dev_on_list(struct edac_pci_device_list *list,
- int free_index, struct pci_dev *dev)
-{
- int i;
- int rc = 0; /* Assume not found */
- unsigned short vendor=dev->vendor;
- unsigned short device=dev->device;
-
- /* Scan the list, looking for a vendor/device match */
- for (i = 0; i < free_index; i++, list++ ) {
- if ((list->vendor == vendor ) && (list->device == device )) {
- rc = 1;
- break;
- }
- }
-
- return rc;
-}
-
-/*
* pci_dev parity list iterator
* Scan the PCI device list for one iteration, looking for SERRORs
* Master Parity ERRORS or Parity ERRORs on primary or secondary devices
@@ -799,22 +553,7 @@ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
* bumped until we are done with it
*/
while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- /* if whitelist exists then it has priority, so only scan
- * those devices on the whitelist
- */
- if (pci_whitelist_count > 0 ) {
- if (check_dev_on_list(pci_whitelist,
- pci_whitelist_count, dev))
- fn(dev);
- } else {
- /*
- * if no whitelist, then check if this devices is
- * blacklisted
- */
- if (!check_dev_on_list(pci_blacklist,
- pci_blacklist_count, dev))
- fn(dev);
- }
+ fn(dev);
}
}
@@ -855,154 +594,101 @@ static inline void clear_pci_parity_errors(void)
#else /* CONFIG_PCI */
-static inline void do_pci_parity_check(void)
-{
- /* no-op */
-}
-
-static inline void clear_pci_parity_errors(void)
-{
- /* no-op */
-}
-
-static void edac_sysfs_pci_teardown(void)
-{
-}
+/* pre-process these away */
+#define do_pci_parity_check()
+#define clear_pci_parity_errors()
+#define edac_sysfs_pci_teardown()
+#define edac_sysfs_pci_setup() (0)
-static int edac_sysfs_pci_setup(void)
-{
- return 0;
-}
#endif /* CONFIG_PCI */
-#ifndef DISABLE_EDAC_SYSFS
-
-/* EDAC sysfs CSROW data structures and methods */
-
-/* Set of more detailed csrow<id> attribute show/store functions */
-static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
-{
- ssize_t size = 0;
-
- if (csrow->nr_channels > 0) {
- size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
- csrow->channels[0].label);
- }
-
- return size;
-}
+/* EDAC sysfs CSROW data structures and methods
+ */
-static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
+/* Set of more default csrow<id> attribute show/store functions */
+static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data, int private)
{
- ssize_t size = 0;
-
- if (csrow->nr_channels > 0) {
- size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
- csrow->channels[1].label);
- }
-
- return size;
+ return sprintf(data,"%u\n", csrow->ue_count);
}
-static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
- const char *data, size_t size)
+static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, int private)
{
- ssize_t max_size = 0;
-
- if (csrow->nr_channels > 0) {
- max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
- strncpy(csrow->channels[0].label, data, max_size);
- csrow->channels[0].label[max_size] = '\0';
- }
-
- return size;
+ return sprintf(data,"%u\n", csrow->ce_count);
}
-static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
- const char *data, size_t size)
+static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, int private)
{
- ssize_t max_size = 0;
-
- if (csrow->nr_channels > 1) {
- max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
- strncpy(csrow->channels[1].label, data, max_size);
- csrow->channels[1].label[max_size] = '\0';
- }
-
- return max_size;
+ return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
}
-static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data)
+static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, int private)
{
- return sprintf(data,"%u\n", csrow->ue_count);
+ return sprintf(data,"%s\n", mem_types[csrow->mtype]);
}
-static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data)
+static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, int private)
{
- return sprintf(data,"%u\n", csrow->ce_count);
+ return sprintf(data,"%s\n", dev_types[csrow->dtype]);
}
-static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
+static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, int private)
{
- ssize_t size = 0;
-
- if (csrow->nr_channels > 0) {
- size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
- }
-
- return size;
+ return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
}
-static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
+/* show/store functions for DIMM Label attributes */
+static ssize_t channel_dimm_label_show(struct csrow_info *csrow,
+ char *data, int channel)
{
- ssize_t size = 0;
-
- if (csrow->nr_channels > 1) {
- size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
- }
-
- return size;
+ return snprintf(data, EDAC_MC_LABEL_LEN,"%s",
+ csrow->channels[channel].label);
}
-static ssize_t csrow_size_show(struct csrow_info *csrow, char *data)
+static ssize_t channel_dimm_label_store(struct csrow_info *csrow,
+ const char *data,
+ size_t count,
+ int channel)
{
- return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
-}
+ ssize_t max_size = 0;
-static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data)
-{
- return sprintf(data,"%s\n", mem_types[csrow->mtype]);
-}
+ max_size = min((ssize_t)count,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[channel].label, data, max_size);
+ csrow->channels[channel].label[max_size] = '\0';
-static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data)
-{
- return sprintf(data,"%s\n", dev_types[csrow->dtype]);
+ return max_size;
}
-static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
+/* show function for dynamic chX_ce_count attribute */
+static ssize_t channel_ce_count_show(struct csrow_info *csrow,
+ char *data,
+ int channel)
{
- return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
+ return sprintf(data, "%u\n", csrow->channels[channel].ce_count);
}
+/* csrow specific attribute structure */
struct csrowdev_attribute {
struct attribute attr;
- ssize_t (*show)(struct csrow_info *,char *);
- ssize_t (*store)(struct csrow_info *, const char *,size_t);
+ ssize_t (*show)(struct csrow_info *,char *,int);
+ ssize_t (*store)(struct csrow_info *, const char *,size_t,int);
+ int private;
};
#define to_csrow(k) container_of(k, struct csrow_info, kobj)
#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
-/* Set of show/store higher level functions for csrow objects */
-static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
- char *buffer)
+/* Set of show/store higher level functions for default csrow attributes */
+static ssize_t csrowdev_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buffer)
{
struct csrow_info *csrow = to_csrow(kobj);
struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
if (csrowdev_attr->show)
- return csrowdev_attr->show(csrow, buffer);
-
+ return csrowdev_attr->show(csrow,
+ buffer,
+ csrowdev_attr->private);
return -EIO;
}
@@ -1013,8 +699,10 @@ static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
if (csrowdev_attr->store)
- return csrowdev_attr->store(csrow, buffer, count);
-
+ return csrowdev_attr->store(csrow,
+ buffer,
+ count,
+ csrowdev_attr->private);
return -EIO;
}
@@ -1023,69 +711,157 @@ static struct sysfs_ops csrowfs_ops = {
.store = csrowdev_store
};
-#define CSROWDEV_ATTR(_name,_mode,_show,_store) \
+#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private) \
struct csrowdev_attribute attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
+ .private = _private, \
};
-/* cwrow<id>/attribute files */
-CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL);
-CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL);
-CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL);
-CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL);
-CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL);
-CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL);
-CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
-CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
-
-/* control/attribute files */
-CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
- csrow_ch0_dimm_label_show,
- csrow_ch0_dimm_label_store);
-CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
- csrow_ch1_dimm_label_show,
- csrow_ch1_dimm_label_store);
+/* default cwrow<id>/attribute files */
+CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL,0);
+CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL,0);
+CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL,0);
+CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL,0);
+CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL,0);
+CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL,0);
-/* Attributes of the CSROW<id> object */
-static struct csrowdev_attribute *csrow_attr[] = {
+/* default attributes of the CSROW<id> object */
+static struct csrowdev_attribute *default_csrow_attr[] = {
&attr_dev_type,
&attr_mem_type,
&attr_edac_mode,
&attr_size_mb,
&attr_ue_count,
&attr_ce_count,
- &attr_ch0_ce_count,
- &attr_ch1_ce_count,
- &attr_ch0_dimm_label,
- &attr_ch1_dimm_label,
NULL,
};
-/* No memory to release */
+
+/* possible dynamic channel DIMM Label attribute files */
+CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
+ channel_dimm_label_show,
+ channel_dimm_label_store,
+ 0 );
+CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
+ channel_dimm_label_show,
+ channel_dimm_label_store,
+ 1 );
+CSROWDEV_ATTR(ch2_dimm_label,S_IRUGO|S_IWUSR,
+ channel_dimm_label_show,
+ channel_dimm_label_store,
+ 2 );
+CSROWDEV_ATTR(ch3_dimm_label,S_IRUGO|S_IWUSR,
+ channel_dimm_label_show,
+ channel_dimm_label_store,
+ 3 );
+CSROWDEV_ATTR(ch4_dimm_label,S_IRUGO|S_IWUSR,
+ channel_dimm_label_show,
+ channel_dimm_label_store,
+ 4 );
+CSROWDEV_ATTR(ch5_dimm_label,S_IRUGO|S_IWUSR,
+ channel_dimm_label_show,
+ channel_dimm_label_store,
+ 5 );
+
+/* Total possible dynamic DIMM Label attribute file table */
+static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = {
+ &attr_ch0_dimm_label,
+ &attr_ch1_dimm_label,
+ &attr_ch2_dimm_label,
+ &attr_ch3_dimm_label,
+ &attr_ch4_dimm_label,
+ &attr_ch5_dimm_label
+};
+
+/* possible dynamic channel ce_count attribute files */
+CSROWDEV_ATTR(ch0_ce_count,S_IRUGO|S_IWUSR,
+ channel_ce_count_show,
+ NULL,
+ 0 );
+CSROWDEV_ATTR(ch1_ce_count,S_IRUGO|S_IWUSR,
+ channel_ce_count_show,
+ NULL,
+ 1 );
+CSROWDEV_ATTR(ch2_ce_count,S_IRUGO|S_IWUSR,
+ channel_ce_count_show,
+ NULL,
+ 2 );
+CSROWDEV_ATTR(ch3_ce_count,S_IRUGO|S_IWUSR,
+ channel_ce_count_show,
+ NULL,
+ 3 );
+CSROWDEV_ATTR(ch4_ce_count,S_IRUGO|S_IWUSR,
+ channel_ce_count_show,
+ NULL,
+ 4 );
+CSROWDEV_ATTR(ch5_ce_count,S_IRUGO|S_IWUSR,
+ channel_ce_count_show,
+ NULL,
+ 5 );
+
+/* Total possible dynamic ce_count attribute file table */
+static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = {
+ &attr_ch0_ce_count,
+ &attr_ch1_ce_count,
+ &attr_ch2_ce_count,
+ &attr_ch3_ce_count,
+ &attr_ch4_ce_count,
+ &attr_ch5_ce_count
+};
+
+
+#define EDAC_NR_CHANNELS 6
+
+/* Create dynamic CHANNEL files, indexed by 'chan', under specifed CSROW */
+static int edac_create_channel_files(struct kobject *kobj, int chan)
+{
+ int err=-ENODEV;
+
+ if (chan >= EDAC_NR_CHANNELS)
+ return err;
+
+ /* create the DIMM label attribute file */
+ err = sysfs_create_file(kobj,
+ (struct attribute *) dynamic_csrow_dimm_attr[chan]);
+
+ if (!err) {
+ /* create the CE Count attribute file */
+ err = sysfs_create_file(kobj,
+ (struct attribute *) dynamic_csrow_ce_count_attr[chan]);
+ } else {
+ debugf1("%s() dimm labels and ce_count files created", __func__);
+ }
+
+ return err;
+}
+
+/* No memory to release for this kobj */
static void edac_csrow_instance_release(struct kobject *kobj)
{
struct csrow_info *cs;
- debugf1("%s()\n", __func__);
cs = container_of(kobj, struct csrow_info, kobj);
complete(&cs->kobj_complete);
}
+/* the kobj_type instance for a CSROW */
static struct kobj_type ktype_csrow = {
.release = edac_csrow_instance_release,
.sysfs_ops = &csrowfs_ops,
- .default_attrs = (struct attribute **) csrow_attr,
+ .default_attrs = (struct attribute **) default_csrow_attr,
};
/* Create a CSROW object under specifed edac_mc_device */
-static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
- struct csrow_info *csrow, int index)
+static int edac_create_csrow_object(
+ struct kobject *edac_mci_kobj,
+ struct csrow_info *csrow,
+ int index)
{
int err = 0;
+ int chan;
- debugf0("%s()\n", __func__);
memset(&csrow->kobj, 0, sizeof(csrow->kobj));
/* generate ..../edac/mc/mc<id>/csrow<index> */
@@ -1095,21 +871,27 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
/* name this instance of csrow<id> */
err = kobject_set_name(&csrow->kobj,"csrow%d",index);
+ if (err)
+ goto error_exit;
+ /* Instanstiate the csrow object */
+ err = kobject_register(&csrow->kobj);
if (!err) {
- /* Instanstiate the csrow object */
- err = kobject_register(&csrow->kobj);
-
- if (err)
- debugf0("Failed to register CSROW%d\n",index);
- else
- debugf0("Registered CSROW%d\n",index);
+ /* Create the dyanmic attribute files on this csrow,
+ * namely, the DIMM labels and the channel ce_count
+ */
+ for (chan = 0; chan < csrow->nr_channels; chan++) {
+ err = edac_create_channel_files(&csrow->kobj,chan);
+ if (err)
+ break;
+ }
}
+error_exit:
return err;
}
-/* sysfs data structures and methods for the MCI kobjects */
+/* default sysfs methods and data structures for the main MCI kobject */
static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
const char *data, size_t count)
@@ -1135,6 +917,7 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
return count;
}
+/* default attribute files for the MCI object */
static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
{
return sprintf(data,"%d\n", mci->ue_count);
@@ -1160,71 +943,11 @@ static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
}
-static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
-{
- return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
-}
-
static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
{
return sprintf(data,"%s\n", mci->ctl_name);
}
-static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
-{
- char *p = buf;
- int bit_idx;
-
- for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
- if ((edac_cap >> bit_idx) & 0x1)
- p += sprintf(p, "%s ", edac_caps[bit_idx]);
- }
-
- return p - buf;
-}
-
-static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
-{
- char *p = data;
-
- p += mci_output_edac_cap(p,mci->edac_ctl_cap);
- p += sprintf(p, "\n");
- return p - data;
-}
-
-static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
- char *data)
-{
- char *p = data;
-
- p += mci_output_edac_cap(p,mci->edac_cap);
- p += sprintf(p, "\n");
- return p - data;
-}
-
-static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
-{
- char *p = buf;
- int bit_idx;
-
- for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
- if ((mtype_cap >> bit_idx) & 0x1)
- p += sprintf(p, "%s ", mem_types[bit_idx]);
- }
-
- return p - buf;
-}
-
-static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci,
- char *data)
-{
- char *p = data;
-
- p += mci_output_mtype_cap(p,mci->mtype_cap);
- p += sprintf(p, "\n");
- return p - data;
-}
-
static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
{
int total_pages, csrow_idx;
@@ -1251,6 +974,7 @@ struct mcidev_attribute {
#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
+/* MCI show/store functions for top most object */
static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
char *buffer)
{
@@ -1287,31 +1011,21 @@ struct mcidev_attribute mci_attr_##_name = { \
.store = _store, \
};
-/* Control file */
+/* default Control file */
MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
-/* Attribute files */
+/* default Attribute files */
MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
-MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
-MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
-MCIDEV_ATTR(edac_current_capability,S_IRUGO,
- mci_edac_current_capability_show,NULL);
-MCIDEV_ATTR(supported_mem_type,S_IRUGO,
- mci_supported_mem_type_show,NULL);
static struct mcidev_attribute *mci_attr[] = {
&mci_attr_reset_counters,
- &mci_attr_module_name,
&mci_attr_mc_name,
- &mci_attr_edac_capability,
- &mci_attr_edac_current_capability,
- &mci_attr_supported_mem_type,
&mci_attr_size_mb,
&mci_attr_seconds_since_reset,
&mci_attr_ue_noinfo_count,
@@ -1339,7 +1053,6 @@ static struct kobj_type ktype_mci = {
.default_attrs = (struct attribute **) mci_attr,
};
-#endif /* DISABLE_EDAC_SYSFS */
#define EDAC_DEVICE_SYMLINK "device"
@@ -1352,11 +1065,6 @@ static struct kobj_type ktype_mci = {
* !0 Failure
*/
static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
-#ifdef DISABLE_EDAC_SYSFS
-{
- return 0;
-}
-#else
{
int i;
int err;
@@ -1368,7 +1076,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
/* set the name of the mc<id> object */
err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
-
if (err)
return err;
@@ -1378,14 +1085,12 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
/* register the mc<id> kobject */
err = kobject_register(edac_mci_kobj);
-
if (err)
return err;
/* create a symlink for the device */
err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj,
EDAC_DEVICE_SYMLINK);
-
if (err)
goto fail0;
@@ -1398,7 +1103,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
/* Only expose populated CSROWs */
if (csrow->nr_pages > 0) {
err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
-
if (err)
goto fail1;
}
@@ -1422,14 +1126,12 @@ fail0:
wait_for_completion(&mci->kobj_complete);
return err;
}
-#endif /* DISABLE_EDAC_SYSFS */
/*
* remove a Memory Controller instance
*/
static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
{
-#ifndef DISABLE_EDAC_SYSFS
int i;
debugf0("%s()\n", __func__);
@@ -1447,7 +1149,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
init_completion(&mci->kobj_complete);
kobject_unregister(&mci->edac_mci_kobj);
wait_for_completion(&mci->kobj_complete);
-#endif /* DISABLE_EDAC_SYSFS */
}
/* END OF sysfs data and methods */
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 59122cc0a50a..cc15c4f2e9ec 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -142,6 +142,14 @@ static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 };
static int force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Set to one to force detection.");
+static int bank1_types[ABIT_UGURU_MAX_BANK1_SENSORS] = { -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+module_param_array(bank1_types, int, NULL, 0);
+MODULE_PARM_DESC(bank1_types, "Bank1 sensortype autodetection override:\n"
+ " -1 autodetect\n"
+ " 0 volt sensor\n"
+ " 1 temp sensor\n"
+ " 2 not connected");
static int fan_sensors;
module_param(fan_sensors, int, 0);
MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru "
@@ -397,6 +405,15 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
u8 val, buf[3];
int ret = ABIT_UGURU_NC;
+ /* If overriden by the user return the user selected type */
+ if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR &&
+ bank1_types[sensor_addr] <= ABIT_UGURU_NC) {
+ ABIT_UGURU_DEBUG(2, "assuming sensor type %d for bank1 sensor "
+ "%d because of \"bank1_types\" module param\n",
+ bank1_types[sensor_addr], (int)sensor_addr);
+ return bank1_types[sensor_addr];
+ }
+
/* First read the sensor and the current settings */
if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val,
1, ABIT_UGURU_MAX_RETRIES) != 1)
@@ -514,7 +531,7 @@ abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
{
int i;
- if (fan_sensors) {
+ if (fan_sensors > 0 && fan_sensors <= ABIT_UGURU_MAX_BANK2_SENSORS) {
data->bank2_sensors = fan_sensors;
ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of "
"\"fan_sensors\" module param\n",
@@ -568,7 +585,7 @@ abituguru_detect_no_pwms(struct abituguru_data *data)
{
int i, j;
- if (pwms) {
+ if (pwms > 0 && pwms <= ABIT_UGURU_MAX_PWMS) {
data->pwms = pwms;
ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of "
"\"pwms\" module param\n", (int)data->pwms);
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index df05df1a0ef6..ab230c033f99 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -372,7 +372,6 @@ static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
while (count > 0) {
inval = i2c_inb(i2c_adap);
-/*printk("%#02x ",inval); if ( ! (count % 16) ) printk("\n"); */
if (inval>=0) {
*temp = inval;
rdcount++;
@@ -544,8 +543,7 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
- i2c_add_adapter(adap);
- return 0;
+ return i2c_add_adapter(adap);
}
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index 2db7bfc85225..70d8eefb5efc 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -742,10 +742,8 @@ int i2c_iic_add_bus(struct i2c_adapter *adap)
adap->retries = 3; /* be replaced by defines */
adap->flags = 0;
- i2c_add_adapter(adap);
iic_init(iic_adap);
-
- return 0;
+ return i2c_add_adapter(adap);
}
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 82946acab4c7..b88a6fcf7bd0 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -374,10 +374,10 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
- rval = pca_init(pca_adap);
+ if ((rval = pca_init(pca_adap)))
+ return rval;
- if (!rval)
- i2c_add_adapter(adap);
+ rval = i2c_add_adapter(adap);
return rval;
}
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 6e498df1f717..5b24930adb5a 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -479,9 +479,11 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
- rval = pcf_init_8584(pcf_adap);
- if (!rval)
- i2c_add_adapter(adap);
+ if ((rval = pcf_init_8584(pcf_adap)))
+ return rval;
+
+ rval = i2c_add_adapter(adap);
+
return rval;
}
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 3df3f09995c2..32d41c6fac0f 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -173,9 +173,7 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
printk("\n");
}
- i2c_add_adapter(i2c_adap);
-
- return 0;
+ return i2c_add_adapter(i2c_adap);
}
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index aca7e1668605..48c56939c861 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -21,6 +21,9 @@
* - Make it work with IXP46x chips
* - Cleanup function names, coding style, etc
*
+ * - writing to slave address causes latchup on iop331.
+ * fix: driver refuses to address self.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
@@ -73,12 +76,6 @@ iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
}
static void
-iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
-{
- __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET);
-}
-
-static void
iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
@@ -248,6 +245,13 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
int status;
int rc;
+ /* avoid writing to my slave address (hangs on 80331),
+ * forbidden in Intel developer manual
+ */
+ if (msg->addr == MYSAR) {
+ return -EBUSY;
+ }
+
__raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
@@ -498,7 +502,6 @@ iop3xx_i2c_probe(struct platform_device *pdev)
spin_lock_init(&adapter_data->lock);
iop3xx_i2c_reset(adapter_data);
- iop3xx_i2c_set_slave_addr(adapter_data);
iop3xx_i2c_enable(adapter_data);
platform_set_drvdata(pdev, new_adapter);
diff --git a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h
index e46ebaea7b1e..8485861f6a36 100644
--- a/drivers/i2c/busses/i2c-iop3xx.h
+++ b/drivers/i2c/busses/i2c-iop3xx.h
@@ -80,7 +80,7 @@
#define IOP3XX_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
#define IOP3XX_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
-#define MYSAR 0x02 /* SWAG a suitable slave address */
+#define MYSAR 0 /* default slave address */
#define I2C_ERR 321
#define I2C_ERR_BERR (I2C_ERR+0)
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 2a0b3be7cdd0..53bb43593863 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -148,8 +148,6 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
int read;
int addrdir;
- if (num != 1)
- return -EINVAL;
if (msgs->flags & I2C_M_TEN)
return -EINVAL;
read = (msgs->flags & I2C_M_RD) != 0;
@@ -166,7 +164,7 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
bail:
pmac_i2c_close(bus);
- return rc < 0 ? rc : msgs->len;
+ return rc < 0 ? rc : 1;
}
static u32 i2c_powermac_func(struct i2c_adapter * adapter)
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 22a3eda04166..ced309ff056f 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -184,21 +184,21 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
break;
case state_read:
- /* Set ACK if receiving the last byte */
- if (iface->len == 1)
+ /* Set ACK if _next_ byte will be the last one */
+ if (iface->len == 2)
outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
else
outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
- *iface->ptr++ = inb(ACBSDA);
- --iface->len;
-
- if (iface->len == 0) {
+ if (iface->len == 1) {
iface->result = 0;
iface->state = state_idle;
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
}
+ *iface->ptr++ = inb(ACBSDA);
+ --iface->len;
+
break;
case state_write:
@@ -307,8 +307,12 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
buffer = (u8 *)&cur_word;
break;
- case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (rw == I2C_SMBUS_READ)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */
len = data->block[0];
+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
buffer = &data->block[1];
break;
@@ -372,7 +376,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA;
+ I2C_FUNC_SMBUS_I2C_BLOCK;
}
/* For now, we only handle combined mode (smbus) */
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 54b6e6a4beed..cb22280cdd27 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -134,11 +134,13 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
new_client->driver = &pca9539_driver;
new_client->flags = 0;
- /* Detection: the pca9539 only has 8 registers (0-7).
- A read of 7 should succeed, but a read of 8 should fail. */
- if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
- (i2c_smbus_read_byte_data(new_client, 8) >= 0))
- goto exit_kfree;
+ if (kind < 0) {
+ /* Detection: the pca9539 only has 8 registers (0-7).
+ A read of 7 should succeed, but a read of 8 should fail. */
+ if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
+ (i2c_smbus_read_byte_data(new_client, 8) >= 0))
+ goto exit_kfree;
+ }
strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a45155f799d4..9cb277d6aa48 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -756,9 +756,9 @@ int i2c_probe(struct i2c_adapter *adapter,
"parameter for adapter %d, "
"addr 0x%02x\n", adap_id,
address_data->ignore[j + 1]);
+ ignore = 1;
+ break;
}
- ignore = 1;
- break;
}
if (ignore)
continue;
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index b7e459e4f284..602797a44208 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -146,16 +146,7 @@ static void ide_detach(struct pcmcia_device *link)
kfree(link->priv);
} /* ide_detach */
-static void idecs_mmio_fixup(ide_hwif_t *hwif)
-{
- default_hwif_mmiops(hwif);
- hwif->mmio = 2;
-
- ide_undecoded_slave(hwif);
-}
-
-static int idecs_register(unsigned long io, unsigned long ctl,
- unsigned long irq, struct pcmcia_device *handle, int is_mmio)
+static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
{
hw_regs_t hw;
memset(&hw, 0, sizeof(hw));
@@ -163,19 +154,7 @@ static int idecs_register(unsigned long io, unsigned long ctl,
hw.irq = irq;
hw.chipset = ide_pci;
hw.dev = &handle->dev;
-
- if(is_mmio)
- return ide_register_hw_with_fixup(&hw, NULL, idecs_mmio_fixup);
- else
- return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
-}
-
-void outb_io(unsigned char value, unsigned long port) {
- outb(value, port);
-}
-
-void outb_mem(unsigned char value, unsigned long port) {
- writeb(value, (void __iomem *) port);
+ return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
}
/*======================================================================
@@ -201,8 +180,7 @@ static int ide_config(struct pcmcia_device *link)
} *stk = NULL;
cistpl_cftable_entry_t *cfg;
int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
- unsigned long io_base, ctl_base, is_mmio, try_slave;
- void (*my_outb)(unsigned char, unsigned long);
+ unsigned long io_base, ctl_base;
DEBUG(0, "ide_config(0x%p)\n", link);
@@ -232,7 +210,7 @@ static int ide_config(struct pcmcia_device *link)
/* Not sure if this is right... look up the current Vcc */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
- pass = io_base = ctl_base = is_mmio = try_slave = 0;
+ pass = io_base = ctl_base = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@@ -280,45 +258,11 @@ static int ide_config(struct pcmcia_device *link)
goto next_entry;
io_base = link->io.BasePort1;
ctl_base = link->io.BasePort1 + 0x0e;
-
- if (io->win[0].len >= 0x20)
- try_slave = 1;
-
} else goto next_entry;
/* If we've got this far, we're done */
break;
}
- if ((cfg->mem.nwin > 0) || (stk->dflt.mem.nwin > 0)) {
- win_req_t req;
- memreq_t map;
- cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &stk->dflt.mem;
-
- if (mem->win[0].len < 16)
- goto next_entry;
-
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
- req.Attributes |= WIN_ENABLE;
- req.Base = mem->win[0].host_addr;
- req.Size = 0;
-
- req.AccessSpeed = 0;
- if (pcmcia_request_window(&link, &req, &link->win) != 0)
- goto next_entry;
- map.Page = 0; map.CardOffset = mem->win[0].card_addr;
- if (pcmcia_map_mem_page(link->win, &map) != 0)
- goto next_entry;
-
- io_base = (unsigned long) ioremap(req.Base, req.Size);
- ctl_base = io_base + 0x0e;
- is_mmio = 1;
-
- if (mem->win[0].len >= 0x20)
- try_slave = 1;
-
- break;
- }
-
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
@@ -334,26 +278,21 @@ static int ide_config(struct pcmcia_device *link)
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
- if(is_mmio)
- my_outb = outb_mem;
- else
- my_outb = outb_io;
-
/* disable drive interrupts during IDE probe */
- my_outb(0x02, ctl_base);
+ outb(0x02, ctl_base);
/* special setup for KXLC005 card */
if (is_kme)
- my_outb(0x81, ctl_base+1);
+ outb(0x81, ctl_base+1);
/* retry registration in case device is still spinning up */
for (hd = -1, i = 0; i < 10; i++) {
- hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link, is_mmio);
+ hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
if (hd >= 0) break;
- if (try_slave) {
- my_outb(0x02, ctl_base + 0x10);
+ if (link->io.NumPorts1 == 0x20) {
+ outb(0x02, ctl_base + 0x10);
hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
- link->irq.AssignedIRQ, link, is_mmio);
+ link->irq.AssignedIRQ, link);
if (hd >= 0) {
io_base += 0x10;
ctl_base += 0x10;
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index f82e82109728..2f962cfa3f7f 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -212,6 +212,9 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
(!(PCI_FUNC(dev->devfn) & 1)))
goto out;
+ if (dev->vendor == PCI_VENDOR_ID_JMICRON && PCI_FUNC(dev->devfn) != 1)
+ goto out;
+
pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
@@ -239,6 +242,11 @@ static struct pci_device_id generic_pci_tbl[] = {
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
{ PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
/* Must come last. If you add entries adjust this table appropriately and the init_one code */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
{ 0, },
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index a98c5e38bbbc..93ff941c48f1 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -297,7 +297,7 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
#ifdef __ISAPNP__
-static struct isapnp_device_id asus_ids[] __initdata = {
+static struct isapnp_device_id asus_ids[] __devinitdata = {
{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
(unsigned long) "Asus1688 PnP" },
@@ -313,11 +313,11 @@ static struct isapnp_device_id asus_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &asus_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &asus_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_asuscom(struct IsdnCard *card)
{
int bytecnt;
diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
index 9a8b02557ff9..729e906bdc61 100644
--- a/drivers/isdn/hisax/avm_a1.c
+++ b/drivers/isdn/hisax/avm_a1.c
@@ -178,7 +178,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-int __init
+int __devinit
setup_avm_a1(struct IsdnCard *card)
{
u_char val;
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 04f5917bf5a1..369afd3a3a4b 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -639,7 +639,7 @@ clear_pending_hdlc_ints(struct IsdnCardState *cs)
}
#endif /* 0 */
-static void __init
+static void
inithdlc(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_hdlc;
@@ -727,13 +727,13 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
#ifdef CONFIG_PCI
-static struct pci_dev *dev_avm __initdata = NULL;
+static struct pci_dev *dev_avm __devinitdata = NULL;
#endif
#ifdef __ISAPNP__
-static struct pnp_card *pnp_avm_c __initdata = NULL;
+static struct pnp_card *pnp_avm_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_avm_pcipnp(struct IsdnCard *card)
{
u_int val, ver;
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index 3cf1f2421789..87a630128a6c 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -255,9 +255,9 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0);
}
-static struct pci_dev *dev_a4t __initdata = NULL;
+static struct pci_dev *dev_a4t __devinitdata = NULL;
-int __init
+int __devinit
setup_bkm_a4t(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 15681f3e73b8..dae090a9a489 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -260,7 +260,7 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0);
}
-static int __init
+static int __devinit
sct_alloc_io(u_int adr, u_int len)
{
if (!request_region(adr, len, "scitel")) {
@@ -272,16 +272,16 @@ sct_alloc_io(u_int adr, u_int len)
return(0);
}
-static struct pci_dev *dev_a8 __initdata = NULL;
-static u16 sub_vendor_id __initdata = 0;
-static u16 sub_sys_id __initdata = 0;
-static u_char pci_bus __initdata = 0;
-static u_char pci_device_fn __initdata = 0;
-static u_char pci_irq __initdata = 0;
+static struct pci_dev *dev_a8 __devinitdata = NULL;
+static u16 sub_vendor_id __devinitdata = 0;
+static u16 sub_sys_id __devinitdata = 0;
+static u_char pci_bus __devinitdata = 0;
+static u_char pci_device_fn __devinitdata = 0;
+static u_char pci_irq __devinitdata = 0;
#endif /* CONFIG_PCI */
-int __init
+int __devinit
setup_sct_quadro(struct IsdnCard *card)
{
#ifdef CONFIG_PCI
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 5333be5d2c47..e10350360f2f 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1875,7 +1875,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if)
#ifdef CONFIG_PCI
#include <linux/pci.h>
-static struct pci_device_id hisax_pci_tbl[] __initdata = {
+static struct pci_device_id hisax_pci_tbl[] __devinitdata = {
#ifdef CONFIG_HISAX_FRITZPCI
{PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID},
#endif
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 323a02ef3844..e294fa3918f3 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -887,13 +887,13 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_diva __initdata = NULL;
-static struct pci_dev *dev_diva_u __initdata = NULL;
-static struct pci_dev *dev_diva201 __initdata = NULL;
-static struct pci_dev *dev_diva202 __initdata = NULL;
+static struct pci_dev *dev_diva __devinitdata = NULL;
+static struct pci_dev *dev_diva_u __devinitdata = NULL;
+static struct pci_dev *dev_diva201 __devinitdata = NULL;
+static struct pci_dev *dev_diva202 __devinitdata = NULL;
#ifdef __ISAPNP__
-static struct isapnp_device_id diva_ids[] __initdata = {
+static struct isapnp_device_id diva_ids[] __devinitdata = {
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
(unsigned long) "Diva picola" },
@@ -915,12 +915,12 @@ static struct isapnp_device_id diva_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &diva_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_diva(struct IsdnCard *card)
{
int bytecnt = 8;
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index 8fcbe2e7d765..76c7d29d1b2f 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -301,10 +301,10 @@ enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
-static struct pci_dev *dev_netjet __initdata = NULL;
+static struct pci_dev *dev_netjet __devinitdata = NULL;
/* called by config.c */
-int __init
+int __devinit
setup_enternow_pci(struct IsdnCard *card)
{
int bytecnt;
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index 3e7d92303582..fe2937267777 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -484,7 +484,7 @@ reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
return 1;
}
-static int __init
+static int __devinit
setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
{
printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
@@ -532,9 +532,9 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
return (0);
}
-static struct pci_dev *dev_tel __initdata = NULL;
+static struct pci_dev *dev_tel __devinitdata = NULL;
-static int __init
+static int __devinit
setup_gazelpci(struct IsdnCardState *cs)
{
u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
@@ -621,7 +621,7 @@ setup_gazelpci(struct IsdnCardState *cs)
return (0);
}
-int __init
+int __devinit
setup_gazel(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 0f967b3df79d..3a5ca8a68fc4 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1703,7 +1703,7 @@ hfc4s8s_module_init(void)
/* driver module exit : */
/* release the HFC-4s/8s hardware */
/*************************************/
-static void
+static void __exit
hfc4s8s_module_exit(void)
{
pci_unregister_driver(&hfc4s8s_driver);
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index 637a261c9312..6360e8214720 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -1015,7 +1015,7 @@ hfc_dbusy_timer(struct IsdnCardState *cs)
{
}
-static unsigned int __init
+static unsigned int
*init_send_hfcd(int cnt)
{
int i, *send;
@@ -1030,7 +1030,7 @@ static unsigned int __init
return(send);
}
-void __init
+void
init2bds0(struct IsdnCardState *cs)
{
cs->setstack_d = setstack_hfcd;
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index c964539cc43e..d0520ad30677 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -551,7 +551,7 @@ setstack_hfc(struct PStack *st, struct BCState *bcs)
return (0);
}
-static void __init
+static void
init_send(struct BCState *bcs)
{
int i;
@@ -565,7 +565,7 @@ init_send(struct BCState *bcs)
bcs->hw.hfc.send[i] = 0x1fff;
}
-void __init
+void
inithfc(struct IsdnCardState *cs)
{
init_send(&cs->bcs[0]);
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 7241e73879ba..1df60ca9481f 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1581,7 +1581,7 @@ hfcpci_bh(struct IsdnCardState *cs)
/********************************/
/* called for card init message */
/********************************/
-static void __init
+static void
inithfcpci(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_2b;
@@ -1638,11 +1638,11 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
/* this variable is used as card index when more than one cards are present */
-static struct pci_dev *dev_hfcpci __initdata = NULL;
+static struct pci_dev *dev_hfcpci __devinitdata = NULL;
#endif /* CONFIG_PCI */
-int __init
+int __devinit
setup_hfcpci(struct IsdnCard *card)
{
u_long flags;
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 86ab1c13f6b1..4e7f472877e9 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -139,7 +139,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
#ifdef __ISAPNP__
-static struct isapnp_device_id hfc_ids[] __initdata = {
+static struct isapnp_device_id hfc_ids[] __devinitdata = {
{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
(unsigned long) "Acer P10" },
@@ -164,11 +164,11 @@ static struct isapnp_device_id hfc_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_hfcs(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index c615752b96aa..2cf7b665609e 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -24,10 +24,10 @@
#define DBUSY_TIMER_VALUE 80
#define ARCOFI_USE 0
-static char *ICCVer[] __initdata =
+static char *ICCVer[] =
{"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
-void __init
+void
ICCVersion(struct IsdnCardState *cs, char *s)
{
int val;
@@ -613,7 +613,7 @@ dbusy_timer_handler(struct IsdnCardState *cs)
}
}
-void __init
+void
initicc(struct IsdnCardState *cs)
{
cs->setstack_d = setstack_icc;
@@ -646,7 +646,7 @@ initicc(struct IsdnCardState *cs)
ph_command(cs, ICC_CMD_DI);
}
-void __init
+void
clear_pending_icc_ints(struct IsdnCardState *cs)
{
int val, eval;
diff --git a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h
index b3bb3d5de532..e7f593967e43 100644
--- a/drivers/isdn/hisax/icc.h
+++ b/drivers/isdn/hisax/icc.h
@@ -65,7 +65,7 @@
#define ICC_IND_AIL 0xE
#define ICC_IND_DC 0xF
-extern void __init ICCVersion(struct IsdnCardState *cs, char *s);
+extern void ICCVersion(struct IsdnCardState *cs, char *s);
extern void initicc(struct IsdnCardState *cs);
extern void icc_interrupt(struct IsdnCardState *cs, u_char val);
extern void clear_pending_icc_ints(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
index df5fc92a89b2..00afd5538909 100644
--- a/drivers/isdn/hisax/ipacx.c
+++ b/drivers/isdn/hisax/ipacx.c
@@ -38,8 +38,8 @@ static void dbusy_timer_handler(struct IsdnCardState *cs);
static void dch_empty_fifo(struct IsdnCardState *cs, int count);
static void dch_fill_fifo(struct IsdnCardState *cs);
static inline void dch_int(struct IsdnCardState *cs);
-static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
-static void __devinit dch_init(struct IsdnCardState *cs);
+static void dch_setstack(struct PStack *st, struct IsdnCardState *cs);
+static void dch_init(struct IsdnCardState *cs);
static void bch_l2l1(struct PStack *st, int pr, void *arg);
static void bch_empty_fifo(struct BCState *bcs, int count);
static void bch_fill_fifo(struct BCState *bcs);
@@ -48,8 +48,8 @@ static void bch_mode(struct BCState *bcs, int mode, int bc);
static void bch_close_state(struct BCState *bcs);
static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs);
static int bch_setstack(struct PStack *st, struct BCState *bcs);
-static void __devinit bch_init(struct IsdnCardState *cs, int hscx);
-static void __init clear_pending_ints(struct IsdnCardState *cs);
+static void bch_init(struct IsdnCardState *cs, int hscx);
+static void clear_pending_ints(struct IsdnCardState *cs);
//----------------------------------------------------------
// Issue Layer 1 command to chip
@@ -408,7 +408,7 @@ dch_int(struct IsdnCardState *cs)
//----------------------------------------------------------
//----------------------------------------------------------
-static void __devinit
+static void
dch_setstack(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.l1hw = dch_l2l1;
@@ -416,7 +416,7 @@ dch_setstack(struct PStack *st, struct IsdnCardState *cs)
//----------------------------------------------------------
//----------------------------------------------------------
-static void __devinit
+static void
dch_init(struct IsdnCardState *cs)
{
printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n");
@@ -823,7 +823,7 @@ bch_setstack(struct PStack *st, struct BCState *bcs)
//----------------------------------------------------------
//----------------------------------------------------------
-static void __devinit
+static void
bch_init(struct IsdnCardState *cs, int hscx)
{
cs->bcs[hscx].BC_SetStack = bch_setstack;
@@ -861,7 +861,7 @@ interrupt_ipacx(struct IsdnCardState *cs)
//----------------------------------------------------------
// Clears chip interrupt status
//----------------------------------------------------------
-static void __init
+static void
clear_pending_ints(struct IsdnCardState *cs)
{
int ista;
@@ -883,7 +883,7 @@ clear_pending_ints(struct IsdnCardState *cs)
// Does chip configuration work
// Work to do depends on bit mask in part
//----------------------------------------------------------
-void __init
+void
init_ipacx(struct IsdnCardState *cs, int part)
{
if (part &1) { // initialise chip
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
index 33747afc984d..715a1a8cd694 100644
--- a/drivers/isdn/hisax/isurf.c
+++ b/drivers/isdn/hisax/isurf.c
@@ -196,10 +196,10 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
}
#ifdef __ISAPNP__
-static struct pnp_card *pnp_c __initdata = NULL;
+static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_isurf(struct IsdnCard *card)
{
int ver;
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index 908a7e144421..39717506c678 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -210,7 +210,7 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
#ifdef __ISAPNP__
-static struct isapnp_device_id itk_ids[] __initdata = {
+static struct isapnp_device_id itk_ids[] __devinitdata = {
{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
(unsigned long) "ITK micro 2" },
@@ -220,12 +220,12 @@ static struct isapnp_device_id itk_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &itk_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &itk_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_ix1micro(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index 2659fecc2674..43d61d1bc5b6 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -19,7 +19,7 @@
#include <linux/interrupt.h>
-int __init
+int
JadeVersion(struct IsdnCardState *cs, char *s)
{
int ver,i;
@@ -253,7 +253,7 @@ setstack_jade(struct PStack *st, struct BCState *bcs)
return (0);
}
-void __init
+void
clear_pending_jade_ints(struct IsdnCardState *cs)
{
int val;
@@ -279,7 +279,7 @@ clear_pending_jade_ints(struct IsdnCardState *cs)
cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
}
-void __init
+void
initjade(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_jade;
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index fe11f226b285..8c82519593a8 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -189,7 +189,7 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-int __init
+int __devinit
setup_mic(struct IsdnCard *card)
{
int bytecnt;
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index 47a47ef0968b..38f648f9b0ed 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -909,7 +909,7 @@ setstack_tiger(struct PStack *st, struct BCState *bcs)
}
-void __init
+void
inittiger(struct IsdnCardState *cs)
{
if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index 79a97b1c3812..489022bdef7b 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -232,12 +232,12 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *niccy_dev __initdata = NULL;
+static struct pci_dev *niccy_dev __devinitdata = NULL;
#ifdef __ISAPNP__
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
-int __init
+int __devinit
setup_niccy(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index e5b900a6fa0b..80025fd890f4 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -148,9 +148,9 @@ NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_netjet __initdata = NULL;
+static struct pci_dev *dev_netjet __devinitdata = NULL;
-int __init
+int __devinit
setup_netjet_s(struct IsdnCard *card)
{
int bytecnt,cfg;
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 7002b09936d4..37497162d539 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -128,9 +128,9 @@ NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_netjet __initdata = NULL;
+static struct pci_dev *dev_netjet __devinitdata = NULL;
-int __init
+int __devinit
setup_netjet_u(struct IsdnCard *card)
{
int bytecnt;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index 7b63085ea6e5..e76042d323ea 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -211,7 +211,7 @@ S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-int __init
+int __devinit
setup_s0box(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index 821776e1561a..d943d365890b 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -241,7 +241,7 @@ saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
-int __init
+int __devinit
setup_saphir(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index cdf35dc564c4..a49b694eb730 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -184,7 +184,7 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static int __init
+static int __devinit
get_io_range(struct IsdnCardState *cs)
{
int i, j, adr;
@@ -209,7 +209,7 @@ get_io_range(struct IsdnCardState *cs)
}
}
-int __init
+int __devinit
setup_sportster(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index a2b1816af37a..e94dc6f5bd62 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -261,7 +261,7 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-int __init
+int __devinit
setup_TeleInt(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index 2b7df8f98233..f94af0930a17 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -265,7 +265,7 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-int __init
+int __devinit
setup_teles0(struct IsdnCard *card)
{
u_char val;
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index 9382cdf04d8d..dca446865f24 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -284,9 +284,9 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_tel __initdata = NULL;
+static struct pci_dev *dev_tel __devinitdata = NULL;
-int __init
+int __devinit
setup_telespci(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index 6c68419c05ff..0595293b8659 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -44,11 +44,11 @@ static const char *w6692_revision = "$Revision: 1.18.2.4 $";
#define DBUSY_TIMER_VALUE 80
-static char *W6692Ver[] __initdata =
+static char *W6692Ver[] =
{"W6692 V00", "W6692 V01", "W6692 V10",
"W6692 V11"};
-static void __init
+static void
W6692Version(struct IsdnCardState *cs, char *s)
{
int val;
@@ -897,7 +897,7 @@ static void resetW6692(struct IsdnCardState *cs)
}
}
-static void __init initW6692(struct IsdnCardState *cs, int part)
+static void initW6692(struct IsdnCardState *cs, int part)
{
if (part & 1) {
cs->setstack_d = setstack_W6692;
@@ -992,9 +992,9 @@ w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static int id_idx ;
-static struct pci_dev *dev_w6692 __initdata = NULL;
+static struct pci_dev *dev_w6692 __devinitdata = NULL;
-int __init
+int __devinit
setup_w6692(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 9f6c6375ff75..c3d79eef9e32 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1059,7 +1059,7 @@ isdn_info_update(void)
static ssize_t
isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
{
- uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ uint minor = iminor(file->f_dentry->d_inode);
int len = 0;
int drvidx;
int chidx;
@@ -1163,7 +1163,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
static ssize_t
isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
{
- uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ uint minor = iminor(file->f_dentry->d_inode);
int drvidx;
int chidx;
int retval;
@@ -1225,7 +1225,7 @@ static unsigned int
isdn_poll(struct file *file, poll_table * wait)
{
unsigned int mask = 0;
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned int minor = iminor(file->f_dentry->d_inode);
int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
lock_kernel();
@@ -1266,7 +1266,7 @@ isdn_poll(struct file *file, poll_table * wait)
static int
isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
{
- uint minor = MINOR(inode->i_rdev);
+ uint minor = iminor(inode);
isdn_ctrl c;
int drvidx;
int chidx;
@@ -1717,7 +1717,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
static int
isdn_open(struct inode *ino, struct file *filep)
{
- uint minor = MINOR(ino->i_rdev);
+ uint minor = iminor(ino);
int drvidx;
int chidx;
int retval = -ENODEV;
@@ -1779,7 +1779,7 @@ isdn_open(struct inode *ino, struct file *filep)
static int
isdn_close(struct inode *ino, struct file *filep)
{
- uint minor = MINOR(ino->i_rdev);
+ uint minor = iminor(ino);
lock_kernel();
if (minor == ISDN_MINOR_STATUS) {
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 29e7667ec962..119412d6bd15 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -667,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
if (is->debug & 0x2)
printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
- MINOR(file->f_dentry->d_inode->i_rdev));
+ iminor(file->f_dentry->d_inode));
/* just registers wait_queue hook. This doesn't really wait. */
poll_wait(file, &is->wq, wait);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 96509989e921..9c39b98d5a5b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -69,6 +69,13 @@ config LEDS_AMS_DELTA
help
This option enables support for the LEDs on Amstrad Delta (E3).
+config LEDS_NET48XX
+ tristate "LED Support for Soekris net48xx series Error LED"
+ depends on LEDS_CLASS && SCx200_GPIO
+ help
+ This option enables support for the Soekris net4801 and net4826 error
+ LED.
+
comment "LED Triggers"
config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 88d3b6eaa6a2..6aa2aed7539d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o
obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
+obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
new file mode 100644
index 000000000000..35ee52f9b79e
--- /dev/null
+++ b/drivers/leds/leds-net48xx.c
@@ -0,0 +1,115 @@
+/*
+ * LEDs driver for Soekris net48xx
+ *
+ * Copyright (C) 2006 Chris Boot <bootc@bootc.net>
+ *
+ * Based on leds-ams-delta.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <linux/scx200_gpio.h>
+
+#define NET48XX_ERROR_LED_GPIO 20
+
+static struct platform_device *pdev;
+
+static void net48xx_error_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value)
+ scx200_gpio_set_high(NET48XX_ERROR_LED_GPIO);
+ else
+ scx200_gpio_set_low(NET48XX_ERROR_LED_GPIO);
+}
+
+static struct led_classdev net48xx_error_led = {
+ .name = "net48xx:error",
+ .brightness_set = net48xx_error_led_set,
+};
+
+#ifdef CONFIG_PM
+static int net48xx_led_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ led_classdev_suspend(&net48xx_error_led);
+ return 0;
+}
+
+static int net48xx_led_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&net48xx_error_led);
+ return 0;
+}
+#else
+#define net48xx_led_suspend NULL
+#define net48xx_led_resume NULL
+#endif
+
+static int net48xx_led_probe(struct platform_device *pdev)
+{
+ return led_classdev_register(&pdev->dev, &net48xx_error_led);
+}
+
+static int net48xx_led_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&net48xx_error_led);
+ return 0;
+}
+
+static struct platform_driver net48xx_led_driver = {
+ .driver.owner = THIS_MODULE,
+ .probe = net48xx_led_probe,
+ .remove = net48xx_led_remove,
+ .suspend = net48xx_led_suspend,
+ .resume = net48xx_led_resume,
+ .driver = {
+ .name = "net48xx-led",
+ },
+};
+
+static int __init net48xx_led_init(void)
+{
+ int ret;
+
+ if (!scx200_gpio_present()) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = platform_driver_register(&net48xx_led_driver);
+ if (ret < 0)
+ goto out;
+
+ pdev = platform_device_register_simple("net48xx-led", -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ ret = PTR_ERR(pdev);
+ platform_driver_unregister(&net48xx_led_driver);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void __exit net48xx_led_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&net48xx_led_driver);
+}
+
+module_init(net48xx_led_init);
+module_exit(net48xx_led_exit);
+
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_DESCRIPTION("Soekris net48xx LED driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 54f3f6b94efc..f5fe7fb4b3ad 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -113,7 +113,10 @@ config PMAC_MEDIABAY
config PMAC_BACKLIGHT
bool "Backlight control for LCD screens"
- depends on ADB_PMU && (BROKEN || !PPC64)
+ depends on ADB_PMU && FB = y && (BROKEN || !PPC64)
+ select FB_BACKLIGHT
+ select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_LCD_SUPPORT
help
Say Y here to enable Macintosh specific extensions of the generic
backlight code. With this enabled, the brightness keys on older
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 80c0c665b5f6..82657bc86d19 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -330,7 +330,7 @@ static void macio_create_fixup_irq(struct macio_dev *dev, int index,
{
unsigned int irq;
- irq = irq_create_mapping(NULL, line, 0);
+ irq = irq_create_mapping(NULL, line);
if (irq != NO_IRQ) {
dev->interrupt[index].start = irq;
dev->interrupt[index].flags = IORESOURCE_IRQ;
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index f139a74696fe..00ef46898147 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -75,9 +75,11 @@ struct smu_device {
struct of_device *of_dev;
int doorbell; /* doorbell gpio */
u32 __iomem *db_buf; /* doorbell buffer */
- int db_irq;
+ struct device_node *db_node;
+ unsigned int db_irq;
int msg;
- int msg_irq;
+ struct device_node *msg_node;
+ unsigned int msg_irq;
struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
u32 cmd_buf_abs; /* command buffer absolute */
struct list_head cmd_list;
@@ -93,6 +95,7 @@ struct smu_device {
*/
static struct smu_device *smu;
static DEFINE_MUTEX(smu_part_access);
+static int smu_irq_inited;
static void smu_i2c_retry(unsigned long data);
@@ -257,6 +260,10 @@ int smu_queue_cmd(struct smu_cmd *cmd)
smu_start_cmd();
spin_unlock_irqrestore(&smu->lock, flags);
+ /* Workaround for early calls when irq isn't available */
+ if (!smu_irq_inited || smu->db_irq == NO_IRQ)
+ smu_spinwait_cmd(cmd);
+
return 0;
}
EXPORT_SYMBOL(smu_queue_cmd);
@@ -478,14 +485,15 @@ int __init smu_init (void)
smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
- np = of_find_node_by_name(NULL, "smu-doorbell");
- if (np == NULL) {
+ smu->db_node = of_find_node_by_name(NULL, "smu-doorbell");
+ if (smu->db_node == NULL) {
printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n");
goto fail;
}
- data = (u32 *)get_property(np, "reg", NULL);
+ data = (u32 *)get_property(smu->db_node, "reg", NULL);
if (data == NULL) {
- of_node_put(np);
+ of_node_put(smu->db_node);
+ smu->db_node = NULL;
printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
goto fail;
}
@@ -497,25 +505,21 @@ int __init smu_init (void)
smu->doorbell = *data;
if (smu->doorbell < 0x50)
smu->doorbell += 0x50;
- smu->db_irq = irq_of_parse_and_map(np, 0);
-
- of_node_put(np);
/* Now look for the smu-interrupt GPIO */
do {
- np = of_find_node_by_name(NULL, "smu-interrupt");
- if (np == NULL)
+ smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt");
+ if (smu->msg_node == NULL)
break;
- data = (u32 *)get_property(np, "reg", NULL);
+ data = (u32 *)get_property(smu->msg_node, "reg", NULL);
if (data == NULL) {
- of_node_put(np);
+ of_node_put(smu->msg_node);
+ smu->msg_node = NULL;
break;
}
smu->msg = *data;
if (smu->msg < 0x50)
smu->msg += 0x50;
- smu->msg_irq = irq_of_parse_and_map(np, 0);
- of_node_put(np);
} while(0);
/* Doorbell buffer is currently hard-coded, I didn't find a proper
@@ -547,6 +551,19 @@ static int smu_late_init(void)
smu->i2c_timer.function = smu_i2c_retry;
smu->i2c_timer.data = (unsigned long)smu;
+ if (smu->db_node) {
+ smu->db_irq = irq_of_parse_and_map(smu->db_node, 0);
+ if (smu->db_irq == NO_IRQ)
+ printk(KERN_ERR "smu: failed to map irq for node %s\n",
+ smu->db_node->full_name);
+ }
+ if (smu->msg_node) {
+ smu->msg_irq = irq_of_parse_and_map(smu->msg_node, 0);
+ if (smu->msg_irq == NO_IRQ)
+ printk(KERN_ERR "smu: failed to map irq for node %s\n",
+ smu->msg_node->full_name);
+ }
+
/*
* Try to request the interrupts
*/
@@ -571,6 +588,7 @@ static int smu_late_init(void)
}
}
+ smu_irq_inited = 1;
return 0;
}
/* This has to be before arch_initcall as the low i2c stuff relies on the
@@ -742,6 +760,11 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
if (fail && --cmd->retries > 0) {
DPRINTK("SMU: i2c failure, starting timer...\n");
BUG_ON(cmd != smu->cmd_i2c_cur);
+ if (!smu_irq_inited) {
+ mdelay(5);
+ smu_i2c_retry(0);
+ return;
+ }
mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
return;
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e4e161372a3e..b6d16022a53e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -110,7 +110,7 @@ static ctl_table raid_table[] = {
.procname = "speed_limit_min",
.data = &sysctl_speed_limit_min,
.maxlen = sizeof(int),
- .mode = 0644,
+ .mode = S_IRUGO|S_IWUSR,
.proc_handler = &proc_dointvec,
},
{
@@ -118,7 +118,7 @@ static ctl_table raid_table[] = {
.procname = "speed_limit_max",
.data = &sysctl_speed_limit_max,
.maxlen = sizeof(int),
- .mode = 0644,
+ .mode = S_IRUGO|S_IWUSR,
.proc_handler = &proc_dointvec,
},
{ .ctl_name = 0 }
@@ -129,7 +129,7 @@ static ctl_table raid_dir_table[] = {
.ctl_name = DEV_RAID,
.procname = "raid",
.maxlen = 0,
- .mode = 0555,
+ .mode = S_IRUGO|S_IXUGO,
.child = raid_table,
},
{ .ctl_name = 0 }
@@ -1062,6 +1062,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
if (rdev->sb_size & bmask)
rdev-> sb_size = (rdev->sb_size | bmask)+1;
+ if (sb->level == cpu_to_le32(LEVEL_MULTIPATH))
+ rdev->desc_nr = -1;
+ else
+ rdev->desc_nr = le32_to_cpu(sb->dev_number);
+
if (refdev == 0)
ret = 1;
else {
@@ -1171,7 +1176,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
}
if (mddev->level != LEVEL_MULTIPATH) {
int role;
- rdev->desc_nr = le32_to_cpu(sb->dev_number);
role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
switch(role) {
case 0xffff: /* spare */
@@ -1779,8 +1783,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
}
return err ? err : len;
}
-static struct rdev_sysfs_entry
-rdev_state = __ATTR(state, 0644, state_show, state_store);
+static struct rdev_sysfs_entry rdev_state =
+__ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store);
static ssize_t
super_show(mdk_rdev_t *rdev, char *page)
@@ -1811,7 +1815,7 @@ errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
return -EINVAL;
}
static struct rdev_sysfs_entry rdev_errors =
-__ATTR(errors, 0644, errors_show, errors_store);
+__ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store);
static ssize_t
slot_show(mdk_rdev_t *rdev, char *page)
@@ -1845,7 +1849,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
static struct rdev_sysfs_entry rdev_slot =
-__ATTR(slot, 0644, slot_show, slot_store);
+__ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store);
static ssize_t
offset_show(mdk_rdev_t *rdev, char *page)
@@ -1867,7 +1871,7 @@ offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
}
static struct rdev_sysfs_entry rdev_offset =
-__ATTR(offset, 0644, offset_show, offset_store);
+__ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store);
static ssize_t
rdev_size_show(mdk_rdev_t *rdev, char *page)
@@ -1891,7 +1895,7 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
}
static struct rdev_sysfs_entry rdev_size =
-__ATTR(size, 0644, rdev_size_show, rdev_size_store);
+__ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store);
static struct attribute *rdev_default_attrs[] = {
&rdev_state.attr,
@@ -1922,6 +1926,8 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
if (!entry->store)
return -EIO;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return entry->store(rdev, page, length);
}
@@ -2128,7 +2134,7 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
return len;
}
static struct md_sysfs_entry md_safe_delay =
-__ATTR(safe_mode_delay, 0644,safe_delay_show, safe_delay_store);
+__ATTR(safe_mode_delay, S_IRUGO|S_IWUSR,safe_delay_show, safe_delay_store);
static ssize_t
level_show(mddev_t *mddev, char *page)
@@ -2163,7 +2169,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
}
static struct md_sysfs_entry md_level =
-__ATTR(level, 0644, level_show, level_store);
+__ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
static ssize_t
@@ -2188,7 +2194,7 @@ layout_store(mddev_t *mddev, const char *buf, size_t len)
return len;
}
static struct md_sysfs_entry md_layout =
-__ATTR(layout, 0655, layout_show, layout_store);
+__ATTR(layout, S_IRUGO|S_IWUSR, layout_show, layout_store);
static ssize_t
@@ -2219,7 +2225,7 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
return rv ? rv : len;
}
static struct md_sysfs_entry md_raid_disks =
-__ATTR(raid_disks, 0644, raid_disks_show, raid_disks_store);
+__ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store);
static ssize_t
chunk_size_show(mddev_t *mddev, char *page)
@@ -2243,7 +2249,7 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
return len;
}
static struct md_sysfs_entry md_chunk_size =
-__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
+__ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store);
static ssize_t
resync_start_show(mddev_t *mddev, char *page)
@@ -2267,7 +2273,7 @@ resync_start_store(mddev_t *mddev, const char *buf, size_t len)
return len;
}
static struct md_sysfs_entry md_resync_start =
-__ATTR(resync_start, 0644, resync_start_show, resync_start_store);
+__ATTR(resync_start, S_IRUGO|S_IWUSR, resync_start_show, resync_start_store);
/*
* The array state can be:
@@ -2437,7 +2443,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
else
return len;
}
-static struct md_sysfs_entry md_array_state = __ATTR(array_state, 0644, array_state_show, array_state_store);
+static struct md_sysfs_entry md_array_state =
+__ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
static ssize_t
null_show(mddev_t *mddev, char *page)
@@ -2497,7 +2504,7 @@ new_dev_store(mddev_t *mddev, const char *buf, size_t len)
}
static struct md_sysfs_entry md_new_device =
-__ATTR(new_dev, 0200, null_show, new_dev_store);
+__ATTR(new_dev, S_IWUSR, null_show, new_dev_store);
static ssize_t
size_show(mddev_t *mddev, char *page)
@@ -2535,7 +2542,7 @@ size_store(mddev_t *mddev, const char *buf, size_t len)
}
static struct md_sysfs_entry md_size =
-__ATTR(component_size, 0644, size_show, size_store);
+__ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store);
/* Metdata version.
@@ -2583,7 +2590,7 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
}
static struct md_sysfs_entry md_metadata =
-__ATTR(metadata_version, 0644, metadata_show, metadata_store);
+__ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
static ssize_t
action_show(mddev_t *mddev, char *page)
@@ -2651,12 +2658,11 @@ mismatch_cnt_show(mddev_t *mddev, char *page)
(unsigned long long) mddev->resync_mismatches);
}
-static struct md_sysfs_entry
-md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
+static struct md_sysfs_entry md_scan_mode =
+__ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
-static struct md_sysfs_entry
-md_mismatches = __ATTR_RO(mismatch_cnt);
+static struct md_sysfs_entry md_mismatches = __ATTR_RO(mismatch_cnt);
static ssize_t
sync_min_show(mddev_t *mddev, char *page)
@@ -2715,15 +2721,14 @@ static ssize_t
sync_speed_show(mddev_t *mddev, char *page)
{
unsigned long resync, dt, db;
- resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+ resync = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active));
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
db = resync - (mddev->resync_mark_cnt);
return sprintf(page, "%ld\n", db/dt/2); /* K/sec */
}
-static struct md_sysfs_entry
-md_sync_speed = __ATTR_RO(sync_speed);
+static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed);
static ssize_t
sync_completed_show(mddev_t *mddev, char *page)
@@ -2739,8 +2744,7 @@ sync_completed_show(mddev_t *mddev, char *page)
return sprintf(page, "%lu / %lu\n", resync, max_blocks);
}
-static struct md_sysfs_entry
-md_sync_completed = __ATTR_RO(sync_completed);
+static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
static ssize_t
suspend_lo_show(mddev_t *mddev, char *page)
@@ -2857,6 +2861,8 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
if (!entry->store)
return -EIO;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
rv = mddev_lock(mddev);
if (!rv) {
rv = entry->store(mddev, page, length);
@@ -3091,7 +3097,6 @@ static int do_md_run(mddev_t * mddev)
}
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- md_wakeup_thread(mddev->thread);
if (mddev->sb_dirty)
md_update_sb(mddev);
@@ -3112,7 +3117,7 @@ static int do_md_run(mddev_t * mddev)
* start recovery here. If we leave it to md_check_recovery,
* it will remove the drives and not do the right thing
*/
- if (mddev->degraded) {
+ if (mddev->degraded && !mddev->sync_thread) {
struct list_head *rtmp;
int spares = 0;
ITERATE_RDEV(mddev,rdev,rtmp)
@@ -3133,10 +3138,11 @@ static int do_md_run(mddev_t * mddev)
mdname(mddev));
/* leave the spares where they are, it shouldn't hurt */
mddev->recovery = 0;
- } else
- md_wakeup_thread(mddev->sync_thread);
+ }
}
}
+ md_wakeup_thread(mddev->thread);
+ md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
mddev->changed = 1;
md_new_event(mddev);
@@ -4586,6 +4592,8 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
__builtin_return_address(0),__builtin_return_address(1),
__builtin_return_address(2),__builtin_return_address(3));
*/
+ if (!mddev->pers)
+ return;
if (!mddev->pers->error_handler)
return;
mddev->pers->error_handler(mddev,rdev);
@@ -4683,12 +4691,13 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
*/
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
- db = resync - (mddev->resync_mark_cnt/2);
- rt = (dt * ((unsigned long)(max_blocks-resync) / (db/100+1)))/100;
+ db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active))
+ - mddev->resync_mark_cnt;
+ rt = (dt * ((unsigned long)(max_blocks-resync) / (db/2/100+1)))/100;
seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
- seq_printf(seq, " speed=%ldK/sec", db/dt);
+ seq_printf(seq, " speed=%ldK/sec", db/2/dt);
}
static void *md_seq_start(struct seq_file *seq, loff_t *pos)
@@ -5199,6 +5208,7 @@ void md_do_sync(mddev_t *mddev)
j += sectors;
if (j>1) mddev->curr_resync = j;
+ mddev->curr_mark_cnt = io_sectors;
if (last_check == 0)
/* this is the earliers that rebuilt will be
* visible in /proc/mdstat
@@ -5645,8 +5655,8 @@ static int set_ro(const char *val, struct kernel_param *kp)
return -EINVAL;
}
-module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
-module_param(start_dirty_degraded, int, 0644);
+module_param_call(start_ro, set_ro, get_ro, NULL, S_IRUSR|S_IWUSR);
+module_param(start_dirty_degraded, int, S_IRUGO|S_IWUSR);
EXPORT_SYMBOL(register_md_personality);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index cead918578a7..1efe22a2d041 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1145,7 +1145,7 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
long sectors_to_go = r1_bio->sectors;
/* make sure these bits doesn't get cleared. */
do {
- bitmap_end_sync(mddev->bitmap, r1_bio->sector,
+ bitmap_end_sync(mddev->bitmap, s,
&sync_blocks, 1);
s += sync_blocks;
sectors_to_go -= sync_blocks;
@@ -1509,6 +1509,9 @@ static void raid1d(mddev_t *mddev)
s<<9, conf->tmppage, READ) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
+ else
+ printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n",
+ mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b));
}
}
} else {
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 7f636283a1ba..016ddb831c9b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1492,6 +1492,10 @@ static void raid10d(mddev_t *mddev)
s<<9, conf->tmppage, READ) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
+ else
+ printk(KERN_INFO "raid10:%s: read error corrected (%d sectors at %llu on %s)\n",
+ mdname(mddev), s, (unsigned long long)(sect+rdev->data_offset), bdevname(rdev->bdev, b));
+
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7433871f4b3a..450066007160 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -18,6 +18,30 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/*
+ * BITMAP UNPLUGGING:
+ *
+ * The sequencing for updating the bitmap reliably is a little
+ * subtle (and I got it wrong the first time) so it deserves some
+ * explanation.
+ *
+ * We group bitmap updates into batches. Each batch has a number.
+ * We may write out several batches at once, but that isn't very important.
+ * conf->bm_write is the number of the last batch successfully written.
+ * conf->bm_flush is the number of the last batch that was closed to
+ * new additions.
+ * When we discover that we will need to write to any block in a stripe
+ * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq
+ * the number of the batch it will be in. This is bm_flush+1.
+ * When we are ready to do a write, if that batch hasn't been written yet,
+ * we plug the array and queue the stripe for later.
+ * When an unplug happens, we increment bm_flush, thus closing the current
+ * batch.
+ * When we notice that bm_flush > bm_write, we write out all pending updates
+ * to the bitmap, and advance bm_write to where bm_flush was.
+ * This may occasionally write a bit out twice, but is sure never to
+ * miss any bits.
+ */
#include <linux/module.h>
#include <linux/slab.h>
@@ -88,12 +112,14 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
BUG_ON(!list_empty(&sh->lru));
BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
- if (test_bit(STRIPE_DELAYED, &sh->state))
+ if (test_bit(STRIPE_DELAYED, &sh->state)) {
list_add_tail(&sh->lru, &conf->delayed_list);
- else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
- conf->seq_write == sh->bm_seq)
+ blk_plug_device(conf->mddev->queue);
+ } else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ sh->bm_seq - conf->seq_write > 0) {
list_add_tail(&sh->lru, &conf->bitmap_list);
- else {
+ blk_plug_device(conf->mddev->queue);
+ } else {
clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
}
@@ -270,7 +296,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
< (conf->max_nr_stripes *3/4)
|| !conf->inactive_blocked),
conf->device_lock,
- unplug_slaves(conf->mddev)
+ raid5_unplug_device(conf->mddev->queue)
);
conf->inactive_blocked = 0;
} else
@@ -281,7 +307,8 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
} else {
if (!test_bit(STRIPE_HANDLE, &sh->state))
atomic_inc(&conf->active_stripes);
- if (list_empty(&sh->lru))
+ if (list_empty(&sh->lru) &&
+ !test_bit(STRIPE_EXPANDING, &sh->state))
BUG();
list_del_init(&sh->lru);
}
@@ -496,6 +523,8 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
raid5_conf_t *conf = sh->raid_conf;
int disks = sh->disks, i;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+ char b[BDEVNAME_SIZE];
+ mdk_rdev_t *rdev;
if (bi->bi_size)
return 1;
@@ -543,25 +572,39 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
set_bit(R5_UPTODATE, &sh->dev[i].flags);
#endif
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- printk(KERN_INFO "raid5: read error corrected!!\n");
+ rdev = conf->disks[i].rdev;
+ printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
+ mdname(conf->mddev), STRIPE_SECTORS,
+ (unsigned long long)sh->sector + rdev->data_offset,
+ bdevname(rdev->bdev, b));
clear_bit(R5_ReadError, &sh->dev[i].flags);
clear_bit(R5_ReWrite, &sh->dev[i].flags);
}
if (atomic_read(&conf->disks[i].rdev->read_errors))
atomic_set(&conf->disks[i].rdev->read_errors, 0);
} else {
+ const char *bdn = bdevname(conf->disks[i].rdev->bdev, b);
int retry = 0;
+ rdev = conf->disks[i].rdev;
+
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
- atomic_inc(&conf->disks[i].rdev->read_errors);
+ atomic_inc(&rdev->read_errors);
if (conf->mddev->degraded)
- printk(KERN_WARNING "raid5: read error not correctable.\n");
+ printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n",
+ mdname(conf->mddev),
+ (unsigned long long)sh->sector + rdev->data_offset,
+ bdn);
else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
/* Oh, no!!! */
- printk(KERN_WARNING "raid5: read error NOT corrected!!\n");
- else if (atomic_read(&conf->disks[i].rdev->read_errors)
+ printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n",
+ mdname(conf->mddev),
+ (unsigned long long)sh->sector + rdev->data_offset,
+ bdn);
+ else if (atomic_read(&rdev->read_errors)
> conf->max_nr_stripes)
printk(KERN_WARNING
- "raid5: Too many read errors, failing device.\n");
+ "raid5:%s: Too many read errors, failing device %s.\n",
+ mdname(conf->mddev), bdn);
else
retry = 1;
if (retry)
@@ -569,7 +612,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
else {
clear_bit(R5_ReadError, &sh->dev[i].flags);
clear_bit(R5_ReWrite, &sh->dev[i].flags);
- md_error(conf->mddev, conf->disks[i].rdev);
+ md_error(conf->mddev, rdev);
}
}
rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
@@ -1270,9 +1313,9 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
(unsigned long long)sh->sector, dd_idx);
if (conf->mddev->bitmap && firstwrite) {
- sh->bm_seq = conf->seq_write;
bitmap_startwrite(conf->mddev->bitmap, sh->sector,
STRIPE_SECTORS, 0);
+ sh->bm_seq = conf->seq_flush+1;
set_bit(STRIPE_BIT_DELAY, &sh->state);
}
@@ -2554,13 +2597,6 @@ static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk,
return ret;
}
-static inline void raid5_plug_device(raid5_conf_t *conf)
-{
- spin_lock_irq(&conf->device_lock);
- blk_plug_device(conf->mddev->queue);
- spin_unlock_irq(&conf->device_lock);
-}
-
static int make_request(request_queue_t *q, struct bio * bi)
{
mddev_t *mddev = q->queuedata;
@@ -2670,7 +2706,6 @@ static int make_request(request_queue_t *q, struct bio * bi)
goto retry;
}
finish_wait(&conf->wait_for_overlap, &w);
- raid5_plug_device(conf);
handle_stripe(sh, NULL);
release_stripe(sh);
} else {
@@ -2923,7 +2958,7 @@ static void raid5d (mddev_t *mddev)
while (1) {
struct list_head *first;
- if (conf->seq_flush - conf->seq_write > 0) {
+ if (conf->seq_flush != conf->seq_write) {
int seq = conf->seq_flush;
spin_unlock_irq(&conf->device_lock);
bitmap_unplug(mddev->bitmap);
@@ -3246,9 +3281,6 @@ static int run(mddev_t *mddev)
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
mddev->sync_thread = md_register_thread(md_do_sync, mddev,
"%s_reshape");
- /* FIXME if md_register_thread fails?? */
- md_wakeup_thread(mddev->sync_thread);
-
}
/* read-ahead size must cover two whole stripes, which is
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 55671cb5255e..87c286ee6a00 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -896,9 +896,9 @@ static int nxt2002_init(struct dvb_frontend* fe)
}
ret = nxt2002_load_firmware(fe, fw);
+ release_firmware(fw);
if (ret) {
printk("nxt2002: Writing firmware to device failed\n");
- release_firmware(fw);
return ret;
}
printk("nxt2002: Firmware upload complete\n");
@@ -960,9 +960,9 @@ static int nxt2004_init(struct dvb_frontend* fe)
}
ret = nxt2004_load_firmware(fe, fw);
+ release_firmware(fw);
if (ret) {
printk("nxt2004: Writing firmware to device failed\n");
- release_firmware(fw);
return ret;
}
printk("nxt2004: Firmware upload complete\n");
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 26bed616fabe..2bf124b53689 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -437,10 +437,10 @@ static int or51211_init(struct dvb_frontend* fe)
}
ret = or51211_load_firmware(fe, fw);
+ release_firmware(fw);
if (ret) {
printk(KERN_WARNING "or51211: Writing firmware to "
"device failed!\n");
- release_firmware(fw);
return ret;
}
printk(KERN_INFO "or51211: Firmware upload complete.\n");
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 44ec5b9a4695..d98fd5c2e13e 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -318,7 +318,6 @@ static int sp8870_init (struct dvb_frontend* fe)
printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
printk("sp8870: no firmware upload (timeout or file not found?)\n");
- release_firmware(fw);
return -EIO;
}
@@ -327,6 +326,7 @@ static int sp8870_init (struct dvb_frontend* fe)
release_firmware(fw);
return -EIO;
}
+ release_firmware(fw);
printk("sp8870: firmware upload complete\n");
/* enable TS output and interface pins */
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index b0a2b02f6608..5c2f8f4e0ae5 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -520,9 +520,9 @@ static int sp887x_init(struct dvb_frontend* fe)
}
ret = sp887x_initial_setup(fe, fw);
+ release_firmware(fw);
if (ret) {
printk("sp887x: writing firmware to device failed\n");
- release_firmware(fw);
return ret;
}
printk("sp887x: firmware upload complete\n");
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 349632b48e93..b60177f173c3 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -453,11 +453,13 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
+ release_firmware(firmware);
return -1;
}
if (0 != memcmp(firmware->data, magic, 8)) {
dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
+ release_firmware(firmware);
return -1;
}
@@ -478,6 +480,7 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
}
if (checksum) {
dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
+ release_firmware(firmware);
return -1;
}
release_firmware(firmware);
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 184974cc734d..dc388a3ff5e0 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -38,6 +38,9 @@ extern struct device_attribute i2o_device_attrs[];
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
+int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
+ int oplen, void *reslist, int reslen);
+
/* IOP */
extern struct i2o_controller *i2o_iop_alloc(void);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 89daf67b764d..7d23e082bf26 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -36,9 +36,9 @@
#include <asm/uaccess.h>
-#define SG_TABLESIZE 30
+#include "core.h"
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+#define SG_TABLESIZE 30
static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 632bc218c86a..2bf32721eb53 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -479,7 +479,7 @@ static int ucb1x00_probe(struct mcp *mcp)
mcp_enable(mcp);
id = mcp_reg_read(mcp, UCB_ID);
- if (id != UCB_ID_1200 && id != UCB_ID_1300) {
+ if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
goto err_disable;
}
diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
index 9c9a647d8b7b..ca8df8072d43 100644
--- a/drivers/mfd/ucb1x00.h
+++ b/drivers/mfd/ucb1x00.h
@@ -94,6 +94,7 @@
#define UCB_ID 0x0c
#define UCB_ID_1200 0x1004
#define UCB_ID_1300 0x1005
+#define UCB_ID_TC35143 0x9712
#define UCB_MODE 0x0d
#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 2819de79442c..80e8ca013e44 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -17,172 +17,6 @@
410 Severn Ave., Suite 210
Annapolis MD 21403
- Linux Kernel Additions:
-
- 0.99H+lk0.9 - David S. Miller - softnet, PCI DMA updates
- 0.99H+lk1.0 - Jeff Garzik <jgarzik@pobox.com>
- Remove compatibility defines for kernel versions < 2.2.x.
- Update for new 2.3.x module interface
- LK1.1.2 (March 19, 2000)
- * New PCI interface (jgarzik)
-
- LK1.1.3 25 April 2000, Andrew Morton <andrewm@uow.edu.au>
- - Merged with 3c575_cb.c
- - Don't set RxComplete in boomerang interrupt enable reg
- - spinlock in vortex_timer to protect mdio functions
- - disable local interrupts around call to vortex_interrupt in
- vortex_tx_timeout() (So vortex_interrupt can use spin_lock())
- - Select window 3 in vortex_timer()'s write to Wn3_MAC_Ctrl
- - In vortex_start_xmit(), move the lock to _after_ we've altered
- vp->cur_tx and vp->tx_full. This defeats the race between
- vortex_start_xmit() and vortex_interrupt which was identified
- by Bogdan Costescu.
- - Merged back support for six new cards from various sources
- - Set vortex_have_pci if pci_module_init returns zero (fixes cardbus
- insertion oops)
- - Tell it that 3c905C has NWAY for 100bT autoneg
- - Fix handling of SetStatusEnd in 'Too much work..' code, as
- per 2.3.99's 3c575_cb (Dave Hinds).
- - Split ISR into two for vortex & boomerang
- - Fix MOD_INC/DEC races
- - Handle resource allocation failures.
- - Fix 3CCFE575CT LED polarity
- - Make tx_interrupt_mitigation the default
-
- LK1.1.4 25 April 2000, Andrew Morton <andrewm@uow.edu.au>
- - Add extra TxReset to vortex_up() to fix 575_cb hotplug initialisation probs.
- - Put vortex_info_tbl into __devinitdata
- - In the vortex_error StatsFull HACK, disable stats in vp->intr_enable as well
- as in the hardware.
- - Increased the loop counter in issue_and_wait from 2,000 to 4,000.
-
- LK1.1.5 28 April 2000, andrewm
- - Added powerpc defines (John Daniel <jdaniel@etresoft.com> said these work...)
- - Some extra diagnostics
- - In vortex_error(), reset the Tx on maxCollisions. Otherwise most
- chips usually get a Tx timeout.
- - Added extra_reset module parm
- - Replaced some inline timer manip with mod_timer
- (Franois romieu <Francois.Romieu@nic.fr>)
- - In vortex_up(), don't make Wn3_config initialisation dependent upon has_nway
- (this came across from 3c575_cb).
-
- LK1.1.6 06 Jun 2000, andrewm
- - Backed out the PPC defines.
- - Use del_timer_sync(), mod_timer().
- - Fix wrapped ulong comparison in boomerang_rx()
- - Add IS_TORNADO, use it to suppress 3c905C checksum error msg
- (Donald Becker, I Lee Hetherington <ilh@sls.lcs.mit.edu>)
- - Replace union wn3_config with BFINS/BFEXT manipulation for
- sparc64 (Pete Zaitcev, Peter Jones)
- - In vortex_error, do_tx_reset and vortex_tx_timeout(Vortex):
- do a netif_wake_queue() to better recover from errors. (Anders Pedersen,
- Donald Becker)
- - Print a warning on out-of-memory (rate limited to 1 per 10 secs)
- - Added two more Cardbus 575 NICs: 5b57 and 6564 (Paul Wagland)
-
- LK1.1.7 2 Jul 2000 andrewm
- - Better handling of shared IRQs
- - Reset the transmitter on a Tx reclaim error
- - Fixed crash under OOM during vortex_open() (Mark Hemment)
- - Fix Rx cessation problem during OOM (help from Mark Hemment)
- - The spinlocks around the mdio access were blocking interrupts for 300uS.
- Fix all this to use spin_lock_bh() within mdio_read/write
- - Only write to TxFreeThreshold if it's a boomerang - other NICs don't
- have one.
- - Added 802.3x MAC-layer flow control support
-
- LK1.1.8 13 Aug 2000 andrewm
- - Ignore request_region() return value - already reserved if Cardbus.
- - Merged some additional Cardbus flags from Don's 0.99Qk
- - Some fixes for 3c556 (Fred Maciel)
- - Fix for EISA initialisation (Jan Rekorajski)
- - Renamed MII_XCVR_PWR and EEPROM_230 to align with 3c575_cb and D. Becker's drivers
- - Fixed MII_XCVR_PWR for 3CCFE575CT
- - Added INVERT_LED_PWR, used it.
- - Backed out the extra_reset stuff
-
- LK1.1.9 12 Sep 2000 andrewm
- - Backed out the tx_reset_resume flags. It was a no-op.
- - In vortex_error, don't reset the Tx on txReclaim errors
- - In vortex_error, don't reset the Tx on maxCollisions errors.
- Hence backed out all the DownListPtr logic here.
- - In vortex_error, give Tornado cards a partial TxReset on
- maxCollisions (David Hinds). Defined MAX_COLLISION_RESET for this.
- - Redid some driver flags and device names based on pcmcia_cs-3.1.20.
- - Fixed a bug where, if vp->tx_full is set when the interface
- is downed, it remains set when the interface is upped. Bad
- things happen.
-
- LK1.1.10 17 Sep 2000 andrewm
- - Added EEPROM_8BIT for 3c555 (Fred Maciel)
- - Added experimental support for the 3c556B Laptop Hurricane (Louis Gerbarg)
- - Add HAS_NWAY to "3c900 Cyclone 10Mbps TPO"
-
- LK1.1.11 13 Nov 2000 andrewm
- - Dump MOD_INC/DEC_USE_COUNT, use SET_MODULE_OWNER
-
- LK1.1.12 1 Jan 2001 andrewm (2.4.0-pre1)
- - Call pci_enable_device before we request our IRQ (Tobias Ringstrom)
- - Add 3c590 PCI latency timer hack to vortex_probe1 (from 0.99Ra)
- - Added extended issue_and_wait for the 3c905CX.
- - Look for an MII on PHY index 24 first (3c905CX oddity).
- - Add HAS_NWAY to 3cSOHO100-TX (Brett Frankenberger)
- - Don't free skbs we don't own on oom path in vortex_open().
-
- LK1.1.13 27 Jan 2001
- - Added explicit `medialock' flag so we can truly
- lock the media type down with `options'.
- - "check ioremap return and some tidbits" (Arnaldo Carvalho de Melo <acme@conectiva.com.br>)
- - Added and used EEPROM_NORESET for 3c556B PM resumes.
- - Fixed leakage of vp->rx_ring.
- - Break out separate HAS_HWCKSM device capability flag.
- - Kill vp->tx_full (ANK)
- - Merge zerocopy fragment handling (ANK?)
-
- LK1.1.14 15 Feb 2001
- - Enable WOL. Can be turned on with `enable_wol' module option.
- - EISA and PCI initialisation fixes (jgarzik, Manfred Spraul)
- - If a device's internalconfig register reports it has NWAY,
- use it, even if autoselect is enabled.
-
- LK1.1.15 6 June 2001 akpm
- - Prevent double counting of received bytes (Lars Christensen)
- - Add ethtool support (jgarzik)
- - Add module parm descriptions (Andrzej M. Krzysztofowicz)
- - Implemented alloc_etherdev() API
- - Special-case the 'Tx error 82' message.
-
- LK1.1.16 18 July 2001 akpm
- - Make NETIF_F_SG dependent upon nr_free_highpages(), not on CONFIG_HIGHMEM
- - Lessen verbosity of bootup messages
- - Fix WOL - use new PM API functions.
- - Use netif_running() instead of vp->open in suspend/resume.
- - Don't reset the interface logic on open/close/rmmod. It upsets
- autonegotiation, and hence DHCP (from 0.99T).
- - Back out EEPROM_NORESET flag because of the above (we do it for all
- NICs).
- - Correct 3c982 identification string
- - Rename wait_for_completion() to issue_and_wait() to avoid completion.h
- clash.
-
- LK1.1.17 18Dec01 akpm
- - PCI ID 9805 is a Python-T, not a dual-port Cyclone. Apparently.
- And it has NWAY.
- - Mask our advertised modes (vp->advertising) with our capabilities
- (MII reg5) when deciding which duplex mode to use.
- - Add `global_options' as default for options[]. Ditto global_enable_wol,
- global_full_duplex.
-
- LK1.1.18 01Jul02 akpm
- - Fix for undocumented transceiver power-up bit on some 3c566B's
- (Donald Becker, Rahul Karnik)
-
- - See http://www.zip.com.au/~akpm/linux/#3c59x-2.3 for more details.
- - Also see Documentation/networking/vortex.txt
-
- LK1.1.19 10Nov02 Marc Zyngier <maz@wild-wind.fr.eu.org>
- - EISA sysfs integration.
*/
/*
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index d2150baa7e35..1428bb7715af 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1916,7 +1916,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
regs = ioremap(pciaddr, CP_REGS_SIZE);
if (!regs) {
rc = -EIO;
- dev_err(&pdev->dev, "Cannot map PCI MMIO (%lx@%lx)\n",
+ dev_err(&pdev->dev, "Cannot map PCI MMIO (%Lx@%Lx)\n",
(unsigned long long)pci_resource_len(pdev, 1),
(unsigned long long)pciaddr);
goto err_out_res;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index cd9718512d1c..e4f4eaff7679 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1709,6 +1709,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
unsigned int entry;
unsigned int len = skb->len;
+ unsigned long flags;
/* Calculate the next Tx descriptor entry. */
entry = tp->cur_tx % NUM_TX_DESC;
@@ -1725,7 +1726,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
return 0;
}
- spin_lock_irq(&tp->lock);
+ spin_lock_irqsave(&tp->lock, flags);
RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
@@ -1736,7 +1737,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_irqrestore(&tp->lock, flags);
if (netif_msg_tx_queued(tp))
printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n",
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 64b6a72b4f6a..db73de0d2511 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -1639,7 +1639,7 @@ bnx2_tx_int(struct bnx2 *bp)
skb = tx_buf->skb;
#ifdef BCM_TSO
/* partial BD completions possible with TSO packets */
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
u16 last_idx, last_ring_idx;
last_idx = sw_cons +
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 87f94d939ff8..61b3754f50ff 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1417,7 +1417,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct cpl_tx_pkt *cpl;
#ifdef NETIF_F_TSO
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
int eth_type;
struct cpl_tx_pkt_lso *hdr;
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 3042d33e2d4d..f411bbb44f86 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -68,7 +68,6 @@
#ifdef NETIF_F_TSO
#include <net/checksum.h>
#endif
-#include <linux/workqueue.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
@@ -143,6 +142,7 @@ struct e1000_adapter;
#define AUTO_ALL_MODES 0
#define E1000_EEPROM_82544_APM 0x0004
+#define E1000_EEPROM_ICH8_APME 0x0004
#define E1000_EEPROM_APME 0x0400
#ifndef E1000_MASTER_SLAVE
@@ -254,7 +254,6 @@ struct e1000_adapter {
spinlock_t tx_queue_lock;
#endif
atomic_t irq_sem;
- struct work_struct watchdog_task;
struct work_struct reset_task;
uint8_t fc_autoneg;
@@ -339,8 +338,14 @@ struct e1000_adapter {
#ifdef NETIF_F_TSO
boolean_t tso_force;
#endif
+ boolean_t smart_power_down; /* phy smart power down */
+ unsigned long flags;
};
+enum e1000_state_t {
+ __E1000_DRIVER_TESTING,
+ __E1000_RESETTING,
+};
/* e1000_main.c */
extern char e1000_driver_name[];
@@ -348,6 +353,7 @@ extern char e1000_driver_version[];
int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter);
void e1000_reset(struct e1000_adapter *adapter);
+void e1000_reinit_locked(struct e1000_adapter *adapter);
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index d19664891768..88a82ba88f57 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -109,7 +109,8 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
SUPPORTED_1000baseT_Full|
SUPPORTED_Autoneg |
SUPPORTED_TP);
-
+ if (hw->phy_type == e1000_phy_ife)
+ ecmd->supported &= ~SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_TP;
if (hw->autoneg == 1) {
@@ -203,11 +204,9 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
/* reset the link */
- if (netif_running(adapter->netdev)) {
- e1000_down(adapter);
- e1000_reset(adapter);
- e1000_up(adapter);
- } else
+ if (netif_running(adapter->netdev))
+ e1000_reinit_locked(adapter);
+ else
e1000_reset(adapter);
return 0;
@@ -254,10 +253,9 @@ e1000_set_pauseparam(struct net_device *netdev,
hw->original_fc = hw->fc;
if (adapter->fc_autoneg == AUTONEG_ENABLE) {
- if (netif_running(adapter->netdev)) {
- e1000_down(adapter);
- e1000_up(adapter);
- } else
+ if (netif_running(adapter->netdev))
+ e1000_reinit_locked(adapter);
+ else
e1000_reset(adapter);
} else
return ((hw->media_type == e1000_media_type_fiber) ?
@@ -279,10 +277,9 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data;
- if (netif_running(netdev)) {
- e1000_down(adapter);
- e1000_up(adapter);
- } else
+ if (netif_running(netdev))
+ e1000_reinit_locked(adapter);
+ else
e1000_reset(adapter);
return 0;
}
@@ -577,6 +574,7 @@ e1000_get_drvinfo(struct net_device *netdev,
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
+ case e1000_ich8lan:
sprintf(firmware_version, "%d.%d-%d",
(eeprom_data & 0xF000) >> 12,
(eeprom_data & 0x0FF0) >> 4,
@@ -631,6 +629,9 @@ e1000_set_ringparam(struct net_device *netdev,
tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
+ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+ msleep(1);
+
if (netif_running(adapter->netdev))
e1000_down(adapter);
@@ -691,9 +692,11 @@ e1000_set_ringparam(struct net_device *netdev,
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
if ((err = e1000_up(adapter)))
- return err;
+ goto err_setup;
}
+ clear_bit(__E1000_RESETTING, &adapter->flags);
+
return 0;
err_setup_tx:
e1000_free_all_rx_resources(adapter);
@@ -701,6 +704,8 @@ err_setup_rx:
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
e1000_up(adapter);
+err_setup:
+ clear_bit(__E1000_RESETTING, &adapter->flags);
return err;
}
@@ -754,6 +759,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
toggle = 0x7FFFF3FF;
break;
case e1000_82573:
+ case e1000_ich8lan:
toggle = 0x7FFFF033;
break;
default:
@@ -773,11 +779,12 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
}
/* restore previous status */
E1000_WRITE_REG(&adapter->hw, STATUS, before);
-
- REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+ if (adapter->hw.mac_type != e1000_ich8lan) {
+ REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+ }
REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
@@ -790,20 +797,22 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
- REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
+ before = (adapter->hw.mac_type == e1000_ich8lan ?
+ 0x06C3B33E : 0x06DFB3FE);
+ REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
if (adapter->hw.mac_type >= e1000_82543) {
- REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
+ REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
- REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
+ if (adapter->hw.mac_type != e1000_ich8lan)
+ REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
-
- for (i = 0; i < E1000_RAR_ENTRIES; i++) {
- REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
- 0xFFFFFFFF);
+ value = (adapter->hw.mac_type == e1000_ich8lan ?
+ E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
+ for (i = 0; i < value; i++) {
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
0xFFFFFFFF);
}
@@ -817,7 +826,9 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
}
- for (i = 0; i < E1000_MC_TBL_SIZE; i++)
+ value = (adapter->hw.mac_type == e1000_ich8lan ?
+ E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
+ for (i = 0; i < value; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0;
@@ -889,6 +900,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
/* Test each interrupt */
for (; i < 10; i++) {
+ if (adapter->hw.mac_type == e1000_ich8lan && i == 8)
+ continue;
/* Interrupt to test */
mask = 1 << i;
@@ -1246,18 +1259,33 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
} else if (adapter->hw.phy_type == e1000_phy_gg82563) {
e1000_write_phy_reg(&adapter->hw,
GG82563_PHY_KMRN_MODE_CTRL,
- 0x1CE);
+ 0x1CC);
}
- /* force 1000, set loopback */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
- /* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
- ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
- ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
- E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
- E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
- E1000_CTRL_FD); /* Force Duplex to FULL */
+
+ if (adapter->hw.phy_type == e1000_phy_ife) {
+ /* force 100, set loopback */
+ e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x6100);
+
+ /* Now set up the MAC to the same speed/duplex as the PHY. */
+ ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ E1000_CTRL_SPD_100 |/* Force Speed to 100 */
+ E1000_CTRL_FD); /* Force Duplex to FULL */
+ } else {
+ /* force 1000, set loopback */
+ e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+
+ /* Now set up the MAC to the same speed/duplex as the PHY. */
+ ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+ E1000_CTRL_FD); /* Force Duplex to FULL */
+ }
if (adapter->hw.media_type == e1000_media_type_copper &&
adapter->hw.phy_type == e1000_phy_m88) {
@@ -1317,6 +1345,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
+ case e1000_ich8lan:
return e1000_integrated_phy_loopback(adapter);
break;
@@ -1568,6 +1597,7 @@ e1000_diag_test(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
boolean_t if_running = netif_running(netdev);
+ set_bit(__E1000_DRIVER_TESTING, &adapter->flags);
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
/* Offline tests */
@@ -1582,7 +1612,8 @@ e1000_diag_test(struct net_device *netdev,
eth_test->flags |= ETH_TEST_FL_FAILED;
if (if_running)
- e1000_down(adapter);
+ /* indicate we're in test mode */
+ dev_close(netdev);
else
e1000_reset(adapter);
@@ -1607,8 +1638,9 @@ e1000_diag_test(struct net_device *netdev,
adapter->hw.autoneg = autoneg;
e1000_reset(adapter);
+ clear_bit(__E1000_DRIVER_TESTING, &adapter->flags);
if (if_running)
- e1000_up(adapter);
+ dev_open(netdev);
} else {
/* Online tests */
if (e1000_link_test(adapter, &data[4]))
@@ -1619,6 +1651,8 @@ e1000_diag_test(struct net_device *netdev,
data[1] = 0;
data[2] = 0;
data[3] = 0;
+
+ clear_bit(__E1000_DRIVER_TESTING, &adapter->flags);
}
msleep_interruptible(4 * 1000);
}
@@ -1778,21 +1812,18 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- } else if (adapter->hw.mac_type < e1000_82573) {
- E1000_WRITE_REG(&adapter->hw, LEDCTL,
- (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+ } else if (adapter->hw.phy_type == e1000_phy_ife) {
+ if (!adapter->blink_timer.function) {
+ init_timer(&adapter->blink_timer);
+ adapter->blink_timer.function = e1000_led_blink_callback;
+ adapter->blink_timer.data = (unsigned long) adapter;
+ }
+ mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
+ del_timer_sync(&adapter->blink_timer);
+ e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);
} else {
- E1000_WRITE_REG(&adapter->hw, LEDCTL,
- (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+ e1000_blink_led_start(&adapter->hw);
msleep_interruptible(data * 1000);
}
@@ -1807,10 +1838,8 @@ static int
e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if (netif_running(netdev)) {
- e1000_down(adapter);
- e1000_up(adapter);
- }
+ if (netif_running(netdev))
+ e1000_reinit_locked(adapter);
return 0;
}
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 3959039b16ec..583518ae49ce 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -101,7 +101,8 @@ static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset,
#define E1000_WRITE_REG_IO(a, reg, val) \
e1000_write_reg_io((a), E1000_##reg, val)
-static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw);
+static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
+ uint16_t duplex);
static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
/* IGP cable length table */
@@ -156,6 +157,14 @@ e1000_set_phy_type(struct e1000_hw *hw)
hw->phy_type = e1000_phy_igp;
break;
}
+ case IGP03E1000_E_PHY_ID:
+ hw->phy_type = e1000_phy_igp_3;
+ break;
+ case IFE_E_PHY_ID:
+ case IFE_PLUS_E_PHY_ID:
+ case IFE_C_E_PHY_ID:
+ hw->phy_type = e1000_phy_ife;
+ break;
case GG82563_E_PHY_ID:
if (hw->mac_type == e1000_80003es2lan) {
hw->phy_type = e1000_phy_gg82563;
@@ -332,6 +341,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
break;
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EI_MOBILE:
+ case E1000_DEV_ID_82541ER_LOM:
hw->mac_type = e1000_82541;
break;
case E1000_DEV_ID_82541ER:
@@ -341,6 +351,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
hw->mac_type = e1000_82541_rev_2;
break;
case E1000_DEV_ID_82547EI:
+ case E1000_DEV_ID_82547EI_MOBILE:
hw->mac_type = e1000_82547;
break;
case E1000_DEV_ID_82547GI:
@@ -354,6 +365,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82572EI_COPPER:
case E1000_DEV_ID_82572EI_FIBER:
case E1000_DEV_ID_82572EI_SERDES:
+ case E1000_DEV_ID_82572EI:
hw->mac_type = e1000_82572;
break;
case E1000_DEV_ID_82573E:
@@ -361,16 +373,29 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82573L:
hw->mac_type = e1000_82573;
break;
+ case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
+ case E1000_DEV_ID_80003ES2LAN_SERDES_SPT:
case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
hw->mac_type = e1000_80003es2lan;
break;
+ case E1000_DEV_ID_ICH8_IGP_M_AMT:
+ case E1000_DEV_ID_ICH8_IGP_AMT:
+ case E1000_DEV_ID_ICH8_IGP_C:
+ case E1000_DEV_ID_ICH8_IFE:
+ case E1000_DEV_ID_ICH8_IGP_M:
+ hw->mac_type = e1000_ich8lan;
+ break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
}
switch(hw->mac_type) {
+ case e1000_ich8lan:
+ hw->swfwhw_semaphore_present = TRUE;
+ hw->asf_firmware_present = TRUE;
+ break;
case e1000_80003es2lan:
hw->swfw_sync_present = TRUE;
/* fall through */
@@ -423,6 +448,7 @@ e1000_set_media_type(struct e1000_hw *hw)
case e1000_82542_rev2_1:
hw->media_type = e1000_media_type_fiber;
break;
+ case e1000_ich8lan:
case e1000_82573:
/* The STATUS_TBIMODE bit is reserved or reused for the this
* device.
@@ -527,6 +553,14 @@ e1000_reset_hw(struct e1000_hw *hw)
} while(timeout);
}
+ /* Workaround for ICH8 bit corruption issue in FIFO memory */
+ if (hw->mac_type == e1000_ich8lan) {
+ /* Set Tx and Rx buffer allocation to 8k apiece. */
+ E1000_WRITE_REG(hw, PBA, E1000_PBA_8K);
+ /* Set Packet Buffer Size to 16k. */
+ E1000_WRITE_REG(hw, PBS, E1000_PBS_16K);
+ }
+
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
@@ -550,6 +584,20 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Reset is performed on a shadow of the control register */
E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
break;
+ case e1000_ich8lan:
+ if (!hw->phy_reset_disable &&
+ e1000_check_phy_reset_block(hw) == E1000_SUCCESS) {
+ /* e1000_ich8lan PHY HW reset requires MAC CORE reset
+ * at the same time to make sure the interface between
+ * MAC and the external PHY is reset.
+ */
+ ctrl |= E1000_CTRL_PHY_RST;
+ }
+
+ e1000_get_software_flag(hw);
+ E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+ msec_delay(5);
+ break;
default:
E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
break;
@@ -591,6 +639,7 @@ e1000_reset_hw(struct e1000_hw *hw)
/* fall through */
case e1000_82571:
case e1000_82572:
+ case e1000_ich8lan:
case e1000_80003es2lan:
ret_val = e1000_get_auto_rd_done(hw);
if(ret_val)
@@ -633,6 +682,12 @@ e1000_reset_hw(struct e1000_hw *hw)
e1000_pci_set_mwi(hw);
}
+ if (hw->mac_type == e1000_ich8lan) {
+ uint32_t kab = E1000_READ_REG(hw, KABGTXD);
+ kab |= E1000_KABGTXD_BGSQLBIAS;
+ E1000_WRITE_REG(hw, KABGTXD, kab);
+ }
+
return E1000_SUCCESS;
}
@@ -675,9 +730,12 @@ e1000_init_hw(struct e1000_hw *hw)
/* Disabling VLAN filtering. */
DEBUGOUT("Initializing the IEEE VLAN\n");
- if (hw->mac_type < e1000_82545_rev_3)
- E1000_WRITE_REG(hw, VET, 0);
- e1000_clear_vfta(hw);
+ /* VET hardcoded to standard value and VFTA removed in ICH8 LAN */
+ if (hw->mac_type != e1000_ich8lan) {
+ if (hw->mac_type < e1000_82545_rev_3)
+ E1000_WRITE_REG(hw, VET, 0);
+ e1000_clear_vfta(hw);
+ }
/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
if(hw->mac_type == e1000_82542_rev2_0) {
@@ -705,8 +763,14 @@ e1000_init_hw(struct e1000_hw *hw)
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
mta_size = E1000_MC_TBL_SIZE;
- for(i = 0; i < mta_size; i++)
+ if (hw->mac_type == e1000_ich8lan)
+ mta_size = E1000_MC_TBL_SIZE_ICH8LAN;
+ for(i = 0; i < mta_size; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+ /* use write flush to prevent Memory Write Block (MWB) from
+ * occuring when accessing our register space */
+ E1000_WRITE_FLUSH(hw);
+ }
/* Set the PCI priority bit correctly in the CTRL register. This
* determines if the adapter gives priority to receives, or if it
@@ -744,6 +808,10 @@ e1000_init_hw(struct e1000_hw *hw)
break;
}
+ /* More time needed for PHY to initialize */
+ if (hw->mac_type == e1000_ich8lan)
+ msec_delay(15);
+
/* Call a subroutine to configure the link and setup flow control. */
ret_val = e1000_setup_link(hw);
@@ -757,6 +825,7 @@ e1000_init_hw(struct e1000_hw *hw)
case e1000_82571:
case e1000_82572:
case e1000_82573:
+ case e1000_ich8lan:
case e1000_80003es2lan:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -795,6 +864,7 @@ e1000_init_hw(struct e1000_hw *hw)
/* Fall through */
case e1000_82571:
case e1000_82572:
+ case e1000_ich8lan:
ctrl = E1000_READ_REG(hw, TXDCTL1);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
if(hw->mac_type >= e1000_82571)
@@ -818,6 +888,11 @@ e1000_init_hw(struct e1000_hw *hw)
*/
e1000_clear_hw_cntrs(hw);
+ /* ICH8 No-snoop bits are opposite polarity.
+ * Set to snoop by default after reset. */
+ if (hw->mac_type == e1000_ich8lan)
+ e1000_set_pci_ex_no_snoop(hw, PCI_EX_82566_SNOOP_ALL);
+
if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
@@ -905,6 +980,7 @@ e1000_setup_link(struct e1000_hw *hw)
*/
if (hw->fc == e1000_fc_default) {
switch (hw->mac_type) {
+ case e1000_ich8lan:
case e1000_82573:
hw->fc = e1000_fc_full;
break;
@@ -971,9 +1047,12 @@ e1000_setup_link(struct e1000_hw *hw)
*/
DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
- E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
- E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
- E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
+ /* FCAL/H and FCT are hardcoded to standard values in e1000_ich8lan. */
+ if (hw->mac_type != e1000_ich8lan) {
+ E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
+ E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+ E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
+ }
E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
@@ -1237,12 +1316,13 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
/* Wait 10ms for MAC to configure PHY from eeprom settings */
msec_delay(15);
-
+ if (hw->mac_type != e1000_ich8lan) {
/* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ }
/* disable lplu d3 during driver init */
ret_val = e1000_set_d3_lplu_state(hw, FALSE);
@@ -1478,8 +1558,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /* Enable Pass False Carrier on the PHY */
- phy_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+ phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
phy_data);
@@ -1561,28 +1640,40 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
if(hw->disable_polarity_correction == 1)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- if(ret_val)
- return ret_val;
-
- /* Force TX_CLK in the Extended PHY Specific Control Register
- * to 25MHz clock.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
- if(ret_val)
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
return ret_val;
- phy_data |= M88E1000_EPSCR_TX_CLK_25;
-
if (hw->phy_revision < M88E1011_I_REV_4) {
- /* Configure Master and Slave downshift values */
- phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
+ /* Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_EPSCR_TX_CLK_25;
+
+ if ((hw->phy_revision == E1000_REVISION_2) &&
+ (hw->phy_id == M88E1111_I_PHY_ID)) {
+ /* Vidalia Phy, set the downshift counter to 5x */
+ phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
+ phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
+ ret_val = e1000_write_phy_reg(hw,
+ M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+ } else {
+ /* Configure Master and Slave downshift values */
+ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
- phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
- ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
- if(ret_val)
- return ret_val;
+ ret_val = e1000_write_phy_reg(hw,
+ M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+ }
}
/* SW Reset the PHY so all changes take effect */
@@ -1620,6 +1711,10 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
if(hw->autoneg_advertised == 0)
hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ /* IFE phy only supports 10/100 */
+ if (hw->phy_type == e1000_phy_ife)
+ hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
+
DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
ret_val = e1000_phy_setup_autoneg(hw);
if(ret_val) {
@@ -1717,6 +1812,26 @@ e1000_setup_copper_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_copper_link");
+ switch (hw->mac_type) {
+ case e1000_80003es2lan:
+ case e1000_ich8lan:
+ /* Set the mac to wait the maximum time between each
+ * iteration and increase the max iterations when
+ * polling the phy; this fixes erroneous timeouts at 10Mbps. */
+ ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+ if (ret_val)
+ return ret_val;
+ reg_data |= 0x3F;
+ ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+ if (ret_val)
+ return ret_val;
+ default:
+ break;
+ }
+
/* Check if it is a valid PHY and set PHY mode if necessary. */
ret_val = e1000_copper_link_preconfig(hw);
if(ret_val)
@@ -1724,10 +1839,8 @@ e1000_setup_copper_link(struct e1000_hw *hw)
switch (hw->mac_type) {
case e1000_80003es2lan:
- ret_val = e1000_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
- &reg_data);
- if (ret_val)
- return ret_val;
+ /* Kumeran registers are written-only */
+ reg_data = E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT;
reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING;
ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
reg_data);
@@ -1739,6 +1852,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
}
if (hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_3 ||
hw->phy_type == e1000_phy_igp_2) {
ret_val = e1000_copper_link_igp_setup(hw);
if(ret_val)
@@ -1803,7 +1917,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
******************************************************************************/
static int32_t
-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw)
+e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
{
int32_t ret_val = E1000_SUCCESS;
uint32_t tipg;
@@ -1823,6 +1937,18 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw)
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
E1000_WRITE_REG(hw, TIPG, tipg);
+ ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+
+ if (ret_val)
+ return ret_val;
+
+ if (duplex == HALF_DUPLEX)
+ reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+ else
+ reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+ ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+
return ret_val;
}
@@ -1847,6 +1973,14 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
E1000_WRITE_REG(hw, TIPG, tipg);
+ ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+
+ if (ret_val)
+ return ret_val;
+
+ reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+ ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+
return ret_val;
}
@@ -1869,10 +2003,13 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ if (hw->phy_type != e1000_phy_ife) {
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+ } else
+ mii_1000t_ctrl_reg=0;
/* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
@@ -1923,6 +2060,9 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
if(hw->autoneg_advertised & ADVERTISE_1000_FULL) {
DEBUGOUT("Advertise 1000mb Full duplex\n");
mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+ if (hw->phy_type == e1000_phy_ife) {
+ DEBUGOUT("e1000_phy_ife is a 10/100 PHY. Gigabit speed is not supported.\n");
+ }
}
/* Check for a software override of the flow control settings, and
@@ -1984,9 +2124,11 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ if (hw->phy_type != e1000_phy_ife) {
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+ }
return E1000_SUCCESS;
}
@@ -2089,6 +2231,18 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
/* Need to reset the PHY or these changes will be ignored */
mii_ctrl_reg |= MII_CR_RESET;
+ /* Disable MDI-X support for 10/100 */
+ } else if (hw->phy_type == e1000_phy_ife) {
+ ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IFE_PMC_AUTO_MDIX;
+ phy_data &= ~IFE_PMC_FORCE_MDIX;
+
+ ret_val = e1000_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, phy_data);
+ if (ret_val)
+ return ret_val;
} else {
/* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed or duplex are forced.
@@ -2721,8 +2875,12 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if(hw->tbi_compatibility_en) {
uint16_t speed, duplex;
- e1000_get_speed_and_duplex(hw, &speed, &duplex);
- if(speed != SPEED_1000) {
+ ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ DEBUGOUT("Error getting link speed and duplex\n");
+ return ret_val;
+ }
+ if (speed != SPEED_1000) {
/* If link speed is not set to gigabit speed, we do not need
* to enable TBI compatibility.
*/
@@ -2889,7 +3047,13 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
if (*speed == SPEED_1000)
ret_val = e1000_configure_kmrn_for_1000(hw);
else
- ret_val = e1000_configure_kmrn_for_10_100(hw);
+ ret_val = e1000_configure_kmrn_for_10_100(hw, *duplex);
+ if (ret_val)
+ return ret_val;
+ }
+
+ if ((hw->phy_type == e1000_phy_igp_3) && (*speed == SPEED_1000)) {
+ ret_val = e1000_kumeran_lock_loss_workaround(hw);
if (ret_val)
return ret_val;
}
@@ -3079,6 +3243,9 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
DEBUGFUNC("e1000_swfw_sync_acquire");
+ if (hw->swfwhw_semaphore_present)
+ return e1000_get_software_flag(hw);
+
if (!hw->swfw_sync_present)
return e1000_get_hw_eeprom_semaphore(hw);
@@ -3118,6 +3285,11 @@ e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
DEBUGFUNC("e1000_swfw_sync_release");
+ if (hw->swfwhw_semaphore_present) {
+ e1000_release_software_flag(hw);
+ return;
+ }
+
if (!hw->swfw_sync_present) {
e1000_put_hw_eeprom_semaphore(hw);
return;
@@ -3160,7 +3332,8 @@ e1000_read_phy_reg(struct e1000_hw *hw,
if (e1000_swfw_sync_acquire(hw, swfw))
return -E1000_ERR_SWFW_SYNC;
- if((hw->phy_type == e1000_phy_igp ||
+ if ((hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_3 ||
hw->phy_type == e1000_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3299,7 +3472,8 @@ e1000_write_phy_reg(struct e1000_hw *hw,
if (e1000_swfw_sync_acquire(hw, swfw))
return -E1000_ERR_SWFW_SYNC;
- if((hw->phy_type == e1000_phy_igp ||
+ if ((hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_3 ||
hw->phy_type == e1000_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3514,7 +3688,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
E1000_WRITE_FLUSH(hw);
if (hw->mac_type >= e1000_82571)
- msec_delay(10);
+ msec_delay_irq(10);
e1000_swfw_sync_release(hw, swfw);
} else {
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
@@ -3544,6 +3718,12 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
ret_val = e1000_get_phy_cfg_done(hw);
e1000_release_software_semaphore(hw);
+ if ((hw->mac_type == e1000_ich8lan) &&
+ (hw->phy_type == e1000_phy_igp_3)) {
+ ret_val = e1000_init_lcd_from_nvm(hw);
+ if (ret_val)
+ return ret_val;
+ }
return ret_val;
}
@@ -3572,9 +3752,11 @@ e1000_phy_reset(struct e1000_hw *hw)
case e1000_82541_rev_2:
case e1000_82571:
case e1000_82572:
+ case e1000_ich8lan:
ret_val = e1000_phy_hw_reset(hw);
if(ret_val)
return ret_val;
+
break;
default:
ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
@@ -3597,11 +3779,120 @@ e1000_phy_reset(struct e1000_hw *hw)
}
/******************************************************************************
+* Work-around for 82566 power-down: on D3 entry-
+* 1) disable gigabit link
+* 2) write VR power-down enable
+* 3) read it back
+* if successful continue, else issue LCD reset and repeat
+*
+* hw - struct containing variables accessed by shared code
+******************************************************************************/
+void
+e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+{
+ int32_t reg;
+ uint16_t phy_data;
+ int32_t retry = 0;
+
+ DEBUGFUNC("e1000_phy_powerdown_workaround");
+
+ if (hw->phy_type != e1000_phy_igp_3)
+ return;
+
+ do {
+ /* Disable link */
+ reg = E1000_READ_REG(hw, PHY_CTRL);
+ E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+
+ /* Write VR power-down enable */
+ e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data);
+ e1000_write_phy_reg(hw, IGP3_VR_CTRL, phy_data |
+ IGP3_VR_CTRL_MODE_SHUT);
+
+ /* Read it back and test */
+ e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data);
+ if ((phy_data & IGP3_VR_CTRL_MODE_SHUT) || retry)
+ break;
+
+ /* Issue PHY reset and repeat at most one more time */
+ reg = E1000_READ_REG(hw, CTRL);
+ E1000_WRITE_REG(hw, CTRL, reg | E1000_CTRL_PHY_RST);
+ retry++;
+ } while (retry);
+
+ return;
+
+}
+
+/******************************************************************************
+* Work-around for 82566 Kumeran PCS lock loss:
+* On link status change (i.e. PCI reset, speed change) and link is up and
+* speed is gigabit-
+* 0) if workaround is optionally disabled do nothing
+* 1) wait 1ms for Kumeran link to come up
+* 2) check Kumeran Diagnostic register PCS lock loss bit
+* 3) if not set the link is locked (all is good), otherwise...
+* 4) reset the PHY
+* 5) repeat up to 10 times
+* Note: this is only called for IGP3 copper when speed is 1gb.
+*
+* hw - struct containing variables accessed by shared code
+******************************************************************************/
+int32_t
+e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ int32_t reg;
+ int32_t cnt;
+ uint16_t phy_data;
+
+ if (hw->kmrn_lock_loss_workaround_disabled)
+ return E1000_SUCCESS;
+
+ /* Make sure link is up before proceeding. If not just return.
+ * Attempting this while link is negotiating fouls up link
+ * stability */
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+
+ if (phy_data & MII_SR_LINK_STATUS) {
+ for (cnt = 0; cnt < 10; cnt++) {
+ /* read once to clear */
+ ret_val = e1000_read_phy_reg(hw, IGP3_KMRN_DIAG, &phy_data);
+ if (ret_val)
+ return ret_val;
+ /* and again to get new status */
+ ret_val = e1000_read_phy_reg(hw, IGP3_KMRN_DIAG, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* check for PCS lock */
+ if (!(phy_data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS))
+ return E1000_SUCCESS;
+
+ /* Issue PHY reset */
+ e1000_phy_hw_reset(hw);
+ msec_delay_irq(5);
+ }
+ /* Disable GigE link negotiation */
+ reg = E1000_READ_REG(hw, PHY_CTRL);
+ E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+
+ /* unable to acquire PCS lock */
+ return E1000_ERR_PHY;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/******************************************************************************
* Probes the expected PHY address for known PHY IDs
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static int32_t
+int32_t
e1000_detect_gig_phy(struct e1000_hw *hw)
{
int32_t phy_init_status, ret_val;
@@ -3613,8 +3904,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
/* The 82571 firmware may still be configuring the PHY. In this
* case, we cannot access the PHY until the configuration is done. So
* we explicitly set the PHY values. */
- if(hw->mac_type == e1000_82571 ||
- hw->mac_type == e1000_82572) {
+ if (hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572) {
hw->phy_id = IGP01E1000_I_PHY_ID;
hw->phy_type = e1000_phy_igp_2;
return E1000_SUCCESS;
@@ -3631,7 +3922,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
/* Read the PHY ID Registers to identify which PHY is onboard. */
ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
- if(ret_val)
+ if (ret_val)
return ret_val;
hw->phy_id = (uint32_t) (phy_id_high << 16);
@@ -3669,6 +3960,12 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
case e1000_80003es2lan:
if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
break;
+ case e1000_ich8lan:
+ if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == IFE_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE;
+ break;
default:
DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
return -E1000_ERR_CONFIG;
@@ -3784,6 +4081,53 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
}
/******************************************************************************
+* Get PHY information from various PHY registers for ife PHY only.
+*
+* hw - Struct containing variables accessed by shared code
+* phy_info - PHY information structure
+******************************************************************************/
+int32_t
+e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+{
+ int32_t ret_val;
+ uint16_t phy_data, polarity;
+
+ DEBUGFUNC("e1000_phy_ife_get_info");
+
+ phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
+ phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
+
+ ret_val = e1000_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
+ phy_info->polarity_correction =
+ (phy_data & IFE_PSC_AUTO_POLARITY_DISABLE) >>
+ IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT;
+
+ if (phy_info->polarity_correction == e1000_polarity_reversal_enabled) {
+ ret_val = e1000_check_polarity(hw, &polarity);
+ if (ret_val)
+ return ret_val;
+ } else {
+ /* Polarity is forced. */
+ polarity = (phy_data & IFE_PSC_FORCE_POLARITY) >>
+ IFE_PSC_FORCE_POLARITY_SHIFT;
+ }
+ phy_info->cable_polarity = polarity;
+
+ ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->mdix_mode =
+ (phy_data & (IFE_PMC_AUTO_MDIX | IFE_PMC_FORCE_MDIX)) >>
+ IFE_PMC_MDIX_MODE_SHIFT;
+
+ return E1000_SUCCESS;
+}
+
+/******************************************************************************
* Get PHY information from various PHY registers fot m88 PHY only.
*
* hw - Struct containing variables accessed by shared code
@@ -3898,9 +4242,12 @@ e1000_phy_get_info(struct e1000_hw *hw,
return -E1000_ERR_CONFIG;
}
- if(hw->phy_type == e1000_phy_igp ||
+ if (hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_3 ||
hw->phy_type == e1000_phy_igp_2)
return e1000_phy_igp_get_info(hw, phy_info);
+ else if (hw->phy_type == e1000_phy_ife)
+ return e1000_phy_ife_get_info(hw, phy_info);
else
return e1000_phy_m88_get_info(hw, phy_info);
}
@@ -4049,6 +4396,35 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->use_eerd = TRUE;
eeprom->use_eewr = FALSE;
break;
+ case e1000_ich8lan:
+ {
+ int32_t i = 0;
+ uint32_t flash_size = E1000_READ_ICH8_REG(hw, ICH8_FLASH_GFPREG);
+
+ eeprom->type = e1000_eeprom_ich8;
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
+ eeprom->word_size = E1000_SHADOW_RAM_WORDS;
+
+ /* Zero the shadow RAM structure. But don't load it from NVM
+ * so as to save time for driver init */
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ hw->eeprom_shadow_ram[i].modified = FALSE;
+ hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+ }
+ }
+
+ hw->flash_base_addr = (flash_size & ICH8_GFPREG_BASE_MASK) *
+ ICH8_FLASH_SECTOR_SIZE;
+
+ hw->flash_bank_size = ((flash_size >> 16) & ICH8_GFPREG_BASE_MASK) + 1;
+ hw->flash_bank_size -= (flash_size & ICH8_GFPREG_BASE_MASK);
+ hw->flash_bank_size *= ICH8_FLASH_SECTOR_SIZE;
+ hw->flash_bank_size /= 2 * sizeof(uint16_t);
+
+ break;
+ }
default:
break;
}
@@ -4469,7 +4845,10 @@ e1000_read_eeprom(struct e1000_hw *hw,
return ret_val;
}
- if(eeprom->type == e1000_eeprom_spi) {
+ if (eeprom->type == e1000_eeprom_ich8)
+ return e1000_read_eeprom_ich8(hw, offset, words, data);
+
+ if (eeprom->type == e1000_eeprom_spi) {
uint16_t word_in;
uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
@@ -4636,7 +5015,10 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
- if(hw->mac_type == e1000_82573) {
+ if (hw->mac_type == e1000_ich8lan)
+ return FALSE;
+
+ if (hw->mac_type == e1000_82573) {
eecd = E1000_READ_REG(hw, EECD);
/* Isolate bits 15 & 16 */
@@ -4686,8 +5068,22 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
}
}
- for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
+ if (hw->mac_type == e1000_ich8lan) {
+ /* Drivers must allocate the shadow ram structure for the
+ * EEPROM checksum to be updated. Otherwise, this bit as well
+ * as the checksum must both be set correctly for this
+ * validation to pass.
+ */
+ e1000_read_eeprom(hw, 0x19, 1, &eeprom_data);
+ if ((eeprom_data & 0x40) == 0) {
+ eeprom_data |= 0x40;
+ e1000_write_eeprom(hw, 0x19, 1, &eeprom_data);
+ e1000_update_eeprom_checksum(hw);
+ }
+ }
+
+ for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
@@ -4713,6 +5109,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
int32_t
e1000_update_eeprom_checksum(struct e1000_hw *hw)
{
+ uint32_t ctrl_ext;
uint16_t checksum = 0;
uint16_t i, eeprom_data;
@@ -4731,6 +5128,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
return -E1000_ERR_EEPROM;
} else if (hw->eeprom.type == e1000_eeprom_flash) {
e1000_commit_shadow_ram(hw);
+ } else if (hw->eeprom.type == e1000_eeprom_ich8) {
+ e1000_commit_shadow_ram(hw);
+ /* Reload the EEPROM, or else modifications will not appear
+ * until after next adapter reset. */
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ msec_delay(10);
}
return E1000_SUCCESS;
}
@@ -4770,6 +5175,9 @@ e1000_write_eeprom(struct e1000_hw *hw,
if(eeprom->use_eewr == TRUE)
return e1000_write_eeprom_eewr(hw, offset, words, data);
+ if (eeprom->type == e1000_eeprom_ich8)
+ return e1000_write_eeprom_ich8(hw, offset, words, data);
+
/* Prepare the EEPROM for writing */
if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
return -E1000_ERR_EEPROM;
@@ -4957,11 +5365,17 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
uint32_t flop = 0;
uint32_t i = 0;
int32_t error = E1000_SUCCESS;
-
- /* The flop register will be used to determine if flash type is STM */
- flop = E1000_READ_REG(hw, FLOP);
+ uint32_t old_bank_offset = 0;
+ uint32_t new_bank_offset = 0;
+ uint32_t sector_retries = 0;
+ uint8_t low_byte = 0;
+ uint8_t high_byte = 0;
+ uint8_t temp_byte = 0;
+ boolean_t sector_write_failed = FALSE;
if (hw->mac_type == e1000_82573) {
+ /* The flop register will be used to determine if flash type is STM */
+ flop = E1000_READ_REG(hw, FLOP);
for (i=0; i < attempts; i++) {
eecd = E1000_READ_REG(hw, EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
@@ -4995,6 +5409,106 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
}
}
+ if (hw->mac_type == e1000_ich8lan && hw->eeprom_shadow_ram != NULL) {
+ /* We're writing to the opposite bank so if we're on bank 1,
+ * write to bank 0 etc. We also need to erase the segment that
+ * is going to be written */
+ if (!(E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL)) {
+ new_bank_offset = hw->flash_bank_size * 2;
+ old_bank_offset = 0;
+ e1000_erase_ich8_4k_segment(hw, 1);
+ } else {
+ old_bank_offset = hw->flash_bank_size * 2;
+ new_bank_offset = 0;
+ e1000_erase_ich8_4k_segment(hw, 0);
+ }
+
+ do {
+ sector_write_failed = FALSE;
+ /* Loop for every byte in the shadow RAM,
+ * which is in units of words. */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ /* Determine whether to write the value stored
+ * in the other NVM bank or a modified value stored
+ * in the shadow RAM */
+ if (hw->eeprom_shadow_ram[i].modified == TRUE) {
+ low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word;
+ e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset,
+ &temp_byte);
+ udelay(100);
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset,
+ low_byte);
+ if (error != E1000_SUCCESS)
+ sector_write_failed = TRUE;
+ high_byte =
+ (uint8_t)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
+ e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1,
+ &temp_byte);
+ udelay(100);
+ } else {
+ e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset,
+ &low_byte);
+ udelay(100);
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset, low_byte);
+ if (error != E1000_SUCCESS)
+ sector_write_failed = TRUE;
+ e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1,
+ &high_byte);
+ }
+
+ /* If the word is 0x13, then make sure the signature bits
+ * (15:14) are 11b until the commit has completed.
+ * This will allow us to write 10b which indicates the
+ * signature is valid. We want to do this after the write
+ * has completed so that we don't mark the segment valid
+ * while the write is still in progress */
+ if (i == E1000_ICH8_NVM_SIG_WORD)
+ high_byte = E1000_ICH8_NVM_SIG_MASK | high_byte;
+
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset + 1, high_byte);
+ if (error != E1000_SUCCESS)
+ sector_write_failed = TRUE;
+
+ if (sector_write_failed == FALSE) {
+ /* Clear the now not used entry in the cache */
+ hw->eeprom_shadow_ram[i].modified = FALSE;
+ hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+ }
+ }
+
+ /* Don't bother writing the segment valid bits if sector
+ * programming failed. */
+ if (sector_write_failed == FALSE) {
+ /* Finally validate the new segment by setting bit 15:14
+ * to 10b in word 0x13 , this can be done without an
+ * erase as well since these bits are 11 to start with
+ * and we need to change bit 14 to 0b */
+ e1000_read_ich8_byte(hw,
+ E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset,
+ &high_byte);
+ high_byte &= 0xBF;
+ error = e1000_verify_write_ich8_byte(hw,
+ E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset,
+ high_byte);
+ if (error != E1000_SUCCESS)
+ sector_write_failed = TRUE;
+
+ /* And invalidate the previously valid segment by setting
+ * its signature word (0x13) high_byte to 0b. This can be
+ * done without an erase because flash erase sets all bits
+ * to 1's. We can write 1's to 0's without an erase */
+ error = e1000_verify_write_ich8_byte(hw,
+ E1000_ICH8_NVM_SIG_WORD * 2 + 1 + old_bank_offset,
+ 0);
+ if (error != E1000_SUCCESS)
+ sector_write_failed = TRUE;
+ }
+ } while (++sector_retries < 10 && sector_write_failed == TRUE);
+ }
+
return error;
}
@@ -5102,15 +5616,19 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
* the other port. */
if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
rar_num -= 1;
+ if (hw->mac_type == e1000_ich8lan)
+ rar_num = E1000_RAR_ENTRIES_ICH8LAN;
+
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
for(i = 1; i < rar_num; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+ E1000_WRITE_FLUSH(hw);
}
}
-#if 0
/******************************************************************************
* Updates the MAC's list of multicast addresses.
*
@@ -5145,6 +5663,8 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
num_rar_entry = E1000_RAR_ENTRIES;
+ if (hw->mac_type == e1000_ich8lan)
+ num_rar_entry = E1000_RAR_ENTRIES_ICH8LAN;
/* Reserve a spot for the Locally Administered Address to work around
* an 82571 issue in which a reset on one port will reload the MAC on
* the other port. */
@@ -5153,14 +5673,19 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
for(i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+ E1000_WRITE_FLUSH(hw);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
num_mta_entry = E1000_NUM_MTA_REGISTERS;
+ if (hw->mac_type == e1000_ich8lan)
+ num_mta_entry = E1000_NUM_MTA_REGISTERS_ICH8LAN;
for(i = 0; i < num_mta_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+ E1000_WRITE_FLUSH(hw);
}
/* Add the new addresses */
@@ -5194,7 +5719,6 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
}
DEBUGOUT("MC Update Complete\n");
}
-#endif /* 0 */
/******************************************************************************
* Hashes an address to determine its location in the multicast table
@@ -5217,24 +5741,46 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
* LSB MSB
*/
case 0:
- /* [47:36] i.e. 0x563 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [47:38] i.e. 0x158 for above example address */
+ hash_value = ((mc_addr[4] >> 6) | (((uint16_t) mc_addr[5]) << 2));
+ } else {
+ /* [47:36] i.e. 0x563 for above example address */
+ hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
+ }
break;
case 1:
- /* [46:35] i.e. 0xAC6 for above example address */
- hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [46:37] i.e. 0x2B1 for above example address */
+ hash_value = ((mc_addr[4] >> 5) | (((uint16_t) mc_addr[5]) << 3));
+ } else {
+ /* [46:35] i.e. 0xAC6 for above example address */
+ hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
+ }
break;
case 2:
- /* [45:34] i.e. 0x5D8 for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
+ if (hw->mac_type == e1000_ich8lan) {
+ /*[45:36] i.e. 0x163 for above example address */
+ hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
+ } else {
+ /* [45:34] i.e. 0x5D8 for above example address */
+ hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
+ }
break;
case 3:
- /* [43:32] i.e. 0x634 for above example address */
- hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [43:34] i.e. 0x18D for above example address */
+ hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
+ } else {
+ /* [43:32] i.e. 0x634 for above example address */
+ hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
+ }
break;
}
hash_value &= 0xFFF;
+ if (hw->mac_type == e1000_ich8lan)
+ hash_value &= 0x3FF;
return hash_value;
}
@@ -5262,6 +5808,8 @@ e1000_mta_set(struct e1000_hw *hw,
* register are determined by the lower 5 bits of the value.
*/
hash_reg = (hash_value >> 5) & 0x7F;
+ if (hw->mac_type == e1000_ich8lan)
+ hash_reg &= 0x1F;
hash_bit = hash_value & 0x1F;
mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg);
@@ -5275,9 +5823,12 @@ e1000_mta_set(struct e1000_hw *hw,
if((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1));
E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp);
+ E1000_WRITE_FLUSH(hw);
} else {
E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
+ E1000_WRITE_FLUSH(hw);
}
}
@@ -5334,7 +5885,9 @@ e1000_rar_set(struct e1000_hw *hw,
}
E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
+ E1000_WRITE_FLUSH(hw);
}
/******************************************************************************
@@ -5351,12 +5904,18 @@ e1000_write_vfta(struct e1000_hw *hw,
{
uint32_t temp;
- if((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
+ if (hw->mac_type == e1000_ich8lan)
+ return;
+
+ if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
+ E1000_WRITE_FLUSH(hw);
} else {
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+ E1000_WRITE_FLUSH(hw);
}
}
@@ -5373,6 +5932,9 @@ e1000_clear_vfta(struct e1000_hw *hw)
uint32_t vfta_offset = 0;
uint32_t vfta_bit_in_reg = 0;
+ if (hw->mac_type == e1000_ich8lan)
+ return;
+
if (hw->mac_type == e1000_82573) {
if (hw->mng_cookie.vlan_id != 0) {
/* The VFTA is a 4096b bit-field, each identifying a single VLAN
@@ -5392,6 +5954,7 @@ e1000_clear_vfta(struct e1000_hw *hw)
* manageability unit */
vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
+ E1000_WRITE_FLUSH(hw);
}
}
@@ -5421,9 +5984,18 @@ e1000_id_led_init(struct e1000_hw * hw)
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
- if((eeprom_data== ID_LED_RESERVED_0000) ||
- (eeprom_data == ID_LED_RESERVED_FFFF)) eeprom_data = ID_LED_DEFAULT;
- for(i = 0; i < 4; i++) {
+
+ if ((hw->mac_type == e1000_82573) &&
+ (eeprom_data == ID_LED_RESERVED_82573))
+ eeprom_data = ID_LED_DEFAULT_82573;
+ else if ((eeprom_data == ID_LED_RESERVED_0000) ||
+ (eeprom_data == ID_LED_RESERVED_FFFF)) {
+ if (hw->mac_type == e1000_ich8lan)
+ eeprom_data = ID_LED_DEFAULT_ICH8LAN;
+ else
+ eeprom_data = ID_LED_DEFAULT;
+ }
+ for (i = 0; i < 4; i++) {
temp = (eeprom_data >> (i << 2)) & led_mask;
switch(temp) {
case ID_LED_ON1_DEF2:
@@ -5519,6 +6091,44 @@ e1000_setup_led(struct e1000_hw *hw)
}
/******************************************************************************
+ * Used on 82571 and later Si that has LED blink bits.
+ * Callers must use their own timer and should have already called
+ * e1000_id_led_init()
+ * Call e1000_cleanup led() to stop blinking
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_blink_led_start(struct e1000_hw *hw)
+{
+ int16_t i;
+ uint32_t ledctl_blink = 0;
+
+ DEBUGFUNC("e1000_id_led_blink_on");
+
+ if (hw->mac_type < e1000_82571) {
+ /* Nothing to do */
+ return E1000_SUCCESS;
+ }
+ if (hw->media_type == e1000_media_type_fiber) {
+ /* always blink LED0 for PCI-E fiber */
+ ledctl_blink = E1000_LEDCTL_LED0_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
+ } else {
+ /* set the blink bit for each LED that's "on" (0x0E) in ledctl_mode2 */
+ ledctl_blink = hw->ledctl_mode2;
+ for (i=0; i < 4; i++)
+ if (((hw->ledctl_mode2 >> (i * 8)) & 0xFF) ==
+ E1000_LEDCTL_MODE_LED_ON)
+ ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8));
+ }
+
+ E1000_WRITE_REG(hw, LEDCTL, ledctl_blink);
+
+ return E1000_SUCCESS;
+}
+
+/******************************************************************************
* Restores the saved state of the SW controlable LED.
*
* hw - Struct containing variables accessed by shared code
@@ -5548,6 +6158,10 @@ e1000_cleanup_led(struct e1000_hw *hw)
return ret_val;
/* Fall Through */
default:
+ if (hw->phy_type == e1000_phy_ife) {
+ e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
+ break;
+ }
/* Restore LEDCTL settings */
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
break;
@@ -5592,7 +6206,10 @@ e1000_led_on(struct e1000_hw *hw)
/* Clear SW Defineable Pin 0 to turn on the LED */
ctrl &= ~E1000_CTRL_SWDPIN0;
ctrl |= E1000_CTRL_SWDPIO0;
- } else if(hw->media_type == e1000_media_type_copper) {
+ } else if (hw->phy_type == e1000_phy_ife) {
+ e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
+ (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
+ } else if (hw->media_type == e1000_media_type_copper) {
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
return E1000_SUCCESS;
}
@@ -5640,7 +6257,10 @@ e1000_led_off(struct e1000_hw *hw)
/* Set SW Defineable Pin 0 to turn off the LED */
ctrl |= E1000_CTRL_SWDPIN0;
ctrl |= E1000_CTRL_SWDPIO0;
- } else if(hw->media_type == e1000_media_type_copper) {
+ } else if (hw->phy_type == e1000_phy_ife) {
+ e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
+ (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
+ } else if (hw->media_type == e1000_media_type_copper) {
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
return E1000_SUCCESS;
}
@@ -5678,12 +6298,16 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, XOFFRXC);
temp = E1000_READ_REG(hw, XOFFTXC);
temp = E1000_READ_REG(hw, FCRUC);
+
+ if (hw->mac_type != e1000_ich8lan) {
temp = E1000_READ_REG(hw, PRC64);
temp = E1000_READ_REG(hw, PRC127);
temp = E1000_READ_REG(hw, PRC255);
temp = E1000_READ_REG(hw, PRC511);
temp = E1000_READ_REG(hw, PRC1023);
temp = E1000_READ_REG(hw, PRC1522);
+ }
+
temp = E1000_READ_REG(hw, GPRC);
temp = E1000_READ_REG(hw, BPRC);
temp = E1000_READ_REG(hw, MPRC);
@@ -5703,12 +6327,16 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, TOTH);
temp = E1000_READ_REG(hw, TPR);
temp = E1000_READ_REG(hw, TPT);
+
+ if (hw->mac_type != e1000_ich8lan) {
temp = E1000_READ_REG(hw, PTC64);
temp = E1000_READ_REG(hw, PTC127);
temp = E1000_READ_REG(hw, PTC255);
temp = E1000_READ_REG(hw, PTC511);
temp = E1000_READ_REG(hw, PTC1023);
temp = E1000_READ_REG(hw, PTC1522);
+ }
+
temp = E1000_READ_REG(hw, MPTC);
temp = E1000_READ_REG(hw, BPTC);
@@ -5731,6 +6359,9 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, IAC);
temp = E1000_READ_REG(hw, ICRXOC);
+
+ if (hw->mac_type == e1000_ich8lan) return;
+
temp = E1000_READ_REG(hw, ICRXPTC);
temp = E1000_READ_REG(hw, ICRXATC);
temp = E1000_READ_REG(hw, ICTXPTC);
@@ -5911,6 +6542,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_width = e1000_bus_width_pciex_1;
break;
case e1000_82571:
+ case e1000_ich8lan:
case e1000_80003es2lan:
hw->bus_type = e1000_bus_type_pci_express;
hw->bus_speed = e1000_bus_speed_2500;
@@ -5948,8 +6580,6 @@ e1000_get_bus_info(struct e1000_hw *hw)
break;
}
}
-
-#if 0
/******************************************************************************
* Reads a value from one of the devices registers using port I/O (as opposed
* memory mapped I/O). Only 82544 and newer devices support port I/O.
@@ -5967,7 +6597,6 @@ e1000_read_reg_io(struct e1000_hw *hw,
e1000_io_write(hw, io_addr, offset);
return e1000_io_read(hw, io_data);
}
-#endif /* 0 */
/******************************************************************************
* Writes a value to one of the devices registers using port I/O (as opposed to
@@ -6012,8 +6641,6 @@ e1000_get_cable_length(struct e1000_hw *hw,
{
int32_t ret_val;
uint16_t agc_value = 0;
- uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
- uint16_t max_agc = 0;
uint16_t i, phy_data;
uint16_t cable_length;
@@ -6086,6 +6713,8 @@ e1000_get_cable_length(struct e1000_hw *hw,
break;
}
} else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
+ uint16_t cur_agc_value;
+ uint16_t min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
{IGP01E1000_PHY_AGC_A,
IGP01E1000_PHY_AGC_B,
@@ -6098,23 +6727,23 @@ e1000_get_cable_length(struct e1000_hw *hw,
if(ret_val)
return ret_val;
- cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
+ cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
- /* Array bound check. */
- if((cur_agc >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
- (cur_agc == 0))
+ /* Value bound check. */
+ if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
+ (cur_agc_value == 0))
return -E1000_ERR_PHY;
- agc_value += cur_agc;
+ agc_value += cur_agc_value;
/* Update minimal AGC value. */
- if(min_agc > cur_agc)
- min_agc = cur_agc;
+ if (min_agc_value > cur_agc_value)
+ min_agc_value = cur_agc_value;
}
/* Remove the minimal AGC result for length < 50m */
- if(agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
- agc_value -= min_agc;
+ if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
+ agc_value -= min_agc_value;
/* Get the average length of the remaining 3 channels */
agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
@@ -6130,7 +6759,10 @@ e1000_get_cable_length(struct e1000_hw *hw,
IGP01E1000_AGC_RANGE) : 0;
*max_length = e1000_igp_cable_length_table[agc_value] +
IGP01E1000_AGC_RANGE;
- } else if (hw->phy_type == e1000_phy_igp_2) {
+ } else if (hw->phy_type == e1000_phy_igp_2 ||
+ hw->phy_type == e1000_phy_igp_3) {
+ uint16_t cur_agc_index, max_agc_index = 0;
+ uint16_t min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
{IGP02E1000_PHY_AGC_A,
IGP02E1000_PHY_AGC_B,
@@ -6145,19 +6777,27 @@ e1000_get_cable_length(struct e1000_hw *hw,
/* Getting bits 15:9, which represent the combination of course and
* fine gain values. The result is a number that can be put into
* the lookup table to obtain the approximate cable length. */
- cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
- IGP02E1000_AGC_LENGTH_MASK;
+ cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+ IGP02E1000_AGC_LENGTH_MASK;
- /* Remove min & max AGC values from calculation. */
- if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
- min_agc = cur_agc;
- if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
- max_agc = cur_agc;
+ /* Array index bound check. */
+ if ((cur_agc_index >= IGP02E1000_AGC_LENGTH_TABLE_SIZE) ||
+ (cur_agc_index == 0))
+ return -E1000_ERR_PHY;
- agc_value += e1000_igp_2_cable_length_table[cur_agc];
+ /* Remove min & max AGC values from calculation. */
+ if (e1000_igp_2_cable_length_table[min_agc_index] >
+ e1000_igp_2_cable_length_table[cur_agc_index])
+ min_agc_index = cur_agc_index;
+ if (e1000_igp_2_cable_length_table[max_agc_index] <
+ e1000_igp_2_cable_length_table[cur_agc_index])
+ max_agc_index = cur_agc_index;
+
+ agc_value += e1000_igp_2_cable_length_table[cur_agc_index];
}
- agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
+ agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
+ e1000_igp_2_cable_length_table[max_agc_index]);
agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
/* Calculate cable length with the error range of +/- 10 meters. */
@@ -6203,7 +6843,8 @@ e1000_check_polarity(struct e1000_hw *hw,
return ret_val;
*polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
M88E1000_PSSR_REV_POLARITY_SHIFT;
- } else if(hw->phy_type == e1000_phy_igp ||
+ } else if (hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_3 ||
hw->phy_type == e1000_phy_igp_2) {
/* Read the Status register to check the speed */
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
@@ -6229,6 +6870,13 @@ e1000_check_polarity(struct e1000_hw *hw,
* 100 Mbps this bit is always 0) */
*polarity = phy_data & IGP01E1000_PSSR_POLARITY_REVERSED;
}
+ } else if (hw->phy_type == e1000_phy_ife) {
+ ret_val = e1000_read_phy_reg(hw, IFE_PHY_EXTENDED_STATUS_CONTROL,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+ *polarity = (phy_data & IFE_PESC_POLARITY_REVERSED) >>
+ IFE_PESC_POLARITY_REVERSED_SHIFT;
}
return E1000_SUCCESS;
}
@@ -6256,7 +6904,8 @@ e1000_check_downshift(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_downshift");
- if(hw->phy_type == e1000_phy_igp ||
+ if (hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_3 ||
hw->phy_type == e1000_phy_igp_2) {
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
&phy_data);
@@ -6273,6 +6922,9 @@ e1000_check_downshift(struct e1000_hw *hw)
hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
M88E1000_PSSR_DOWNSHIFT_SHIFT;
+ } else if (hw->phy_type == e1000_phy_ife) {
+ /* e1000_phy_ife supports 10/100 speed only */
+ hw->speed_downgraded = FALSE;
}
return E1000_SUCCESS;
@@ -6317,7 +6969,9 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
if(speed == SPEED_1000) {
- e1000_get_cable_length(hw, &min_length, &max_length);
+ ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
+ if (ret_val)
+ return ret_val;
if((hw->dsp_config_state == e1000_dsp_config_enabled) &&
min_length >= e1000_igp_cable_length_50) {
@@ -6525,20 +7179,27 @@ static int32_t
e1000_set_d3_lplu_state(struct e1000_hw *hw,
boolean_t active)
{
+ uint32_t phy_ctrl = 0;
int32_t ret_val;
uint16_t phy_data;
DEBUGFUNC("e1000_set_d3_lplu_state");
- if(hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2)
+ if (hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2
+ && hw->phy_type != e1000_phy_igp_3)
return E1000_SUCCESS;
/* During driver activity LPLU should not be used or it will attain link
* from the lowest speeds starting from 10Mbps. The capability is used for
* Dx transitions and states */
- if(hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
+ if (hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
- if(ret_val)
+ if (ret_val)
return ret_val;
+ } else if (hw->mac_type == e1000_ich8lan) {
+ /* MAC writes into PHY register based on the state transition
+ * and start auto-negotiation. SW driver can overwrite the settings
+ * in CSR PHY power control E1000_PHY_CTRL register. */
+ phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
} else {
ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if(ret_val)
@@ -6553,11 +7214,16 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
if(ret_val)
return ret_val;
} else {
+ if (hw->mac_type == e1000_ich8lan) {
+ phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+ E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ } else {
phy_data &= ~IGP02E1000_PM_D3_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
phy_data);
if (ret_val)
return ret_val;
+ }
}
/* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
@@ -6593,17 +7259,22 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
(hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
if(hw->mac_type == e1000_82541_rev_2 ||
- hw->mac_type == e1000_82547_rev_2) {
+ hw->mac_type == e1000_82547_rev_2) {
phy_data |= IGP01E1000_GMII_FLEX_SPD;
ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
if(ret_val)
return ret_val;
} else {
+ if (hw->mac_type == e1000_ich8lan) {
+ phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
+ E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ } else {
phy_data |= IGP02E1000_PM_D3_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
phy_data);
if (ret_val)
return ret_val;
+ }
}
/* When LPLU is enabled we should disable SmartSpeed */
@@ -6638,6 +7309,7 @@ static int32_t
e1000_set_d0_lplu_state(struct e1000_hw *hw,
boolean_t active)
{
+ uint32_t phy_ctrl = 0;
int32_t ret_val;
uint16_t phy_data;
DEBUGFUNC("e1000_set_d0_lplu_state");
@@ -6645,15 +7317,24 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
if(hw->mac_type <= e1000_82547_rev_2)
return E1000_SUCCESS;
+ if (hw->mac_type == e1000_ich8lan) {
+ phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+ } else {
ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if(ret_val)
return ret_val;
+ }
if (!active) {
+ if (hw->mac_type == e1000_ich8lan) {
+ phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
+ E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ } else {
phy_data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
if (ret_val)
return ret_val;
+ }
/* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
* Dx states where the power conservation is most important. During
@@ -6686,10 +7367,15 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
} else {
+ if (hw->mac_type == e1000_ich8lan) {
+ phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
+ E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ } else {
phy_data |= IGP02E1000_PM_D0_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
if (ret_val)
return ret_val;
+ }
/* When LPLU is enabled we should disable SmartSpeed */
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
@@ -6928,8 +7614,10 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
length >>= 2;
/* The device driver writes the relevant command block into the ram area. */
- for (i = 0; i < length; i++)
+ for (i = 0; i < length; i++) {
E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i));
+ E1000_WRITE_FLUSH(hw);
+ }
return E1000_SUCCESS;
}
@@ -6961,15 +7649,18 @@ e1000_mng_write_commit(
* returns - TRUE when the mode is IAMT or FALSE.
****************************************************************************/
boolean_t
-e1000_check_mng_mode(
- struct e1000_hw *hw)
+e1000_check_mng_mode(struct e1000_hw *hw)
{
uint32_t fwsm;
fwsm = E1000_READ_REG(hw, FWSM);
- if((fwsm & E1000_FWSM_MODE_MASK) ==
- (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+ if (hw->mac_type == e1000_ich8lan) {
+ if ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+ return TRUE;
+ } else if ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
return TRUE;
return FALSE;
@@ -7209,7 +7900,6 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
E1000_WRITE_REG(hw, CTRL, ctrl);
}
-#if 0
/***************************************************************************
*
* Enables PCI-Express master access.
@@ -7233,7 +7923,6 @@ e1000_enable_pciex_master(struct e1000_hw *hw)
ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
E1000_WRITE_REG(hw, CTRL, ctrl);
}
-#endif /* 0 */
/*******************************************************************************
*
@@ -7299,8 +7988,10 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
- while(timeout) {
- if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
+ case e1000_ich8lan:
+ while (timeout) {
+ if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD)
+ break;
else msec_delay(1);
timeout--;
}
@@ -7340,7 +8031,7 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
switch (hw->mac_type) {
default:
- msec_delay(10);
+ msec_delay_irq(10);
break;
case e1000_80003es2lan:
/* Separate *_CFG_DONE_* bit for each port */
@@ -7523,6 +8214,13 @@ int32_t
e1000_check_phy_reset_block(struct e1000_hw *hw)
{
uint32_t manc = 0;
+ uint32_t fwsm = 0;
+
+ if (hw->mac_type == e1000_ich8lan) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+ return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS
+ : E1000_BLK_PHY_RESET;
+ }
if (hw->mac_type > e1000_82547_rev_2)
manc = E1000_READ_REG(hw, MANC);
@@ -7549,6 +8247,8 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
if((fwsm & E1000_FWSM_MODE_MASK) != 0)
return TRUE;
break;
+ case e1000_ich8lan:
+ return TRUE;
default:
break;
}
@@ -7556,4 +8256,846 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
}
+/******************************************************************************
+ * Configure PCI-Ex no-snoop
+ *
+ * hw - Struct containing variables accessed by shared code.
+ * no_snoop - Bitmap of no-snoop events.
+ *
+ * returns: E1000_SUCCESS
+ *
+ *****************************************************************************/
+int32_t
+e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+{
+ uint32_t gcr_reg = 0;
+
+ DEBUGFUNC("e1000_set_pci_ex_no_snoop");
+
+ if (hw->bus_type == e1000_bus_type_unknown)
+ e1000_get_bus_info(hw);
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return E1000_SUCCESS;
+
+ if (no_snoop) {
+ gcr_reg = E1000_READ_REG(hw, GCR);
+ gcr_reg &= ~(PCI_EX_NO_SNOOP_ALL);
+ gcr_reg |= no_snoop;
+ E1000_WRITE_REG(hw, GCR, gcr_reg);
+ }
+ if (hw->mac_type == e1000_ich8lan) {
+ uint32_t ctrl_ext;
+
+ E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ }
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Get software semaphore FLAG bit (SWFLAG).
+ * SWFLAG is used to synchronize the access to all shared resource between
+ * SW, FW and HW.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+int32_t
+e1000_get_software_flag(struct e1000_hw *hw)
+{
+ int32_t timeout = PHY_CFG_TIMEOUT;
+ uint32_t extcnf_ctrl;
+
+ DEBUGFUNC("e1000_get_software_flag");
+
+ if (hw->mac_type == e1000_ich8lan) {
+ while (timeout) {
+ extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
+ E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+
+ extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
+ break;
+ msec_delay_irq(1);
+ timeout--;
+ }
+
+ if (!timeout) {
+ DEBUGOUT("FW or HW locks the resource too long.\n");
+ return -E1000_ERR_CONFIG;
+ }
+ }
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Release software semaphore FLAG bit (SWFLAG).
+ * SWFLAG is used to synchronize the access to all shared resource between
+ * SW, FW and HW.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+void
+e1000_release_software_flag(struct e1000_hw *hw)
+{
+ uint32_t extcnf_ctrl;
+
+ DEBUGFUNC("e1000_release_software_flag");
+
+ if (hw->mac_type == e1000_ich8lan) {
+ extcnf_ctrl= E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+ E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ }
+
+ return;
+}
+
+/***************************************************************************
+ *
+ * Disable dynamic power down mode in ife PHY.
+ * It can be used to workaround band-gap problem.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+int32_t
+e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
+{
+ uint16_t phy_data;
+ int32_t ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_ife_disable_dynamic_power_down");
+
+ if (hw->phy_type == e1000_phy_ife) {
+ ret_val = e1000_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN;
+ ret_val = e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, phy_data);
+ }
+
+ return ret_val;
+}
+
+/***************************************************************************
+ *
+ * Enable dynamic power down mode in ife PHY.
+ * It can be used to workaround band-gap problem.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+int32_t
+e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
+{
+ uint16_t phy_data;
+ int32_t ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_ife_enable_dynamic_power_down");
+
+ if (hw->phy_type == e1000_phy_ife) {
+ ret_val = e1000_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN;
+ ret_val = e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, phy_data);
+ }
+
+ return ret_val;
+}
+
+/******************************************************************************
+ * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
+ * register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+int32_t
+e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ uint16_t *data)
+{
+ int32_t error = E1000_SUCCESS;
+ uint32_t flash_bank = 0;
+ uint32_t act_offset = 0;
+ uint32_t bank_offset = 0;
+ uint16_t word = 0;
+ uint16_t i = 0;
+
+ /* We need to know which is the valid flash bank. In the event
+ * that we didn't allocate eeprom_shadow_ram, we may not be
+ * managing flash_bank. So it cannot be trusted and needs
+ * to be updated with each read.
+ */
+ /* Value of bit 22 corresponds to the flash bank we're on. */
+ flash_bank = (E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
+
+ /* Adjust offset appropriately if we're on bank 1 - adjust for word size */
+ bank_offset = flash_bank * (hw->flash_bank_size * 2);
+
+ error = e1000_get_software_flag(hw);
+ if (error != E1000_SUCCESS)
+ return error;
+
+ for (i = 0; i < words; i++) {
+ if (hw->eeprom_shadow_ram != NULL &&
+ hw->eeprom_shadow_ram[offset+i].modified == TRUE) {
+ data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
+ } else {
+ /* The NVM part needs a byte offset, hence * 2 */
+ act_offset = bank_offset + ((offset + i) * 2);
+ error = e1000_read_ich8_word(hw, act_offset, &word);
+ if (error != E1000_SUCCESS)
+ break;
+ data[i] = word;
+ }
+ }
+
+ e1000_release_software_flag(hw);
+
+ return error;
+}
+
+/******************************************************************************
+ * Writes a 16 bit word or words to the EEPROM using the ICH8's flash access
+ * register. Actually, writes are written to the shadow ram cache in the hw
+ * structure hw->e1000_shadow_ram. e1000_commit_shadow_ram flushes this to
+ * the NVM, which occurs when the NVM checksum is updated.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to write
+ * words - number of words to write
+ * data - words to write to the EEPROM
+ *****************************************************************************/
+int32_t
+e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ uint16_t *data)
+{
+ uint32_t i = 0;
+ int32_t error = E1000_SUCCESS;
+
+ error = e1000_get_software_flag(hw);
+ if (error != E1000_SUCCESS)
+ return error;
+
+ /* A driver can write to the NVM only if it has eeprom_shadow_ram
+ * allocated. Subsequent reads to the modified words are read from
+ * this cached structure as well. Writes will only go into this
+ * cached structure unless it's followed by a call to
+ * e1000_update_eeprom_checksum() where it will commit the changes
+ * and clear the "modified" field.
+ */
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < words; i++) {
+ if ((offset + i) < E1000_SHADOW_RAM_WORDS) {
+ hw->eeprom_shadow_ram[offset+i].modified = TRUE;
+ hw->eeprom_shadow_ram[offset+i].eeprom_word = data[i];
+ } else {
+ error = -E1000_ERR_EEPROM;
+ break;
+ }
+ }
+ } else {
+ /* Drivers have the option to not allocate eeprom_shadow_ram as long
+ * as they don't perform any NVM writes. An attempt in doing so
+ * will result in this error.
+ */
+ error = -E1000_ERR_EEPROM;
+ }
+
+ e1000_release_software_flag(hw);
+
+ return error;
+}
+
+/******************************************************************************
+ * This function does initial flash setup so that a new read/write/erase cycle
+ * can be started.
+ *
+ * hw - The pointer to the hw structure
+ ****************************************************************************/
+int32_t
+e1000_ich8_cycle_init(struct e1000_hw *hw)
+{
+ union ich8_hws_flash_status hsfsts;
+ int32_t error = E1000_ERR_EEPROM;
+ int32_t i = 0;
+
+ DEBUGFUNC("e1000_ich8_cycle_init");
+
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+
+ /* May be check the Flash Des Valid bit in Hw status */
+ if (hsfsts.hsf_status.fldesvalid == 0) {
+ DEBUGOUT("Flash descriptor invalid. SW Sequencing must be used.");
+ return error;
+ }
+
+ /* Clear FCERR in Hw status by writing 1 */
+ /* Clear DAEL in Hw status by writing a 1 */
+ hsfsts.hsf_status.flcerr = 1;
+ hsfsts.hsf_status.dael = 1;
+
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval);
+
+ /* Either we should have a hardware SPI cycle in progress bit to check
+ * against, in order to start a new cycle or FDONE bit should be changed
+ * in the hardware so that it is 1 after harware reset, which can then be
+ * used as an indication whether a cycle is in progress or has been
+ * completed .. we should also have some software semaphore mechanism to
+ * guard FDONE or the cycle in progress bit so that two threads access to
+ * those bits can be sequentiallized or a way so that 2 threads dont
+ * start the cycle at the same time */
+
+ if (hsfsts.hsf_status.flcinprog == 0) {
+ /* There is no cycle running at present, so we can start a cycle */
+ /* Begin by setting Flash Cycle Done. */
+ hsfsts.hsf_status.flcdone = 1;
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval);
+ error = E1000_SUCCESS;
+ } else {
+ /* otherwise poll for sometime so the current cycle has a chance
+ * to end before giving up. */
+ for (i = 0; i < ICH8_FLASH_COMMAND_TIMEOUT; i++) {
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcinprog == 0) {
+ error = E1000_SUCCESS;
+ break;
+ }
+ udelay(1);
+ }
+ if (error == E1000_SUCCESS) {
+ /* Successful in waiting for previous cycle to timeout,
+ * now set the Flash Cycle Done. */
+ hsfsts.hsf_status.flcdone = 1;
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval);
+ } else {
+ DEBUGOUT("Flash controller busy, cannot get access");
+ }
+ }
+ return error;
+}
+
+/******************************************************************************
+ * This function starts a flash cycle and waits for its completion
+ *
+ * hw - The pointer to the hw structure
+ ****************************************************************************/
+int32_t
+e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
+{
+ union ich8_hws_flash_ctrl hsflctl;
+ union ich8_hws_flash_status hsfsts;
+ int32_t error = E1000_ERR_EEPROM;
+ uint32_t i = 0;
+
+ /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
+ hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ hsflctl.hsf_ctrl.flcgo = 1;
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+
+ /* wait till FDONE bit is set to 1 */
+ do {
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcdone == 1)
+ break;
+ udelay(1);
+ i++;
+ } while (i < timeout);
+ if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) {
+ error = E1000_SUCCESS;
+ }
+ return error;
+}
+
+/******************************************************************************
+ * Reads a byte or word from the NVM using the ICH8 flash access registers.
+ *
+ * hw - The pointer to the hw structure
+ * index - The index of the byte or word to read.
+ * size - Size of data to read, 1=byte 2=word
+ * data - Pointer to the word to store the value read.
+ *****************************************************************************/
+int32_t
+e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+ uint32_t size, uint16_t* data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ uint32_t flash_linear_address;
+ uint32_t flash_data = 0;
+ int32_t error = -E1000_ERR_EEPROM;
+ int32_t count = 0;
+
+ DEBUGFUNC("e1000_read_ich8_data");
+
+ if (size < 1 || size > 2 || data == 0x0 ||
+ index > ICH8_FLASH_LINEAR_ADDR_MASK)
+ return error;
+
+ flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) +
+ hw->flash_base_addr;
+
+ do {
+ udelay(1);
+ /* Steps */
+ error = e1000_ich8_cycle_init(hw);
+ if (error != E1000_SUCCESS)
+ break;
+
+ hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
+ hsflctl.hsf_ctrl.fldbcount = size - 1;
+ hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_READ;
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+
+ /* Write the last 24 bits of index into Flash Linear address field in
+ * Flash Address */
+ /* TODO: TBD maybe check the index against the size of flash */
+
+ E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address);
+
+ error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT);
+
+ /* Check if FCERR is set to 1, if set to 1, clear it and try the whole
+ * sequence a few more times, else read in (shift in) the Flash Data0,
+ * the order is least significant byte first msb to lsb */
+ if (error == E1000_SUCCESS) {
+ flash_data = E1000_READ_ICH8_REG(hw, ICH8_FLASH_FDATA0);
+ if (size == 1) {
+ *data = (uint8_t)(flash_data & 0x000000FF);
+ } else if (size == 2) {
+ *data = (uint16_t)(flash_data & 0x0000FFFF);
+ }
+ break;
+ } else {
+ /* If we've gotten here, then things are probably completely hosed,
+ * but if the error condition is detected, it won't hurt to give
+ * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr == 1) {
+ /* Repeat for some time before giving up. */
+ continue;
+ } else if (hsfsts.hsf_status.flcdone == 0) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.");
+ break;
+ }
+ }
+ } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT);
+
+ return error;
+}
+
+/******************************************************************************
+ * Writes One /two bytes to the NVM using the ICH8 flash access registers.
+ *
+ * hw - The pointer to the hw structure
+ * index - The index of the byte/word to read.
+ * size - Size of data to read, 1=byte 2=word
+ * data - The byte(s) to write to the NVM.
+ *****************************************************************************/
+int32_t
+e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+ uint16_t data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ uint32_t flash_linear_address;
+ uint32_t flash_data = 0;
+ int32_t error = -E1000_ERR_EEPROM;
+ int32_t count = 0;
+
+ DEBUGFUNC("e1000_write_ich8_data");
+
+ if (size < 1 || size > 2 || data > size * 0xff ||
+ index > ICH8_FLASH_LINEAR_ADDR_MASK)
+ return error;
+
+ flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) +
+ hw->flash_base_addr;
+
+ do {
+ udelay(1);
+ /* Steps */
+ error = e1000_ich8_cycle_init(hw);
+ if (error != E1000_SUCCESS)
+ break;
+
+ hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
+ hsflctl.hsf_ctrl.fldbcount = size -1;
+ hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_WRITE;
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+
+ /* Write the last 24 bits of index into Flash Linear address field in
+ * Flash Address */
+ E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address);
+
+ if (size == 1)
+ flash_data = (uint32_t)data & 0x00FF;
+ else
+ flash_data = (uint32_t)data;
+
+ E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FDATA0, flash_data);
+
+ /* check if FCERR is set to 1 , if set to 1, clear it and try the whole
+ * sequence a few more times else done */
+ error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT);
+ if (error == E1000_SUCCESS) {
+ break;
+ } else {
+ /* If we're here, then things are most likely completely hosed,
+ * but if the error condition is detected, it won't hurt to give
+ * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr == 1) {
+ /* Repeat for some time before giving up. */
+ continue;
+ } else if (hsfsts.hsf_status.flcdone == 0) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.");
+ break;
+ }
+ }
+ } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT);
+
+ return error;
+}
+
+/******************************************************************************
+ * Reads a single byte from the NVM using the ICH8 flash access registers.
+ *
+ * hw - pointer to e1000_hw structure
+ * index - The index of the byte to read.
+ * data - Pointer to a byte to store the value read.
+ *****************************************************************************/
+int32_t
+e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
+{
+ int32_t status = E1000_SUCCESS;
+ uint16_t word = 0;
+
+ status = e1000_read_ich8_data(hw, index, 1, &word);
+ if (status == E1000_SUCCESS) {
+ *data = (uint8_t)word;
+ }
+
+ return status;
+}
+
+/******************************************************************************
+ * Writes a single byte to the NVM using the ICH8 flash access registers.
+ * Performs verification by reading back the value and then going through
+ * a retry algorithm before giving up.
+ *
+ * hw - pointer to e1000_hw structure
+ * index - The index of the byte to write.
+ * byte - The byte to write to the NVM.
+ *****************************************************************************/
+int32_t
+e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
+{
+ int32_t error = E1000_SUCCESS;
+ int32_t program_retries;
+ uint8_t temp_byte;
+
+ e1000_write_ich8_byte(hw, index, byte);
+ udelay(100);
+
+ for (program_retries = 0; program_retries < 100; program_retries++) {
+ e1000_read_ich8_byte(hw, index, &temp_byte);
+ if (temp_byte == byte)
+ break;
+ udelay(10);
+ e1000_write_ich8_byte(hw, index, byte);
+ udelay(100);
+ }
+ if (program_retries == 100)
+ error = E1000_ERR_EEPROM;
+
+ return error;
+}
+
+/******************************************************************************
+ * Writes a single byte to the NVM using the ICH8 flash access registers.
+ *
+ * hw - pointer to e1000_hw structure
+ * index - The index of the byte to read.
+ * data - The byte to write to the NVM.
+ *****************************************************************************/
+int32_t
+e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
+{
+ int32_t status = E1000_SUCCESS;
+ uint16_t word = (uint16_t)data;
+
+ status = e1000_write_ich8_data(hw, index, 1, word);
+
+ return status;
+}
+
+/******************************************************************************
+ * Reads a word from the NVM using the ICH8 flash access registers.
+ *
+ * hw - pointer to e1000_hw structure
+ * index - The starting byte index of the word to read.
+ * data - Pointer to a word to store the value read.
+ *****************************************************************************/
+int32_t
+e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
+{
+ int32_t status = E1000_SUCCESS;
+ status = e1000_read_ich8_data(hw, index, 2, data);
+ return status;
+}
+
+/******************************************************************************
+ * Writes a word to the NVM using the ICH8 flash access registers.
+ *
+ * hw - pointer to e1000_hw structure
+ * index - The starting byte index of the word to read.
+ * data - The word to write to the NVM.
+ *****************************************************************************/
+int32_t
+e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
+{
+ int32_t status = E1000_SUCCESS;
+ status = e1000_write_ich8_data(hw, index, 2, data);
+ return status;
+}
+
+/******************************************************************************
+ * Erases the bank specified. Each bank is a 4k block. Segments are 0 based.
+ * segment N is 4096 * N + flash_reg_addr.
+ *
+ * hw - pointer to e1000_hw structure
+ * segment - 0 for first segment, 1 for second segment, etc.
+ *****************************************************************************/
+int32_t
+e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ uint32_t flash_linear_address;
+ int32_t count = 0;
+ int32_t error = E1000_ERR_EEPROM;
+ int32_t iteration, seg_size;
+ int32_t sector_size;
+ int32_t j = 0;
+ int32_t error_flag = 0;
+
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+
+ /* Determine HW Sector size: Read BERASE bits of Hw flash Status register */
+ /* 00: The Hw sector is 256 bytes, hence we need to erase 16
+ * consecutive sectors. The start index for the nth Hw sector can be
+ * calculated as = segment * 4096 + n * 256
+ * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
+ * The start index for the nth Hw sector can be calculated
+ * as = segment * 4096
+ * 10: Error condition
+ * 11: The Hw sector size is much bigger than the size asked to
+ * erase...error condition */
+ if (hsfsts.hsf_status.berasesz == 0x0) {
+ /* Hw sector size 256 */
+ sector_size = seg_size = ICH8_FLASH_SEG_SIZE_256;
+ iteration = ICH8_FLASH_SECTOR_SIZE / ICH8_FLASH_SEG_SIZE_256;
+ } else if (hsfsts.hsf_status.berasesz == 0x1) {
+ sector_size = seg_size = ICH8_FLASH_SEG_SIZE_4K;
+ iteration = 1;
+ } else if (hsfsts.hsf_status.berasesz == 0x3) {
+ sector_size = seg_size = ICH8_FLASH_SEG_SIZE_64K;
+ iteration = 1;
+ } else {
+ return error;
+ }
+
+ for (j = 0; j < iteration ; j++) {
+ do {
+ count++;
+ /* Steps */
+ error = e1000_ich8_cycle_init(hw);
+ if (error != E1000_SUCCESS) {
+ error_flag = 1;
+ break;
+ }
+
+ /* Write a value 11 (block Erase) in Flash Cycle field in Hw flash
+ * Control */
+ hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL);
+ hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_ERASE;
+ E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval);
+
+ /* Write the last 24 bits of an index within the block into Flash
+ * Linear address field in Flash Address. This probably needs to
+ * be calculated here based off the on-chip segment size and the
+ * software segment size assumed (4K) */
+ /* TBD */
+ flash_linear_address = segment * sector_size + j * seg_size;
+ flash_linear_address &= ICH8_FLASH_LINEAR_ADDR_MASK;
+ flash_linear_address += hw->flash_base_addr;
+
+ E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address);
+
+ error = e1000_ich8_flash_cycle(hw, 1000000);
+ /* Check if FCERR is set to 1. If 1, clear it and try the whole
+ * sequence a few more times else Done */
+ if (error == E1000_SUCCESS) {
+ break;
+ } else {
+ hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr == 1) {
+ /* repeat for some time before giving up */
+ continue;
+ } else if (hsfsts.hsf_status.flcdone == 0) {
+ error_flag = 1;
+ break;
+ }
+ }
+ } while ((count < ICH8_FLASH_CYCLE_REPEAT_COUNT) && !error_flag);
+ if (error_flag == 1)
+ break;
+ }
+ if (error_flag != 1)
+ error = E1000_SUCCESS;
+ return error;
+}
+
+/******************************************************************************
+ *
+ * Reverse duplex setting without breaking the link.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ *****************************************************************************/
+int32_t
+e1000_duplex_reversal(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+
+ if (hw->phy_type != e1000_phy_igp_3)
+ return E1000_SUCCESS;
+
+ ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data ^= MII_CR_FULL_DUPLEX;
+
+ ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_read_phy_reg(hw, IGP3E1000_PHY_MISC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= IGP3_PHY_MISC_DUPLEX_MANUAL_SET;
+ ret_val = e1000_write_phy_reg(hw, IGP3E1000_PHY_MISC_CTRL, phy_data);
+
+ return ret_val;
+}
+
+int32_t
+e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ uint32_t cnf_base_addr, uint32_t cnf_size)
+{
+ uint32_t ret_val = E1000_SUCCESS;
+ uint16_t word_addr, reg_data, reg_addr;
+ uint16_t i;
+
+ /* cnf_base_addr is in DWORD */
+ word_addr = (uint16_t)(cnf_base_addr << 1);
+
+ /* cnf_size is returned in size of dwords */
+ for (i = 0; i < cnf_size; i++) {
+ ret_val = e1000_read_eeprom(hw, (word_addr + i*2), 1, &reg_data);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_read_eeprom(hw, (word_addr + i*2 + 1), 1, &reg_addr);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_get_software_flag(hw);
+ if (ret_val != E1000_SUCCESS)
+ return ret_val;
+
+ ret_val = e1000_write_phy_reg_ex(hw, (uint32_t)reg_addr, reg_data);
+
+ e1000_release_software_flag(hw);
+ }
+
+ return ret_val;
+}
+
+
+int32_t
+e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+{
+ uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
+
+ if (hw->phy_type != e1000_phy_igp_3)
+ return E1000_SUCCESS;
+
+ /* Check if SW needs configure the PHY */
+ reg_data = E1000_READ_REG(hw, FEXTNVM);
+ if (!(reg_data & FEXTNVM_SW_CONFIG))
+ return E1000_SUCCESS;
+
+ /* Wait for basic configuration completes before proceeding*/
+ loop = 0;
+ do {
+ reg_data = E1000_READ_REG(hw, STATUS) & E1000_STATUS_LAN_INIT_DONE;
+ udelay(100);
+ loop++;
+ } while ((!reg_data) && (loop < 50));
+
+ /* Clear the Init Done bit for the next init event */
+ reg_data = E1000_READ_REG(hw, STATUS);
+ reg_data &= ~E1000_STATUS_LAN_INIT_DONE;
+ E1000_WRITE_REG(hw, STATUS, reg_data);
+
+ /* Make sure HW does not configure LCD from PHY extended configuration
+ before SW configuration */
+ reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+ if ((reg_data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) == 0x0000) {
+ reg_data = E1000_READ_REG(hw, EXTCNF_SIZE);
+ cnf_size = reg_data & E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH;
+ cnf_size >>= 16;
+ if (cnf_size) {
+ reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+ cnf_base_addr = reg_data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER;
+ /* cnf_base_addr is in DWORD */
+ cnf_base_addr >>= 16;
+
+ /* Configure LCD from extended configuration region. */
+ ret_val = e1000_init_lcd_from_nvm_config_region(hw, cnf_base_addr,
+ cnf_size);
+ if (ret_val)
+ return ret_val;
+ }
+ }
+
+ return E1000_SUCCESS;
+}
+
+
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 467c9ed944f8..f9341e3276b3 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -62,6 +62,7 @@ typedef enum {
e1000_82572,
e1000_82573,
e1000_80003es2lan,
+ e1000_ich8lan,
e1000_num_macs
} e1000_mac_type;
@@ -70,6 +71,7 @@ typedef enum {
e1000_eeprom_spi,
e1000_eeprom_microwire,
e1000_eeprom_flash,
+ e1000_eeprom_ich8,
e1000_eeprom_none, /* No NVM support */
e1000_num_eeprom_types
} e1000_eeprom_type;
@@ -98,6 +100,11 @@ typedef enum {
e1000_fc_default = 0xFF
} e1000_fc_type;
+struct e1000_shadow_ram {
+ uint16_t eeprom_word;
+ boolean_t modified;
+};
+
/* PCI bus types */
typedef enum {
e1000_bus_type_unknown = 0,
@@ -218,6 +225,8 @@ typedef enum {
e1000_phy_igp,
e1000_phy_igp_2,
e1000_phy_gg82563,
+ e1000_phy_igp_3,
+ e1000_phy_ife,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
@@ -313,6 +322,10 @@ int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy
int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw);
+void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
+int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
+int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
@@ -331,6 +344,7 @@ uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */
#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */
#define E1000_MNG_IAMT_MODE 0x3
+#define E1000_MNG_ICH_IAMT_MODE 0x2
#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */
#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */
@@ -388,6 +402,8 @@ int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
int32_t e1000_read_mac_addr(struct e1000_hw * hw);
int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
+void e1000_release_software_flag(struct e1000_hw *hw);
+int32_t e1000_get_software_flag(struct e1000_hw *hw);
/* Filters (multicast, vlan, receive) */
void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
@@ -401,6 +417,7 @@ int32_t e1000_setup_led(struct e1000_hw *hw);
int32_t e1000_cleanup_led(struct e1000_hw *hw);
int32_t e1000_led_on(struct e1000_hw *hw);
int32_t e1000_led_off(struct e1000_hw *hw);
+int32_t e1000_blink_led_start(struct e1000_hw *hw);
/* Adaptive IFS Functions */
@@ -422,6 +439,29 @@ int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
void e1000_release_software_semaphore(struct e1000_hw *hw);
int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
+int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
+
+int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
+ uint8_t *data);
+int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
+ uint8_t byte);
+int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
+ uint8_t byte);
+int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
+ uint16_t *data);
+int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+ uint32_t size, uint16_t *data);
+int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+ uint16_t words, uint16_t *data);
+int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+ uint16_t words, uint16_t *data);
+int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment);
+
+
+#define E1000_READ_REG_IO(a, reg) \
+ e1000_read_reg_io((a), E1000_##reg)
+#define E1000_WRITE_REG_IO(a, reg, val) \
+ e1000_write_reg_io((a), E1000_##reg, val)
/* PCI Device IDs */
#define E1000_DEV_ID_82542 0x1000
@@ -446,6 +486,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
#define E1000_DEV_ID_82541EI 0x1013
#define E1000_DEV_ID_82541EI_MOBILE 0x1018
+#define E1000_DEV_ID_82541ER_LOM 0x1014
#define E1000_DEV_ID_82541ER 0x1078
#define E1000_DEV_ID_82547GI 0x1075
#define E1000_DEV_ID_82541GI 0x1076
@@ -457,18 +498,28 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82547EI_MOBILE 0x101A
#define E1000_DEV_ID_82571EB_COPPER 0x105E
#define E1000_DEV_ID_82571EB_FIBER 0x105F
#define E1000_DEV_ID_82571EB_SERDES 0x1060
#define E1000_DEV_ID_82572EI_COPPER 0x107D
#define E1000_DEV_ID_82572EI_FIBER 0x107E
#define E1000_DEV_ID_82572EI_SERDES 0x107F
+#define E1000_DEV_ID_82572EI 0x10B9
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
#define E1000_DEV_ID_82573L 0x109A
#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB
+
+#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049
+#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A
+#define E1000_DEV_ID_ICH8_IGP_C 0x104B
+#define E1000_DEV_ID_ICH8_IFE 0x104C
+#define E1000_DEV_ID_ICH8_IGP_M 0x104D
#define NODE_ADDRESS_SIZE 6
@@ -539,6 +590,14 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
E1000_IMS_RXSEQ | \
E1000_IMS_LSC)
+/* Additional interrupts need to be handled for e1000_ich8lan:
+ DSW = The FW changed the status of the DISSW bit in FWSM
+ PHYINT = The LAN connected device generates an interrupt
+ EPRST = Manageability reset event */
+#define IMS_ICH8LAN_ENABLE_MASK (\
+ E1000_IMS_DSW | \
+ E1000_IMS_PHYINT | \
+ E1000_IMS_EPRST)
/* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor. We
@@ -546,6 +605,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
* E1000_RAR_ENTRIES - 1 multicast addresses.
*/
#define E1000_RAR_ENTRIES 15
+#define E1000_RAR_ENTRIES_ICH8LAN 7
#define MIN_NUMBER_OF_DESCRIPTORS 8
#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8
@@ -767,6 +827,9 @@ struct e1000_data_desc {
#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+#define E1000_NUM_UNICAST_ICH8LAN 7
+#define E1000_MC_TBL_SIZE_ICH8LAN 32
+
/* Receive Address Register */
struct e1000_rar {
@@ -776,6 +839,7 @@ struct e1000_rar {
/* Number of entries in the Multicast Table Array (MTA). */
#define E1000_NUM_MTA_REGISTERS 128
+#define E1000_NUM_MTA_REGISTERS_ICH8LAN 32
/* IPv4 Address Table Entry */
struct e1000_ipv4_at_entry {
@@ -786,6 +850,7 @@ struct e1000_ipv4_at_entry {
/* Four wakeup IP addresses are supported */
#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4
#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX
+#define E1000_IP4AT_SIZE_ICH8LAN 3
#define E1000_IP6AT_SIZE 1
/* IPv6 Address Table Entry */
@@ -844,6 +909,7 @@ struct e1000_ffvt_entry {
#define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
+#define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
@@ -872,6 +938,8 @@ struct e1000_ffvt_entry {
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
+#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
+#define FEXTNVM_SW_CONFIG 0x0001
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
@@ -899,11 +967,13 @@ struct e1000_ffvt_entry {
#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
-#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
+#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */
+#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */
+#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
@@ -1050,6 +1120,7 @@ struct e1000_ffvt_entry {
#define E1000_82542_FLA E1000_FLA
#define E1000_82542_MDIC E1000_MDIC
#define E1000_82542_SCTL E1000_SCTL
+#define E1000_82542_FEXTNVM E1000_FEXTNVM
#define E1000_82542_FCAL E1000_FCAL
#define E1000_82542_FCAH E1000_FCAH
#define E1000_82542_FCT E1000_FCT
@@ -1073,6 +1144,19 @@ struct e1000_ffvt_entry {
#define E1000_82542_RDLEN0 E1000_82542_RDLEN
#define E1000_82542_RDH0 E1000_82542_RDH
#define E1000_82542_RDT0 E1000_82542_RDT
+#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8)) /* Split and Replication
+ * RX Control - RW */
+#define E1000_82542_DCA_RXCTRL(_n) (0x02814 + ((_n) << 8))
+#define E1000_82542_RDBAH3 0x02B04 /* RX Desc Base High Queue 3 - RW */
+#define E1000_82542_RDBAL3 0x02B00 /* RX Desc Low Queue 3 - RW */
+#define E1000_82542_RDLEN3 0x02B08 /* RX Desc Length Queue 3 - RW */
+#define E1000_82542_RDH3 0x02B10 /* RX Desc Head Queue 3 - RW */
+#define E1000_82542_RDT3 0x02B18 /* RX Desc Tail Queue 3 - RW */
+#define E1000_82542_RDBAL2 0x02A00 /* RX Desc Base Low Queue 2 - RW */
+#define E1000_82542_RDBAH2 0x02A04 /* RX Desc Base High Queue 2 - RW */
+#define E1000_82542_RDLEN2 0x02A08 /* RX Desc Length Queue 2 - RW */
+#define E1000_82542_RDH2 0x02A10 /* RX Desc Head Queue 2 - RW */
+#define E1000_82542_RDT2 0x02A18 /* RX Desc Tail Queue 2 - RW */
#define E1000_82542_RDTR1 0x00130
#define E1000_82542_RDBAL1 0x00138
#define E1000_82542_RDBAH1 0x0013C
@@ -1110,11 +1194,14 @@ struct e1000_ffvt_entry {
#define E1000_82542_FLOP E1000_FLOP
#define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL
#define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE
+#define E1000_82542_PHY_CTRL E1000_PHY_CTRL
#define E1000_82542_ERT E1000_ERT
#define E1000_82542_RXDCTL E1000_RXDCTL
+#define E1000_82542_RXDCTL1 E1000_RXDCTL1
#define E1000_82542_RADV E1000_RADV
#define E1000_82542_RSRPD E1000_RSRPD
#define E1000_82542_TXDMAC E1000_TXDMAC
+#define E1000_82542_KABGTXD E1000_KABGTXD
#define E1000_82542_TDFHS E1000_TDFHS
#define E1000_82542_TDFTS E1000_TDFTS
#define E1000_82542_TDFPC E1000_TDFPC
@@ -1310,13 +1397,16 @@ struct e1000_hw_stats {
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t __iomem *hw_addr;
+ uint8_t *hw_addr;
uint8_t *flash_address;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
uint32_t phy_init_script;
e1000_media_type media_type;
void *back;
+ struct e1000_shadow_ram *eeprom_shadow_ram;
+ uint32_t flash_bank_size;
+ uint32_t flash_base_addr;
e1000_fc_type fc;
e1000_bus_speed bus_speed;
e1000_bus_width bus_width;
@@ -1328,6 +1418,7 @@ struct e1000_hw {
uint32_t asf_firmware_present;
uint32_t eeprom_semaphore_present;
uint32_t swfw_sync_present;
+ uint32_t swfwhw_semaphore_present;
unsigned long io_base;
uint32_t phy_id;
uint32_t phy_revision;
@@ -1387,6 +1478,7 @@ struct e1000_hw {
boolean_t in_ifs_mode;
boolean_t mng_reg_access_disabled;
boolean_t leave_av_bit_off;
+ boolean_t kmrn_lock_loss_workaround_disabled;
};
@@ -1435,6 +1527,7 @@ struct e1000_hw {
#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */
#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
+#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */
/* Device Status */
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
@@ -1449,6 +1542,8 @@ struct e1000_hw {
#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
+#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion
+ by EEPROM/Flash */
#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */
#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
@@ -1506,6 +1601,10 @@ struct e1000_hw {
#define E1000_STM_OPCODE 0xDB00
#define E1000_HICR_FW_RESET 0xC0
+#define E1000_SHADOW_RAM_WORDS 2048
+#define E1000_ICH8_NVM_SIG_WORD 0x13
+#define E1000_ICH8_NVM_SIG_MASK 0xC0
+
/* EEPROM Read */
#define E1000_EERD_START 0x00000001 /* Start Read */
#define E1000_EERD_DONE 0x00000010 /* Read Done */
@@ -1551,7 +1650,6 @@ struct e1000_hw {
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
-#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */
#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
@@ -1591,12 +1689,31 @@ struct e1000_hw {
#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800
/* In-Band Control */
+#define E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT 0x00000500
#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010
/* Half-Duplex Control */
#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000
+#define E1000_KUMCTRLSTA_OFFSET_K0S_CTRL 0x0000001E
+
+#define E1000_KUMCTRLSTA_DIAG_FELPBK 0x2000
+#define E1000_KUMCTRLSTA_DIAG_NELPBK 0x1000
+
+#define E1000_KUMCTRLSTA_K0S_100_EN 0x2000
+#define E1000_KUMCTRLSTA_K0S_GBE_EN 0x1000
+#define E1000_KUMCTRLSTA_K0S_ENTRY_LATENCY_MASK 0x0003
+
+#define E1000_KABGTXD_BGSQLBIAS 0x00050000
+
+#define E1000_PHY_CTRL_SPD_EN 0x00000001
+#define E1000_PHY_CTRL_D0A_LPLU 0x00000002
+#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004
+#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008
+#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040
+#define E1000_PHY_CTRL_B2B_EN 0x00000080
+
/* LED Control */
#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
#define E1000_LEDCTL_LED0_MODE_SHIFT 0
@@ -1666,6 +1783,9 @@ struct e1000_hw {
#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */
#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */
#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */
+#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */
+#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */
+#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */
/* Interrupt Cause Set */
#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -1692,6 +1812,9 @@ struct e1000_hw {
#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_ICS_DSW E1000_ICR_DSW
+#define E1000_ICS_PHYINT E1000_ICR_PHYINT
+#define E1000_ICS_EPRST E1000_ICR_EPRST
/* Interrupt Mask Set */
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -1718,6 +1841,9 @@ struct e1000_hw {
#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_IMS_DSW E1000_ICR_DSW
+#define E1000_IMS_PHYINT E1000_ICR_PHYINT
+#define E1000_IMS_EPRST E1000_ICR_EPRST
/* Interrupt Mask Clear */
#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -1744,6 +1870,9 @@ struct e1000_hw {
#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_IMC_DSW E1000_ICR_DSW
+#define E1000_IMC_PHYINT E1000_ICR_PHYINT
+#define E1000_IMC_EPRST E1000_ICR_EPRST
/* Receive Control */
#define E1000_RCTL_RST 0x00000001 /* Software reset */
@@ -1918,9 +2047,10 @@ struct e1000_hw {
#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
-#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
@@ -2010,6 +2140,15 @@ struct e1000_hw {
#define E1000_FWSM_MODE_SHIFT 1
#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */
+#define E1000_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */
+#define E1000_FWSM_DISSW 0x10000000 /* FW disable SW Write Access */
+#define E1000_FWSM_SKUSEL_MASK 0x60000000 /* LAN SKU select */
+#define E1000_FWSM_SKUEL_SHIFT 29
+#define E1000_FWSM_SKUSEL_EMB 0x0 /* Embedded SKU */
+#define E1000_FWSM_SKUSEL_CONS 0x1 /* Consumer SKU */
+#define E1000_FWSM_SKUSEL_PERF_100 0x2 /* Perf & Corp 10/100 SKU */
+#define E1000_FWSM_SKUSEL_PERF_GBE 0x3 /* Perf & Copr GbE SKU */
+
/* FFLT Debug Register */
#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */
@@ -2082,6 +2221,8 @@ struct e1000_host_command_info {
E1000_GCR_TXDSCW_NO_SNOOP | \
E1000_GCR_TXDSCR_NO_SNOOP)
+#define PCI_EX_82566_SNOOP_ALL PCI_EX_NO_SNOOP_ALL
+
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
@@ -2140,8 +2281,10 @@ struct e1000_host_command_info {
#define EEPROM_PHY_CLASS_WORD 0x0007
#define EEPROM_INIT_CONTROL1_REG 0x000A
#define EEPROM_INIT_CONTROL2_REG 0x000F
+#define EEPROM_SWDEF_PINS_CTRL_PORT_1 0x0010
#define EEPROM_INIT_CONTROL3_PORT_B 0x0014
#define EEPROM_INIT_3GIO_3 0x001A
+#define EEPROM_SWDEF_PINS_CTRL_PORT_0 0x0020
#define EEPROM_INIT_CONTROL3_PORT_A 0x0024
#define EEPROM_CFG 0x0012
#define EEPROM_FLASH_VERSION 0x0032
@@ -2153,10 +2296,16 @@ struct e1000_host_command_info {
/* Word definitions for ID LED Settings */
#define ID_LED_RESERVED_0000 0x0000
#define ID_LED_RESERVED_FFFF 0xFFFF
+#define ID_LED_RESERVED_82573 0xF746
+#define ID_LED_DEFAULT_82573 0x1811
#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \
(ID_LED_OFF1_OFF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_DEF1_DEF2))
+#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \
+ (ID_LED_DEF1_OFF2 << 8) | \
+ (ID_LED_DEF1_ON2 << 4) | \
+ (ID_LED_DEF1_DEF2))
#define ID_LED_DEF1_DEF2 0x1
#define ID_LED_DEF1_ON2 0x2
#define ID_LED_DEF1_OFF2 0x3
@@ -2191,6 +2340,11 @@ struct e1000_host_command_info {
#define EEPROM_WORD0F_ASM_DIR 0x2000
#define EEPROM_WORD0F_ANE 0x0800
#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
+#define EEPROM_WORD0F_LPLU 0x0001
+
+/* Mask bits for fields in Word 0x10/0x20 of the EEPROM */
+#define EEPROM_WORD1020_GIGA_DISABLE 0x0010
+#define EEPROM_WORD1020_GIGA_DISABLE_NON_D0A 0x0008
/* Mask bits for fields in Word 0x1a of the EEPROM */
#define EEPROM_WORD1A_ASPM_MASK 0x000C
@@ -2265,23 +2419,29 @@ struct e1000_host_command_info {
#define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040
-#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x1FFF0000
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x0FFF0000
#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF
#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000
+#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
/* PBA constants */
+#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */
#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
#define E1000_PBA_30K 0x001E
#define E1000_PBA_32K 0x0020
+#define E1000_PBA_34K 0x0022
#define E1000_PBA_38K 0x0026
#define E1000_PBA_40K 0x0028
#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
+#define E1000_PBS_16K E1000_PBA_16K
+
/* Flow Control Constants */
#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
@@ -2336,7 +2496,7 @@ struct e1000_host_command_info {
/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */
#define AUTO_READ_DONE_TIMEOUT 10
/* Number of milliseconds we wait for PHY configuration done after MAC reset */
-#define PHY_CFG_TIMEOUT 40
+#define PHY_CFG_TIMEOUT 100
#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
@@ -2764,6 +2924,17 @@ struct e1000_host_command_info {
#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
+/* M88EC018 Rev 2 specific DownShift settings */
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00
+
/* IGP01E1000 Specific Port Config Register - R/W */
#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010
#define IGP01E1000_PSCFR_PRE_EN 0x0020
@@ -2990,6 +3161,221 @@ struct e1000_host_command_info {
#define L1LXT971A_PHY_ID 0x001378E0
#define GG82563_E_PHY_ID 0x01410CA0
+
+/* Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define PHY_PAGE_SHIFT 5
+#define PHY_REG(page, reg) \
+ (((page) << PHY_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+
+#define IGP3_PHY_PORT_CTRL \
+ PHY_REG(769, 17) /* Port General Configuration */
+#define IGP3_PHY_RATE_ADAPT_CTRL \
+ PHY_REG(769, 25) /* Rate Adapter Control Register */
+
+#define IGP3_KMRN_FIFO_CTRL_STATS \
+ PHY_REG(770, 16) /* KMRN FIFO's control/status register */
+#define IGP3_KMRN_POWER_MNG_CTRL \
+ PHY_REG(770, 17) /* KMRN Power Management Control Register */
+#define IGP3_KMRN_INBAND_CTRL \
+ PHY_REG(770, 18) /* KMRN Inband Control Register */
+#define IGP3_KMRN_DIAG \
+ PHY_REG(770, 19) /* KMRN Diagnostic register */
+#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 /* RX PCS is not synced */
+#define IGP3_KMRN_ACK_TIMEOUT \
+ PHY_REG(770, 20) /* KMRN Acknowledge Timeouts register */
+
+#define IGP3_VR_CTRL \
+ PHY_REG(776, 18) /* Voltage regulator control register */
+#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */
+
+#define IGP3_CAPABILITY \
+ PHY_REG(776, 19) /* IGP3 Capability Register */
+
+/* Capabilities for SKU Control */
+#define IGP3_CAP_INITIATE_TEAM 0x0001 /* Able to initiate a team */
+#define IGP3_CAP_WFM 0x0002 /* Support WoL and PXE */
+#define IGP3_CAP_ASF 0x0004 /* Support ASF */
+#define IGP3_CAP_LPLU 0x0008 /* Support Low Power Link Up */
+#define IGP3_CAP_DC_AUTO_SPEED 0x0010 /* Support AC/DC Auto Link Speed */
+#define IGP3_CAP_SPD 0x0020 /* Support Smart Power Down */
+#define IGP3_CAP_MULT_QUEUE 0x0040 /* Support 2 tx & 2 rx queues */
+#define IGP3_CAP_RSS 0x0080 /* Support RSS */
+#define IGP3_CAP_8021PQ 0x0100 /* Support 802.1Q & 802.1p */
+#define IGP3_CAP_AMT_CB 0x0200 /* Support active manageability and circuit breaker */
+
+#define IGP3_PPC_JORDAN_EN 0x0001
+#define IGP3_PPC_JORDAN_GIGA_SPEED 0x0002
+
+#define IGP3_KMRN_PMC_EE_IDLE_LINK_DIS 0x0001
+#define IGP3_KMRN_PMC_K0S_ENTRY_LATENCY_MASK 0x001E
+#define IGP3_KMRN_PMC_K0S_MODE1_EN_GIGA 0x0020
+#define IGP3_KMRN_PMC_K0S_MODE1_EN_100 0x0040
+
+#define IGP3E1000_PHY_MISC_CTRL 0x1B /* Misc. Ctrl register */
+#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Duplex Manual Set */
+
+#define IGP3_KMRN_EXT_CTRL PHY_REG(770, 18)
+#define IGP3_KMRN_EC_DIS_INBAND 0x0080
+
+#define IGP03E1000_E_PHY_ID 0x02A80390
+#define IFE_E_PHY_ID 0x02A80330 /* 10/100 PHY */
+#define IFE_PLUS_E_PHY_ID 0x02A80320
+#define IFE_C_E_PHY_ID 0x02A80310
+
+#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 /* 100BaseTx Extended Status, Control and Address */
+#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */
+#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False Carrier Counter */
+#define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnet Counter */
+#define IFE_PHY_RCV_ERROT_FRAME 0x15 /* 100BaseTx Receive Error Frame Counter */
+#define IFE_PHY_RCV_SYMBOL_ERR 0x16 /* Receive Symbol Error Counter */
+#define IFE_PHY_PREM_EOF_ERR 0x17 /* 100BaseTx Receive Premature End Of Frame Error Counter */
+#define IFE_PHY_RCV_EOF_ERR 0x18 /* 10BaseT Receive End Of Frame Error Counter */
+#define IFE_PHY_TX_JABBER_DETECT 0x19 /* 10BaseT Transmit Jabber Detect Counter */
+#define IFE_PHY_EQUALIZER 0x1A /* PHY Equalizer Control and Status */
+#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY special control and LED configuration */
+#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control register */
+#define IFE_PHY_HWI_CONTROL 0x1D /* Hardware Integrity Control (HWI) */
+
+#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE 0x2000 /* Defaut 1 = Disable auto reduced power down */
+#define IFE_PESC_100BTX_POWER_DOWN 0x0400 /* Indicates the power state of 100BASE-TX */
+#define IFE_PESC_10BTX_POWER_DOWN 0x0200 /* Indicates the power state of 10BASE-T */
+#define IFE_PESC_POLARITY_REVERSED 0x0100 /* Indicates 10BASE-T polarity */
+#define IFE_PESC_PHY_ADDR_MASK 0x007C /* Bit 6:2 for sampled PHY address */
+#define IFE_PESC_SPEED 0x0002 /* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */
+#define IFE_PESC_DUPLEX 0x0001 /* Auto-negotiation duplex result 1=Full, 0=Half */
+#define IFE_PESC_POLARITY_REVERSED_SHIFT 8
+
+#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* 1 = Dyanmic Power Down disabled */
+#define IFE_PSC_FORCE_POLARITY 0x0020 /* 1=Reversed Polarity, 0=Normal */
+#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 /* 1=Auto Polarity Disabled, 0=Enabled */
+#define IFE_PSC_JABBER_FUNC_DISABLE 0x0001 /* 1=Jabber Disabled, 0=Normal Jabber Operation */
+#define IFE_PSC_FORCE_POLARITY_SHIFT 5
+#define IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT 4
+
+#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable MDI/MDI-X feature, default 0=disabled */
+#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDIX-X, 0=force MDI */
+#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
+#define IFE_PMC_AUTO_MDIX_COMPLETE 0x0010 /* Resolution algorthm is completed */
+#define IFE_PMC_MDIX_MODE_SHIFT 6
+#define IFE_PHC_MDIX_RESET_ALL_MASK 0x0000 /* Disable auto MDI-X */
+
+#define IFE_PHC_HWI_ENABLE 0x8000 /* Enable the HWI feature */
+#define IFE_PHC_ABILITY_CHECK 0x4000 /* 1= Test Passed, 0=failed */
+#define IFE_PHC_TEST_EXEC 0x2000 /* PHY launch test pulses on the wire */
+#define IFE_PHC_HIGHZ 0x0200 /* 1 = Open Circuit */
+#define IFE_PHC_LOWZ 0x0400 /* 1 = Short Circuit */
+#define IFE_PHC_LOW_HIGH_Z_MASK 0x0600 /* Mask for indication type of problem on the line */
+#define IFE_PHC_DISTANCE_MASK 0x01FF /* Mask for distance to the cable problem, in 80cm granularity */
+#define IFE_PHC_RESET_ALL_MASK 0x0000 /* Disable HWI */
+#define IFE_PSCL_PROBE_MODE 0x0020 /* LED Probe mode */
+#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
+#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
+
+#define ICH8_FLASH_COMMAND_TIMEOUT 500 /* 500 ms , should be adjusted */
+#define ICH8_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles , should be adjusted */
+#define ICH8_FLASH_SEG_SIZE_256 256
+#define ICH8_FLASH_SEG_SIZE_4K 4096
+#define ICH8_FLASH_SEG_SIZE_64K 65536
+
+#define ICH8_CYCLE_READ 0x0
+#define ICH8_CYCLE_RESERVED 0x1
+#define ICH8_CYCLE_WRITE 0x2
+#define ICH8_CYCLE_ERASE 0x3
+
+#define ICH8_FLASH_GFPREG 0x0000
+#define ICH8_FLASH_HSFSTS 0x0004
+#define ICH8_FLASH_HSFCTL 0x0006
+#define ICH8_FLASH_FADDR 0x0008
+#define ICH8_FLASH_FDATA0 0x0010
+#define ICH8_FLASH_FRACC 0x0050
+#define ICH8_FLASH_FREG0 0x0054
+#define ICH8_FLASH_FREG1 0x0058
+#define ICH8_FLASH_FREG2 0x005C
+#define ICH8_FLASH_FREG3 0x0060
+#define ICH8_FLASH_FPR0 0x0074
+#define ICH8_FLASH_FPR1 0x0078
+#define ICH8_FLASH_SSFSTS 0x0090
+#define ICH8_FLASH_SSFCTL 0x0092
+#define ICH8_FLASH_PREOP 0x0094
+#define ICH8_FLASH_OPTYPE 0x0096
+#define ICH8_FLASH_OPMENU 0x0098
+
+#define ICH8_FLASH_REG_MAPSIZE 0x00A0
+#define ICH8_FLASH_SECTOR_SIZE 4096
+#define ICH8_GFPREG_BASE_MASK 0x1FFF
+#define ICH8_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
+
+/* ICH8 GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
+/* Offset 04h HSFSTS */
+union ich8_hws_flash_status {
+ struct ich8_hsfsts {
+#ifdef E1000_BIG_ENDIAN
+ uint16_t reserved2 :6;
+ uint16_t fldesvalid :1;
+ uint16_t flockdn :1;
+ uint16_t flcdone :1;
+ uint16_t flcerr :1;
+ uint16_t dael :1;
+ uint16_t berasesz :2;
+ uint16_t flcinprog :1;
+ uint16_t reserved1 :2;
+#else
+ uint16_t flcdone :1; /* bit 0 Flash Cycle Done */
+ uint16_t flcerr :1; /* bit 1 Flash Cycle Error */
+ uint16_t dael :1; /* bit 2 Direct Access error Log */
+ uint16_t berasesz :2; /* bit 4:3 Block/Sector Erase Size */
+ uint16_t flcinprog :1; /* bit 5 flash SPI cycle in Progress */
+ uint16_t reserved1 :2; /* bit 13:6 Reserved */
+ uint16_t reserved2 :6; /* bit 13:6 Reserved */
+ uint16_t fldesvalid :1; /* bit 14 Flash Descriptor Valid */
+ uint16_t flockdn :1; /* bit 15 Flash Configuration Lock-Down */
+#endif
+ } hsf_status;
+ uint16_t regval;
+};
+
+/* ICH8 GbE Flash Hardware Sequencing Flash control Register bit breakdown */
+/* Offset 06h FLCTL */
+union ich8_hws_flash_ctrl {
+ struct ich8_hsflctl {
+#ifdef E1000_BIG_ENDIAN
+ uint16_t fldbcount :2;
+ uint16_t flockdn :6;
+ uint16_t flcgo :1;
+ uint16_t flcycle :2;
+ uint16_t reserved :5;
+#else
+ uint16_t flcgo :1; /* 0 Flash Cycle Go */
+ uint16_t flcycle :2; /* 2:1 Flash Cycle */
+ uint16_t reserved :5; /* 7:3 Reserved */
+ uint16_t fldbcount :2; /* 9:8 Flash Data Byte Count */
+ uint16_t flockdn :6; /* 15:10 Reserved */
+#endif
+ } hsf_ctrl;
+ uint16_t regval;
+};
+
+/* ICH8 Flash Region Access Permissions */
+union ich8_hws_flash_regacc {
+ struct ich8_flracc {
+#ifdef E1000_BIG_ENDIAN
+ uint32_t gmwag :8;
+ uint32_t gmrag :8;
+ uint32_t grwa :8;
+ uint32_t grra :8;
+#else
+ uint32_t grra :8; /* 0:7 GbE region Read Access */
+ uint32_t grwa :8; /* 8:15 GbE region Write Access */
+ uint32_t gmrag :8; /* 23:16 GbE Master Read Access Grant */
+ uint32_t gmwag :8; /* 31:24 GbE Master Write Access Grant */
+#endif
+ } hsf_flregacc;
+ uint16_t regval;
+};
+
/* Miscellaneous PHY bit definitions. */
#define PHY_PREAMBLE 0xFFFFFFFF
#define PHY_SOF 0x01
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index f77624f5f17b..6d3d41934503 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -36,7 +36,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "7.0.38-k4"DRIVERNAPI
+#define DRV_VERSION "7.1.9-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -73,6 +73,11 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1026),
INTEL_E1000_ETHERNET_DEVICE(0x1027),
INTEL_E1000_ETHERNET_DEVICE(0x1028),
+ INTEL_E1000_ETHERNET_DEVICE(0x1049),
+ INTEL_E1000_ETHERNET_DEVICE(0x104A),
+ INTEL_E1000_ETHERNET_DEVICE(0x104B),
+ INTEL_E1000_ETHERNET_DEVICE(0x104C),
+ INTEL_E1000_ETHERNET_DEVICE(0x104D),
INTEL_E1000_ETHERNET_DEVICE(0x105E),
INTEL_E1000_ETHERNET_DEVICE(0x105F),
INTEL_E1000_ETHERNET_DEVICE(0x1060),
@@ -96,6 +101,8 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x109A),
INTEL_E1000_ETHERNET_DEVICE(0x10B5),
INTEL_E1000_ETHERNET_DEVICE(0x10B9),
+ INTEL_E1000_ETHERNET_DEVICE(0x10BA),
+ INTEL_E1000_ETHERNET_DEVICE(0x10BB),
/* required last entry */
{0,}
};
@@ -133,7 +140,6 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data);
-static void e1000_watchdog_task(struct e1000_adapter *adapter);
static void e1000_82547_tx_fifo_stall(unsigned long data);
static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
@@ -178,8 +184,8 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
static void e1000_restore_vlan(struct e1000_adapter *adapter);
-#ifdef CONFIG_PM
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
+#ifdef CONFIG_PM
static int e1000_resume(struct pci_dev *pdev);
#endif
static void e1000_shutdown(struct pci_dev *pdev);
@@ -206,8 +212,8 @@ static struct pci_driver e1000_driver = {
.probe = e1000_probe,
.remove = __devexit_p(e1000_remove),
/* Power Managment Hooks */
-#ifdef CONFIG_PM
.suspend = e1000_suspend,
+#ifdef CONFIG_PM
.resume = e1000_resume,
#endif
.shutdown = e1000_shutdown,
@@ -261,6 +267,44 @@ e1000_exit_module(void)
module_exit(e1000_exit_module);
+static int e1000_request_irq(struct e1000_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int flags, err = 0;
+
+ flags = IRQF_SHARED;
+#ifdef CONFIG_PCI_MSI
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->have_msi = TRUE;
+ if ((err = pci_enable_msi(adapter->pdev))) {
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate MSI interrupt Error: %d\n", err);
+ adapter->have_msi = FALSE;
+ }
+ }
+ if (adapter->have_msi)
+ flags &= ~IRQF_SHARED;
+#endif
+ if ((err = request_irq(adapter->pdev->irq, &e1000_intr, flags,
+ netdev->name, netdev)))
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate interrupt Error: %d\n", err);
+
+ return err;
+}
+
+static void e1000_free_irq(struct e1000_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ free_irq(adapter->pdev->irq, netdev);
+
+#ifdef CONFIG_PCI_MSI
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
+#endif
+}
+
/**
* e1000_irq_disable - Mask off interrupt generation on the NIC
* @adapter: board private structure
@@ -329,6 +373,7 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
{
uint32_t ctrl_ext;
uint32_t swsm;
+ uint32_t extcnf;
/* Let firmware taken over control of h/w */
switch (adapter->hw.mac_type) {
@@ -343,6 +388,11 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
swsm & ~E1000_SWSM_DRV_LOAD);
+ case e1000_ich8lan:
+ extcnf = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ extcnf & ~E1000_CTRL_EXT_DRV_LOAD);
+ break;
default:
break;
}
@@ -364,6 +414,7 @@ e1000_get_hw_control(struct e1000_adapter *adapter)
{
uint32_t ctrl_ext;
uint32_t swsm;
+ uint32_t extcnf;
/* Let firmware know the driver has taken over */
switch (adapter->hw.mac_type) {
case e1000_82571:
@@ -378,6 +429,11 @@ e1000_get_hw_control(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, SWSM,
swsm | E1000_SWSM_DRV_LOAD);
break;
+ case e1000_ich8lan:
+ extcnf = E1000_READ_REG(&adapter->hw, EXTCNF_CTRL);
+ E1000_WRITE_REG(&adapter->hw, EXTCNF_CTRL,
+ extcnf | E1000_EXTCNF_CTRL_SWFLAG);
+ break;
default:
break;
}
@@ -387,18 +443,10 @@ int
e1000_up(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int i, err;
+ int i;
/* hardware has been reset, we need to reload some things */
- /* Reset the PHY if it was previously powered down */
- if (adapter->hw.media_type == e1000_media_type_copper) {
- uint16_t mii_reg;
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
- if (mii_reg & MII_CR_POWER_DOWN)
- e1000_phy_hw_reset(&adapter->hw);
- }
-
e1000_set_multi(netdev);
e1000_restore_vlan(adapter);
@@ -415,24 +463,6 @@ e1000_up(struct e1000_adapter *adapter)
E1000_DESC_UNUSED(ring));
}
-#ifdef CONFIG_PCI_MSI
- if (adapter->hw.mac_type > e1000_82547_rev_2) {
- adapter->have_msi = TRUE;
- if ((err = pci_enable_msi(adapter->pdev))) {
- DPRINTK(PROBE, ERR,
- "Unable to allocate MSI interrupt Error: %d\n", err);
- adapter->have_msi = FALSE;
- }
- }
-#endif
- if ((err = request_irq(adapter->pdev->irq, &e1000_intr,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- netdev->name, netdev))) {
- DPRINTK(PROBE, ERR,
- "Unable to allocate interrupt Error: %d\n", err);
- return err;
- }
-
adapter->tx_queue_len = netdev->tx_queue_len;
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -445,21 +475,60 @@ e1000_up(struct e1000_adapter *adapter)
return 0;
}
+/**
+ * e1000_power_up_phy - restore link in case the phy was powered down
+ * @adapter: address of board private structure
+ *
+ * The phy may be powered down to save power and turn off link when the
+ * driver is unloaded and wake on lan is not enabled (among others)
+ * *** this routine MUST be followed by a call to e1000_reset ***
+ *
+ **/
+
+static void e1000_power_up_phy(struct e1000_adapter *adapter)
+{
+ uint16_t mii_reg = 0;
+
+ /* Just clear the power down bit to wake the phy back up */
+ if (adapter->hw.media_type == e1000_media_type_copper) {
+ /* according to the manual, the phy will retain its
+ * settings across a power-down/up cycle */
+ e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+ mii_reg &= ~MII_CR_POWER_DOWN;
+ e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ }
+}
+
+static void e1000_power_down_phy(struct e1000_adapter *adapter)
+{
+ boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
+ e1000_check_mng_mode(&adapter->hw);
+ /* Power down the PHY so no link is implied when interface is down
+ * The PHY cannot be powered down if any of the following is TRUE
+ * (a) WoL is enabled
+ * (b) AMT is active
+ * (c) SoL/IDER session is active */
+ if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.mac_type != e1000_ich8lan &&
+ adapter->hw.media_type == e1000_media_type_copper &&
+ !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
+ !mng_mode_enabled &&
+ !e1000_check_phy_reset_block(&adapter->hw)) {
+ uint16_t mii_reg = 0;
+ e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+ mii_reg |= MII_CR_POWER_DOWN;
+ e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ mdelay(1);
+ }
+}
+
void
e1000_down(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
- e1000_check_mng_mode(&adapter->hw);
e1000_irq_disable(adapter);
- free_irq(adapter->pdev->irq, netdev);
-#ifdef CONFIG_PCI_MSI
- if (adapter->hw.mac_type > e1000_82547_rev_2 &&
- adapter->have_msi == TRUE)
- pci_disable_msi(adapter->pdev);
-#endif
del_timer_sync(&adapter->tx_fifo_stall_timer);
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
@@ -476,23 +545,17 @@ e1000_down(struct e1000_adapter *adapter)
e1000_reset(adapter);
e1000_clean_all_tx_rings(adapter);
e1000_clean_all_rx_rings(adapter);
+}
- /* Power down the PHY so no link is implied when interface is down *
- * The PHY cannot be powered down if any of the following is TRUE *
- * (a) WoL is enabled
- * (b) AMT is active
- * (c) SoL/IDER session is active */
- if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.media_type == e1000_media_type_copper &&
- !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
- !mng_mode_enabled &&
- !e1000_check_phy_reset_block(&adapter->hw)) {
- uint16_t mii_reg;
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
- mii_reg |= MII_CR_POWER_DOWN;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
- mdelay(1);
- }
+void
+e1000_reinit_locked(struct e1000_adapter *adapter)
+{
+ WARN_ON(in_interrupt());
+ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+ msleep(1);
+ e1000_down(adapter);
+ e1000_up(adapter);
+ clear_bit(__E1000_RESETTING, &adapter->flags);
}
void
@@ -518,6 +581,9 @@ e1000_reset(struct e1000_adapter *adapter)
case e1000_82573:
pba = E1000_PBA_12K;
break;
+ case e1000_ich8lan:
+ pba = E1000_PBA_8K;
+ break;
default:
pba = E1000_PBA_48K;
break;
@@ -542,6 +608,12 @@ e1000_reset(struct e1000_adapter *adapter)
/* Set the FC high water mark to 90% of the FIFO size.
* Required to clear last 3 LSB */
fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
+ /* We can't use 90% on small FIFOs because the remainder
+ * would be less than 1 full frame. In this case, we size
+ * it to allow at least a full frame above the high water
+ * mark. */
+ if (pba < E1000_PBA_16K)
+ fc_high_water_mark = (pba * 1024) - 1600;
adapter->hw.fc_high_water = fc_high_water_mark;
adapter->hw.fc_low_water = fc_high_water_mark - 8;
@@ -564,6 +636,23 @@ e1000_reset(struct e1000_adapter *adapter)
e1000_reset_adaptive(&adapter->hw);
e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+
+ if (!adapter->smart_power_down &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+ uint16_t phy_data = 0;
+ /* speed up time to link by disabling smart power down, ignore
+ * the return value of this function because there is nothing
+ * different we would do if it failed */
+ e1000_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+ &phy_data);
+ phy_data &= ~IGP02E1000_PM_SPD;
+ e1000_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+ phy_data);
+ }
+
+ if (adapter->hw.mac_type < e1000_ich8lan)
+ /* FIXME: this code is duplicate and wrong for PCI Express */
if (adapter->en_mng_pt) {
manc = E1000_READ_REG(&adapter->hw, MANC);
manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
@@ -590,6 +679,7 @@ e1000_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct e1000_adapter *adapter;
unsigned long mmio_start, mmio_len;
+ unsigned long flash_start, flash_len;
static int cards_found = 0;
static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */
@@ -599,10 +689,12 @@ e1000_probe(struct pci_dev *pdev,
if ((err = pci_enable_device(pdev)))
return err;
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
+ !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) &&
+ (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
E1000_ERR("No usable DMA configuration, aborting\n");
return err;
}
@@ -682,6 +774,19 @@ e1000_probe(struct pci_dev *pdev,
if ((err = e1000_sw_init(adapter)))
goto err_sw_init;
+ /* Flash BAR mapping must happen after e1000_sw_init
+ * because it depends on mac_type */
+ if ((adapter->hw.mac_type == e1000_ich8lan) &&
+ (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
+ flash_start = pci_resource_start(pdev, 1);
+ flash_len = pci_resource_len(pdev, 1);
+ adapter->hw.flash_address = ioremap(flash_start, flash_len);
+ if (!adapter->hw.flash_address) {
+ err = -EIO;
+ goto err_flashmap;
+ }
+ }
+
if ((err = e1000_check_phy_reset_block(&adapter->hw)))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
@@ -700,6 +805,8 @@ e1000_probe(struct pci_dev *pdev,
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
+ if (adapter->hw.mac_type == e1000_ich8lan)
+ netdev->features &= ~NETIF_F_HW_VLAN_FILTER;
}
#ifdef NETIF_F_TSO
@@ -715,11 +822,17 @@ e1000_probe(struct pci_dev *pdev,
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
- /* hard_start_xmit is safe against parallel locking */
netdev->features |= NETIF_F_LLTX;
adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+ /* initialize eeprom parameters */
+
+ if (e1000_init_eeprom_params(&adapter->hw)) {
+ E1000_ERR("EEPROM initialization failed\n");
+ return -EIO;
+ }
+
/* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
@@ -758,9 +871,6 @@ e1000_probe(struct pci_dev *pdev,
adapter->watchdog_timer.function = &e1000_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
- INIT_WORK(&adapter->watchdog_task,
- (void (*)(void *))e1000_watchdog_task, adapter);
-
init_timer(&adapter->phy_info_timer);
adapter->phy_info_timer.function = &e1000_update_phy_info;
adapter->phy_info_timer.data = (unsigned long) adapter;
@@ -790,6 +900,11 @@ e1000_probe(struct pci_dev *pdev,
EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
eeprom_apme_mask = E1000_EEPROM_82544_APM;
break;
+ case e1000_ich8lan:
+ e1000_read_eeprom(&adapter->hw,
+ EEPROM_INIT_CONTROL1_REG, 1, &eeprom_data);
+ eeprom_apme_mask = E1000_EEPROM_ICH8_APME;
+ break;
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
@@ -849,6 +964,9 @@ e1000_probe(struct pci_dev *pdev,
return 0;
err_register:
+ if (adapter->hw.flash_address)
+ iounmap(adapter->hw.flash_address);
+err_flashmap:
err_sw_init:
err_eeprom:
iounmap(adapter->hw.hw_addr);
@@ -882,6 +1000,7 @@ e1000_remove(struct pci_dev *pdev)
flush_scheduled_work();
if (adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.mac_type != e1000_ich8lan &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
if (manc & E1000_MANC_SMBUS_EN) {
@@ -910,6 +1029,8 @@ e1000_remove(struct pci_dev *pdev)
#endif
iounmap(adapter->hw.hw_addr);
+ if (adapter->hw.flash_address)
+ iounmap(adapter->hw.flash_address);
pci_release_regions(pdev);
free_netdev(netdev);
@@ -960,13 +1081,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
return -EIO;
}
- /* initialize eeprom parameters */
-
- if (e1000_init_eeprom_params(hw)) {
- E1000_ERR("EEPROM initialization failed\n");
- return -EIO;
- }
-
switch (hw->mac_type) {
default:
break;
@@ -1078,6 +1192,10 @@ e1000_open(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
int err;
+ /* disallow open during test */
+ if (test_bit(__E1000_DRIVER_TESTING, &adapter->flags))
+ return -EBUSY;
+
/* allocate transmit descriptors */
if ((err = e1000_setup_all_tx_resources(adapter)))
@@ -1088,6 +1206,12 @@ e1000_open(struct net_device *netdev)
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
+ err = e1000_request_irq(adapter);
+ if (err)
+ goto err_up;
+
+ e1000_power_up_phy(adapter);
+
if ((err = e1000_up(adapter)))
goto err_up;
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
@@ -1131,7 +1255,10 @@ e1000_close(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
e1000_down(adapter);
+ e1000_power_down_phy(adapter);
+ e1000_free_irq(adapter);
e1000_free_all_tx_resources(adapter);
e1000_free_all_rx_resources(adapter);
@@ -1189,8 +1316,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
int size;
size = sizeof(struct e1000_buffer) * txdr->count;
-
- txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
+ txdr->buffer_info = vmalloc(size);
if (!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
@@ -1302,11 +1428,11 @@ e1000_configure_tx(struct e1000_adapter *adapter)
tdba = adapter->tx_ring[0].dma;
tdlen = adapter->tx_ring[0].count *
sizeof(struct e1000_tx_desc);
- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
E1000_WRITE_REG(hw, TDLEN, tdlen);
- E1000_WRITE_REG(hw, TDH, 0);
+ E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
+ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
E1000_WRITE_REG(hw, TDT, 0);
+ E1000_WRITE_REG(hw, TDH, 0);
adapter->tx_ring[0].tdh = E1000_TDH;
adapter->tx_ring[0].tdt = E1000_TDT;
break;
@@ -1418,7 +1544,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
- rxdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
+ rxdr->buffer_info = vmalloc(size);
if (!rxdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
@@ -1560,9 +1686,6 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
- if (adapter->hw.mac_type > e1000_82543)
- rctl |= E1000_RCTL_SECRC;
-
if (adapter->hw.tbi_compatibility_on == 1)
rctl |= E1000_RCTL_SBP;
else
@@ -1628,7 +1751,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rfctl |= E1000_RFCTL_IPV6_DIS;
E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
- rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
+ rctl |= E1000_RCTL_DTYP_PS;
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
@@ -1712,11 +1835,11 @@ e1000_configure_rx(struct e1000_adapter *adapter)
case 1:
default:
rdba = adapter->rx_ring[0].dma;
- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
E1000_WRITE_REG(hw, RDLEN, rdlen);
- E1000_WRITE_REG(hw, RDH, 0);
+ E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
+ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
E1000_WRITE_REG(hw, RDT, 0);
+ E1000_WRITE_REG(hw, RDH, 0);
adapter->rx_ring[0].rdh = E1000_RDH;
adapter->rx_ring[0].rdt = E1000_RDT;
break;
@@ -1741,9 +1864,6 @@ e1000_configure_rx(struct e1000_adapter *adapter)
E1000_WRITE_REG(hw, RXCSUM, rxcsum);
}
- if (hw->mac_type == e1000_82573)
- E1000_WRITE_REG(hw, ERT, 0x0100);
-
/* Enable Receives */
E1000_WRITE_REG(hw, RCTL, rctl);
}
@@ -2083,6 +2203,12 @@ e1000_set_multi(struct net_device *netdev)
uint32_t rctl;
uint32_t hash_value;
int i, rar_entries = E1000_RAR_ENTRIES;
+ int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
+ E1000_NUM_MTA_REGISTERS_ICH8LAN :
+ E1000_NUM_MTA_REGISTERS;
+
+ if (adapter->hw.mac_type == e1000_ich8lan)
+ rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
/* reserve RAR[14] for LAA over-write work-around */
if (adapter->hw.mac_type == e1000_82571)
@@ -2121,14 +2247,18 @@ e1000_set_multi(struct net_device *netdev)
mc_ptr = mc_ptr->next;
} else {
E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
+ E1000_WRITE_FLUSH(hw);
}
}
/* clear the old settings from the multicast hash table */
- for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+ for (i = 0; i < mta_reg_count; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+ E1000_WRITE_FLUSH(hw);
+ }
/* load any remaining addresses into the hash table */
@@ -2201,19 +2331,19 @@ static void
e1000_watchdog(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-
- /* Do the rest outside of interrupt context */
- schedule_work(&adapter->watchdog_task);
-}
-
-static void
-e1000_watchdog_task(struct e1000_adapter *adapter)
-{
struct net_device *netdev = adapter->netdev;
struct e1000_tx_ring *txdr = adapter->tx_ring;
uint32_t link, tctl;
-
- e1000_check_for_link(&adapter->hw);
+ int32_t ret_val;
+
+ ret_val = e1000_check_for_link(&adapter->hw);
+ if ((ret_val == E1000_ERR_PHY) &&
+ (adapter->hw.phy_type == e1000_phy_igp_3) &&
+ (E1000_READ_REG(&adapter->hw, CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
+ /* See e1000_kumeran_lock_loss_workaround() */
+ DPRINTK(LINK, INFO,
+ "Gigabit has been disabled, downgrading speed\n");
+ }
if (adapter->hw.mac_type == e1000_82573) {
e1000_enable_tx_pkt_filtering(&adapter->hw);
if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
@@ -2394,7 +2524,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
@@ -2519,7 +2649,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
* tso gets written back prematurely before the data is fully
* DMA'd to the controller */
if (!skb->data_len && tx_ring->last_tx_tso &&
- !skb_shinfo(skb)->gso_size) {
+ !skb_is_gso(skb)) {
tx_ring->last_tx_tso = 0;
size -= 4;
}
@@ -2779,9 +2909,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
case e1000_82571:
case e1000_82572:
case e1000_82573:
+ case e1000_ich8lan:
pull_size = min((unsigned int)4, skb->data_len);
if (!__pskb_pull_tail(skb, pull_size)) {
- printk(KERN_ERR
+ DPRINTK(DRV, ERR,
"__pskb_pull_tail failed.\n");
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -2806,8 +2937,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
#ifdef NETIF_F_TSO
/* Controller Erratum workaround */
- if (!skb->data_len && tx_ring->last_tx_tso &&
- !skb_shinfo(skb)->gso_size)
+ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
count++;
#endif
@@ -2919,8 +3049,7 @@ e1000_reset_task(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_down(adapter);
- e1000_up(adapter);
+ e1000_reinit_locked(adapter);
}
/**
@@ -2964,6 +3093,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
/* Adapter-specific max frame size limits. */
switch (adapter->hw.mac_type) {
case e1000_undefined ... e1000_82542_rev2_1:
+ case e1000_ich8lan:
if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
return -EINVAL;
@@ -3026,10 +3156,8 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- if (netif_running(netdev)) {
- e1000_down(adapter);
- e1000_up(adapter);
- }
+ if (netif_running(netdev))
+ e1000_reinit_locked(adapter);
adapter->hw.max_frame_size = max_frame;
@@ -3074,12 +3202,15 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
adapter->stats.roc += E1000_READ_REG(hw, ROC);
+
+ if (adapter->hw.mac_type != e1000_ich8lan) {
adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
+ }
adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
adapter->stats.mpc += E1000_READ_REG(hw, MPC);
@@ -3107,12 +3238,16 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.totl += E1000_READ_REG(hw, TOTL);
adapter->stats.toth += E1000_READ_REG(hw, TOTH);
adapter->stats.tpr += E1000_READ_REG(hw, TPR);
+
+ if (adapter->hw.mac_type != e1000_ich8lan) {
adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
+ }
+
adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
@@ -3134,6 +3269,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
if (hw->mac_type > e1000_82547_rev_2) {
adapter->stats.iac += E1000_READ_REG(hw, IAC);
adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
+
+ if (adapter->hw.mac_type != e1000_ich8lan) {
adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
@@ -3141,6 +3278,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+ }
}
/* Fill out the OS statistics structure */
@@ -3547,7 +3685,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
/* All receives must fit into a single buffer */
E1000_DBG("%s: Receive packet consumed multiple"
" buffers\n", netdev->name);
- dev_kfree_skb_irq(skb);
+ /* recycle */
+ buffer_info-> skb = skb;
goto next_desc;
}
@@ -3675,7 +3814,6 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
buffer_info = &rx_ring->buffer_info[i];
while (staterr & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
#ifdef CONFIG_E1000_NAPI
@@ -4180,10 +4318,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return retval;
}
}
- if (netif_running(adapter->netdev)) {
- e1000_down(adapter);
- e1000_up(adapter);
- } else
+ if (netif_running(adapter->netdev))
+ e1000_reinit_locked(adapter);
+ else
e1000_reset(adapter);
break;
case M88E1000_PHY_SPEC_CTRL:
@@ -4200,10 +4337,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
case PHY_CTRL:
if (mii_reg & MII_CR_POWER_DOWN)
break;
- if (netif_running(adapter->netdev)) {
- e1000_down(adapter);
- e1000_up(adapter);
- } else
+ if (netif_running(adapter->netdev))
+ e1000_reinit_locked(adapter);
+ else
e1000_reset(adapter);
break;
}
@@ -4277,18 +4413,21 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
ctrl |= E1000_CTRL_VME;
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ if (adapter->hw.mac_type != e1000_ich8lan) {
/* enable VLAN receive filtering */
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_VFE;
rctl &= ~E1000_RCTL_CFIEN;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
e1000_update_mng_vlan(adapter);
+ }
} else {
/* disable VLAN tag insert/strip */
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
ctrl &= ~E1000_CTRL_VME;
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ if (adapter->hw.mac_type != e1000_ich8lan) {
/* disable VLAN filtering */
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~E1000_RCTL_VFE;
@@ -4297,6 +4436,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
}
+ }
}
e1000_irq_enable(adapter);
@@ -4458,12 +4598,16 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t ctrl, ctrl_ext, rctl, manc, status;
uint32_t wufc = adapter->wol;
+#ifdef CONFIG_PM
int retval = 0;
+#endif
netif_device_detach(netdev);
- if (netif_running(netdev))
+ if (netif_running(netdev)) {
+ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
e1000_down(adapter);
+ }
#ifdef CONFIG_PM
/* Implement our own version of pci_save_state(pdev) because pci-
@@ -4521,7 +4665,9 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
pci_enable_wake(pdev, PCI_D3cold, 0);
}
+ /* FIXME: this code is incorrect for PCI Express */
if (adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.mac_type != e1000_ich8lan &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
if (manc & E1000_MANC_SMBUS_EN) {
@@ -4532,6 +4678,9 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
}
}
+ if (adapter->hw.phy_type == e1000_phy_igp_3)
+ e1000_phy_powerdown_workaround(&adapter->hw);
+
/* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant. */
e1000_release_hw_control(adapter);
@@ -4567,7 +4716,9 @@ e1000_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
+ /* FIXME: this code is incorrect for PCI Express */
if (adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.mac_type != e1000_ich8lan &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 048d052be29d..2d3e8b06cab0 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -127,4 +127,17 @@ typedef enum {
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
+#define E1000_WRITE_ICH8_REG(a, reg, value) ( \
+ writel((value), ((a)->flash_address + reg)))
+
+#define E1000_READ_ICH8_REG(a, reg) ( \
+ readl((a)->flash_address + reg))
+
+#define E1000_WRITE_ICH8_REG16(a, reg, value) ( \
+ writew((value), ((a)->flash_address + reg)))
+
+#define E1000_READ_ICH8_REG16(a, reg) ( \
+ readw((a)->flash_address + reg))
+
+
#endif /* _E1000_OSDEP_H_ */
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index e55f8969a0fb..0ef413172c68 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -45,6 +45,16 @@
*/
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
+/* Module Parameters are always initialized to -1, so that the driver
+ * can tell the difference between no user specified value or the
+ * user asking for the default value.
+ * The true default values are loaded in when e1000_check_options is called.
+ *
+ * This is a GCC extension to ANSI C.
+ * See the item "Labeled Elements in Initializers" in the section
+ * "Extensions to the C Language Family" of the GCC documentation.
+ */
+
#define E1000_PARAM(X, desc) \
static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
static int num_##X = 0; \
@@ -183,6 +193,24 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+/* Enable Smart Power Down of the PHY
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 0 (disabled)
+ */
+
+E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
+
+/* Enable Kumeran Lock Loss workaround
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 1 (enabled)
+ */
+
+E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
+
#define AUTONEG_ADV_DEFAULT 0x2F
#define AUTONEG_ADV_MASK 0x2F
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
@@ -296,6 +324,7 @@ e1000_check_options(struct e1000_adapter *adapter)
DPRINTK(PROBE, NOTICE,
"Warning: no configuration for board #%i\n", bd);
DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
+ bd = E1000_MAX_NIC;
}
{ /* Transmit Descriptor Count */
@@ -313,14 +342,9 @@ e1000_check_options(struct e1000_adapter *adapter)
opt.arg.r.max = mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD;
- if (num_TxDescriptors > bd) {
- tx_ring->count = TxDescriptors[bd];
- e1000_validate_option(&tx_ring->count, &opt, adapter);
- E1000_ROUNDUP(tx_ring->count,
- REQ_TX_DESCRIPTOR_MULTIPLE);
- } else {
- tx_ring->count = opt.def;
- }
+ tx_ring->count = TxDescriptors[bd];
+ e1000_validate_option(&tx_ring->count, &opt, adapter);
+ E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
for (i = 0; i < adapter->num_tx_queues; i++)
tx_ring[i].count = tx_ring->count;
}
@@ -339,14 +363,9 @@ e1000_check_options(struct e1000_adapter *adapter)
opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
- if (num_RxDescriptors > bd) {
- rx_ring->count = RxDescriptors[bd];
- e1000_validate_option(&rx_ring->count, &opt, adapter);
- E1000_ROUNDUP(rx_ring->count,
- REQ_RX_DESCRIPTOR_MULTIPLE);
- } else {
- rx_ring->count = opt.def;
- }
+ rx_ring->count = RxDescriptors[bd];
+ e1000_validate_option(&rx_ring->count, &opt, adapter);
+ E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
for (i = 0; i < adapter->num_rx_queues; i++)
rx_ring[i].count = rx_ring->count;
}
@@ -358,13 +377,9 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = OPTION_ENABLED
};
- if (num_XsumRX > bd) {
- int rx_csum = XsumRX[bd];
- e1000_validate_option(&rx_csum, &opt, adapter);
- adapter->rx_csum = rx_csum;
- } else {
- adapter->rx_csum = opt.def;
- }
+ int rx_csum = XsumRX[bd];
+ e1000_validate_option(&rx_csum, &opt, adapter);
+ adapter->rx_csum = rx_csum;
}
{ /* Flow Control */
@@ -384,13 +399,9 @@ e1000_check_options(struct e1000_adapter *adapter)
.p = fc_list }}
};
- if (num_FlowControl > bd) {
- int fc = FlowControl[bd];
- e1000_validate_option(&fc, &opt, adapter);
- adapter->hw.fc = adapter->hw.original_fc = fc;
- } else {
- adapter->hw.fc = adapter->hw.original_fc = opt.def;
- }
+ int fc = FlowControl[bd];
+ e1000_validate_option(&fc, &opt, adapter);
+ adapter->hw.fc = adapter->hw.original_fc = fc;
}
{ /* Transmit Interrupt Delay */
struct e1000_option opt = {
@@ -402,13 +413,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.max = MAX_TXDELAY }}
};
- if (num_TxIntDelay > bd) {
- adapter->tx_int_delay = TxIntDelay[bd];
- e1000_validate_option(&adapter->tx_int_delay, &opt,
- adapter);
- } else {
- adapter->tx_int_delay = opt.def;
- }
+ adapter->tx_int_delay = TxIntDelay[bd];
+ e1000_validate_option(&adapter->tx_int_delay, &opt, adapter);
}
{ /* Transmit Absolute Interrupt Delay */
struct e1000_option opt = {
@@ -420,13 +426,9 @@ e1000_check_options(struct e1000_adapter *adapter)
.max = MAX_TXABSDELAY }}
};
- if (num_TxAbsIntDelay > bd) {
- adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
- e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
- adapter);
- } else {
- adapter->tx_abs_int_delay = opt.def;
- }
+ adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
+ e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
+ adapter);
}
{ /* Receive Interrupt Delay */
struct e1000_option opt = {
@@ -438,13 +440,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.max = MAX_RXDELAY }}
};
- if (num_RxIntDelay > bd) {
- adapter->rx_int_delay = RxIntDelay[bd];
- e1000_validate_option(&adapter->rx_int_delay, &opt,
- adapter);
- } else {
- adapter->rx_int_delay = opt.def;
- }
+ adapter->rx_int_delay = RxIntDelay[bd];
+ e1000_validate_option(&adapter->rx_int_delay, &opt, adapter);
}
{ /* Receive Absolute Interrupt Delay */
struct e1000_option opt = {
@@ -456,13 +453,9 @@ e1000_check_options(struct e1000_adapter *adapter)
.max = MAX_RXABSDELAY }}
};
- if (num_RxAbsIntDelay > bd) {
- adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
- e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
- adapter);
- } else {
- adapter->rx_abs_int_delay = opt.def;
- }
+ adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
+ e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
+ adapter);
}
{ /* Interrupt Throttling Rate */
struct e1000_option opt = {
@@ -474,26 +467,44 @@ e1000_check_options(struct e1000_adapter *adapter)
.max = MAX_ITR }}
};
- if (num_InterruptThrottleRate > bd) {
- adapter->itr = InterruptThrottleRate[bd];
- switch (adapter->itr) {
- case 0:
- DPRINTK(PROBE, INFO, "%s turned off\n",
- opt.name);
- break;
- case 1:
- DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
- opt.name);
- break;
- default:
- e1000_validate_option(&adapter->itr, &opt,
- adapter);
- break;
- }
- } else {
- adapter->itr = opt.def;
+ adapter->itr = InterruptThrottleRate[bd];
+ switch (adapter->itr) {
+ case 0:
+ DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
+ break;
+ case 1:
+ DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
+ opt.name);
+ break;
+ default:
+ e1000_validate_option(&adapter->itr, &opt, adapter);
+ break;
}
}
+ { /* Smart Power Down */
+ struct e1000_option opt = {
+ .type = enable_option,
+ .name = "PHY Smart Power Down",
+ .err = "defaulting to Disabled",
+ .def = OPTION_DISABLED
+ };
+
+ int spd = SmartPowerDownEnable[bd];
+ e1000_validate_option(&spd, &opt, adapter);
+ adapter->smart_power_down = spd;
+ }
+ { /* Kumeran Lock Loss Workaround */
+ struct e1000_option opt = {
+ .type = enable_option,
+ .name = "Kumeran Lock Loss Workaround",
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
+ };
+
+ int kmrn_lock_loss = KumeranLockLoss[bd];
+ e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
+ adapter->hw.kmrn_lock_loss_workaround_disabled = !kmrn_lock_loss;
+ }
switch (adapter->hw.media_type) {
case e1000_media_type_fiber:
@@ -519,17 +530,18 @@ static void __devinit
e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if (num_Speed > bd) {
+ bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
+ if ((Speed[bd] != OPTION_UNSET)) {
DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
"parameter ignored\n");
}
- if (num_Duplex > bd) {
+ if ((Duplex[bd] != OPTION_UNSET)) {
DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
"parameter ignored\n");
}
- if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
+ if ((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
"not valid for fiber adapters, "
"parameter ignored\n");
@@ -548,6 +560,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
{
int speed, dplx, an;
int bd = adapter->bd_number;
+ bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
{ /* Speed */
struct e1000_opt_list speed_list[] = {{ 0, "" },
@@ -564,12 +577,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = speed_list }}
};
- if (num_Speed > bd) {
- speed = Speed[bd];
- e1000_validate_option(&speed, &opt, adapter);
- } else {
- speed = opt.def;
- }
+ speed = Speed[bd];
+ e1000_validate_option(&speed, &opt, adapter);
}
{ /* Duplex */
struct e1000_opt_list dplx_list[] = {{ 0, "" },
@@ -591,15 +600,11 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
"Speed/Duplex/AutoNeg parameter ignored.\n");
return;
}
- if (num_Duplex > bd) {
- dplx = Duplex[bd];
- e1000_validate_option(&dplx, &opt, adapter);
- } else {
- dplx = opt.def;
- }
+ dplx = Duplex[bd];
+ e1000_validate_option(&dplx, &opt, adapter);
}
- if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
+ if (AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) {
DPRINTK(PROBE, INFO,
"AutoNeg specified along with Speed or Duplex, "
"parameter ignored\n");
@@ -648,19 +653,15 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = an_list }}
};
- if (num_AutoNeg > bd) {
- an = AutoNeg[bd];
- e1000_validate_option(&an, &opt, adapter);
- } else {
- an = opt.def;
- }
+ an = AutoNeg[bd];
+ e1000_validate_option(&an, &opt, adapter);
adapter->hw.autoneg_advertised = an;
}
switch (speed + dplx) {
case 0:
adapter->hw.autoneg = adapter->fc_autoneg = 1;
- if ((num_Speed > bd) && (speed != 0 || dplx != 0))
+ if (Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
DPRINTK(PROBE, INFO,
"Speed and duplex autonegotiation enabled\n");
break;
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 037d870712ff..11b8f1b43dd5 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -240,10 +240,12 @@ enum {
#define NVREG_RNDSEED_FORCE2 0x2d00
#define NVREG_RNDSEED_FORCE3 0x7400
- NvRegUnknownSetupReg1 = 0xA0,
-#define NVREG_UNKSETUP1_VAL 0x16070f
- NvRegUnknownSetupReg2 = 0xA4,
-#define NVREG_UNKSETUP2_VAL 0x16
+ NvRegTxDeferral = 0xA0,
+#define NVREG_TX_DEFERRAL_DEFAULT 0x15050f
+#define NVREG_TX_DEFERRAL_RGMII_10_100 0x16070f
+#define NVREG_TX_DEFERRAL_RGMII_1000 0x14050f
+ NvRegRxDeferral = 0xA4,
+#define NVREG_RX_DEFERRAL_DEFAULT 0x16
NvRegMacAddrA = 0xA8,
NvRegMacAddrB = 0xAC,
NvRegMulticastAddrA = 0xB0,
@@ -269,8 +271,10 @@ enum {
#define NVREG_LINKSPEED_MASK (0xFFF)
NvRegUnknownSetupReg5 = 0x130,
#define NVREG_UNKSETUP5_BIT31 (1<<31)
- NvRegUnknownSetupReg3 = 0x13c,
-#define NVREG_UNKSETUP3_VAL1 0x200010
+ NvRegTxWatermark = 0x13c,
+#define NVREG_TX_WM_DESC1_DEFAULT 0x0200010
+#define NVREG_TX_WM_DESC2_3_DEFAULT 0x1e08000
+#define NVREG_TX_WM_DESC2_3_1000 0xfe08000
NvRegTxRxControl = 0x144,
#define NVREG_TXRXCTL_KICK 0x0001
#define NVREG_TXRXCTL_BIT1 0x0002
@@ -658,7 +662,7 @@ static const struct register_test nv_registers_test[] = {
{ NvRegMisc1, 0x03c },
{ NvRegOffloadConfig, 0x03ff },
{ NvRegMulticastAddrA, 0xffffffff },
- { NvRegUnknownSetupReg3, 0x0ff },
+ { NvRegTxWatermark, 0x0ff },
{ NvRegWakeUpFlags, 0x07777 },
{ 0,0 }
};
@@ -1495,7 +1499,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
np->tx_skbuff[nr] = skb;
#ifdef NETIF_F_TSO
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
else
#endif
@@ -2127,7 +2131,7 @@ static int nv_update_linkspeed(struct net_device *dev)
int newdup = np->duplex;
int mii_status;
int retval = 0;
- u32 control_1000, status_1000, phyreg, pause_flags;
+ u32 control_1000, status_1000, phyreg, pause_flags, txreg;
/* BMSR_LSTATUS is latched, read it twice:
* we want the current value.
@@ -2245,6 +2249,26 @@ set_speed:
phyreg |= PHY_1000;
writel(phyreg, base + NvRegPhyInterface);
+ if (phyreg & PHY_RGMII) {
+ if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000)
+ txreg = NVREG_TX_DEFERRAL_RGMII_1000;
+ else
+ txreg = NVREG_TX_DEFERRAL_RGMII_10_100;
+ } else {
+ txreg = NVREG_TX_DEFERRAL_DEFAULT;
+ }
+ writel(txreg, base + NvRegTxDeferral);
+
+ if (np->desc_ver == DESC_VER_1) {
+ txreg = NVREG_TX_WM_DESC1_DEFAULT;
+ } else {
+ if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000)
+ txreg = NVREG_TX_WM_DESC2_3_1000;
+ else
+ txreg = NVREG_TX_WM_DESC2_3_DEFAULT;
+ }
+ writel(txreg, base + NvRegTxWatermark);
+
writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD),
base + NvRegMisc1);
pci_push(base);
@@ -3910,7 +3934,10 @@ static int nv_open(struct net_device *dev)
/* 5) continue setup */
writel(np->linkspeed, base + NvRegLinkSpeed);
- writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
+ if (np->desc_ver == DESC_VER_1)
+ writel(NVREG_TX_WM_DESC1_DEFAULT, base + NvRegTxWatermark);
+ else
+ writel(NVREG_TX_WM_DESC2_3_DEFAULT, base + NvRegTxWatermark);
writel(np->txrxctl_bits, base + NvRegTxRxControl);
writel(np->vlanctl_bits, base + NvRegVlanControl);
pci_push(base);
@@ -3932,8 +3959,8 @@ static int nv_open(struct net_device *dev)
writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
get_random_bytes(&i, sizeof(i));
writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
- writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
- writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
+ writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral);
+ writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral);
if (poll_interval == -1) {
if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT)
writel(NVREG_POLL_DEFAULT_THROUGHPUT, base + NvRegPollingInterval);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 0641f54fc638..889f338132fa 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -122,6 +122,12 @@ struct bpqdev {
static LIST_HEAD(bpq_devices);
+/*
+ * bpqether network devices are paired with ethernet devices below them, so
+ * form a special "super class" of normal ethernet devices; split their locks
+ * off into a separate class since they always nest.
+ */
+static struct lock_class_key bpq_netdev_xmit_lock_key;
/* ------------------------------------------------------------------------ */
@@ -528,6 +534,7 @@ static int bpq_new_device(struct net_device *edev)
err = register_netdevice(ndev);
if (err)
goto error;
+ lockdep_set_class(&ndev->_xmit_lock, &bpq_netdev_xmit_lock_key);
/* List protected by RTNL */
list_add_rcu(&bpq->bpq_list, &bpq_devices);
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index bf1fca5a3fa0..e3c8cd5eca67 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -146,7 +146,7 @@ static int __init ali_ircc_init(void)
{
ali_chip_t *chip;
chipio_t info;
- int ret = -ENODEV;
+ int ret;
int cfg, cfg_base;
int reg, revision;
int i = 0;
@@ -160,6 +160,7 @@ static int __init ali_ircc_init(void)
return ret;
}
+ ret = -ENODEV;
/* Probe for all the ALi chipsets we know about */
for (chip= chips; chip->name; chip++, i++)
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index a4674044bd6f..2eff45bedc7c 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -2353,7 +2353,7 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
#ifdef CONFIG_PCI
#define PCIID_VENDOR_INTEL 0x8086
#define PCIID_VENDOR_ALI 0x10b9
-static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
+static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = {
{
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
.device = 0x24cc,
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index b91e082483f6..7bbd447289b5 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1173,7 +1173,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
uint16_t ipcse, tucse, mss;
int err;
- if(likely(skb_shinfo(skb)->gso_size)) {
+ if (likely(skb_is_gso(skb))) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
@@ -1281,7 +1281,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
while(len) {
buffer_info = &tx_ring->buffer_info[i];
- size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
+ size = min(len, IXGB_MAX_DATA_PER_TXD);
buffer_info->length = size;
buffer_info->dma =
pci_map_single(adapter->pdev,
@@ -1306,7 +1306,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
while(len) {
buffer_info = &tx_ring->buffer_info[i];
- size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
+ size = min(len, IXGB_MAX_DATA_PER_TXD);
buffer_info->length = size;
buffer_info->dma =
pci_map_page(adapter->pdev,
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 43fef7de8cb9..997cbce9af6e 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
#ifdef LOOPBACK_TSO
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
BUG_ON(skb->protocol != htons(ETH_P_IP));
BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index f4c8fd373b9b..07ca9480a6fe 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -2116,7 +2116,7 @@ abort_linearize:
}
idx = (idx + 1) & tx->mask;
} while (idx != last_idx);
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
printk(KERN_ERR
"myri10ge: %s: TSO but wanted to linearize?!?!?\n",
mgp->dev->name);
@@ -2412,14 +2412,20 @@ static int myri10ge_resume(struct pci_dev *pdev)
return -EIO;
}
myri10ge_restore_state(mgp);
- pci_enable_device(pdev);
+
+ status = pci_enable_device(pdev);
+ if (status < 0) {
+ dev_err(&pdev->dev, "failed to enable device\n");
+ return -EIO;
+ }
+
pci_set_master(pdev);
status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
netdev->name, mgp);
if (status != 0) {
dev_err(&pdev->dev, "failed to allocate IRQ\n");
- goto abort_with_msi;
+ goto abort_with_enabled;
}
myri10ge_reset(mgp);
@@ -2438,7 +2444,8 @@ static int myri10ge_resume(struct pci_dev *pdev)
return 0;
-abort_with_msi:
+abort_with_enabled:
+ pci_disable_device(pdev);
return -EIO;
}
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c6b77acb35ef..e1fe3a0a7b0b 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1976,7 +1976,6 @@ static int start_nic(struct s2io_nic *nic)
XENA_dev_config_t __iomem *bar0 = nic->bar0;
struct net_device *dev = nic->dev;
register u64 val64 = 0;
- u16 interruptible;
u16 subid, i;
mac_info_t *mac_control;
struct config_param *config;
@@ -2047,16 +2046,6 @@ static int start_nic(struct s2io_nic *nic)
return FAILURE;
}
- /* Enable select interrupts */
- if (nic->intr_type != INTA)
- en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
- else {
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
- interruptible |= TX_PIC_INTR | RX_PIC_INTR;
- interruptible |= TX_MAC_INTR | RX_MAC_INTR;
- en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
- }
-
/*
* With some switches, link might be already up at this point.
* Because of this weird behavior, when we enable laser,
@@ -3749,101 +3738,19 @@ static int s2io_open(struct net_device *dev)
if (err) {
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
dev->name);
- if (err == -ENODEV)
- goto hw_init_failed;
- else
- goto hw_enable_failed;
- }
-
- /* Store the values of the MSIX table in the nic_t structure */
- store_xmsi_data(sp);
-
- /* After proper initialization of H/W, register ISR */
- if (sp->intr_type == MSI) {
- err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
- IRQF_SHARED, sp->name, dev);
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: MSI registration \
-failed\n", dev->name);
- goto isr_registration_failed;
- }
- }
- if (sp->intr_type == MSI_X) {
- int i;
-
- for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
- if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
- sprintf(sp->desc1, "%s:MSI-X-%d-TX",
- dev->name, i);
- err = request_irq(sp->entries[i].vector,
- s2io_msix_fifo_handle, 0, sp->desc1,
- sp->s2io_entries[i].arg);
- DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
- (unsigned long long)sp->msix_info[i].addr);
- } else {
- sprintf(sp->desc2, "%s:MSI-X-%d-RX",
- dev->name, i);
- err = request_irq(sp->entries[i].vector,
- s2io_msix_ring_handle, 0, sp->desc2,
- sp->s2io_entries[i].arg);
- DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
- (unsigned long long)sp->msix_info[i].addr);
- }
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
-failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
- goto isr_registration_failed;
- }
- sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
- }
- }
- if (sp->intr_type == INTA) {
- err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
- sp->name, dev);
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
- dev->name);
- goto isr_registration_failed;
- }
+ goto hw_init_failed;
}
if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
+ s2io_card_down(sp);
err = -ENODEV;
- goto setting_mac_address_failed;
+ goto hw_init_failed;
}
netif_start_queue(dev);
return 0;
-setting_mac_address_failed:
- if (sp->intr_type != MSI_X)
- free_irq(sp->pdev->irq, dev);
-isr_registration_failed:
- del_timer_sync(&sp->alarm_timer);
- if (sp->intr_type == MSI_X) {
- int i;
- u16 msi_control; /* Temp variable */
-
- 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;
-
- free_irq(vector, arg);
- }
- pci_disable_msix(sp->pdev);
-
- /* Temp */
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
- }
- else if (sp->intr_type == MSI)
- pci_disable_msi(sp->pdev);
-hw_enable_failed:
- s2io_reset(sp);
hw_init_failed:
if (sp->intr_type == MSI_X) {
if (sp->entries)
@@ -3874,7 +3781,7 @@ static int s2io_close(struct net_device *dev)
flush_scheduled_work();
netif_stop_queue(dev);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
- s2io_card_down(sp, 1);
+ s2io_card_down(sp);
sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
@@ -5919,7 +5826,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
dev->mtu = new_mtu;
if (netif_running(dev)) {
- s2io_card_down(sp, 0);
+ s2io_card_down(sp);
netif_stop_queue(dev);
if (s2io_card_up(sp)) {
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -6216,43 +6123,106 @@ static int rxd_owner_bit_reset(nic_t *sp)
}
-static void s2io_card_down(nic_t * sp, int flag)
+static int s2io_add_isr(nic_t * sp)
{
- int cnt = 0;
- XENA_dev_config_t __iomem *bar0 = sp->bar0;
- unsigned long flags;
- register u64 val64 = 0;
+ int ret = 0;
struct net_device *dev = sp->dev;
+ int err = 0;
- del_timer_sync(&sp->alarm_timer);
- /* If s2io_set_link task is executing, wait till it completes. */
- while (test_and_set_bit(0, &(sp->link_state))) {
- msleep(50);
+ if (sp->intr_type == MSI)
+ ret = s2io_enable_msi(sp);
+ else if (sp->intr_type == MSI_X)
+ ret = s2io_enable_msi_x(sp);
+ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+ sp->intr_type = INTA;
}
- atomic_set(&sp->card_state, CARD_DOWN);
- /* disable Tx and Rx traffic on the NIC */
- stop_nic(sp);
- if (flag) {
- if (sp->intr_type == MSI_X) {
- int i;
- u16 msi_control;
+ /* Store the values of the MSIX table in the nic_t structure */
+ store_xmsi_data(sp);
- 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;
+ /* After proper initialization of H/W, register ISR */
+ if (sp->intr_type == MSI) {
+ err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
+ IRQF_SHARED, sp->name, dev);
+ if (err) {
+ pci_disable_msi(sp->pdev);
+ DBG_PRINT(ERR_DBG, "%s: MSI registration failed\n",
+ dev->name);
+ return -1;
+ }
+ }
+ if (sp->intr_type == MSI_X) {
+ int i;
- free_irq(vector, arg);
+ for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+ if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+ sprintf(sp->desc[i], "%s:MSI-X-%d-TX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_fifo_handle, 0, sp->desc[i],
+ sp->s2io_entries[i].arg);
+ DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
+ (unsigned long long)sp->msix_info[i].addr);
+ } else {
+ sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_ring_handle, 0, sp->desc[i],
+ sp->s2io_entries[i].arg);
+ DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
+ (unsigned long long)sp->msix_info[i].addr);
}
- 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 {
- free_irq(sp->pdev->irq, dev);
- if (sp->intr_type == MSI)
- pci_disable_msi(sp->pdev);
+ if (err) {
+ DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
+ "failed\n", dev->name, i);
+ DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+ return -1;
+ }
+ sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+ }
+ }
+ if (sp->intr_type == INTA) {
+ err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
+ sp->name, dev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+ dev->name);
+ return -1;
+ }
+ }
+ return 0;
+}
+static void s2io_rem_isr(nic_t * sp)
+{
+ int cnt = 0;
+ struct net_device *dev = sp->dev;
+
+ if (sp->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;
+
+ free_irq(vector, arg);
+ }
+ 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 {
+ free_irq(sp->pdev->irq, dev);
+ if (sp->intr_type == MSI) {
+ u16 val;
+
+ pci_disable_msi(sp->pdev);
+ pci_read_config_word(sp->pdev, 0x4c, &val);
+ val ^= 0x1;
+ pci_write_config_word(sp->pdev, 0x4c, val);
}
}
/* Waiting till all Interrupt handlers are complete */
@@ -6263,6 +6233,26 @@ static void s2io_card_down(nic_t * sp, int flag)
break;
cnt++;
} while(cnt < 5);
+}
+
+static void s2io_card_down(nic_t * sp)
+{
+ int cnt = 0;
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ unsigned long flags;
+ register u64 val64 = 0;
+
+ del_timer_sync(&sp->alarm_timer);
+ /* If s2io_set_link task is executing, wait till it completes. */
+ while (test_and_set_bit(0, &(sp->link_state))) {
+ msleep(50);
+ }
+ atomic_set(&sp->card_state, CARD_DOWN);
+
+ /* disable Tx and Rx traffic on the NIC */
+ stop_nic(sp);
+
+ s2io_rem_isr(sp);
/* Kill tasklet. */
tasklet_kill(&sp->task);
@@ -6314,23 +6304,16 @@ static int s2io_card_up(nic_t * sp)
mac_info_t *mac_control;
struct config_param *config;
struct net_device *dev = (struct net_device *) sp->dev;
+ u16 interruptible;
/* Initialize the H/W I/O registers */
if (init_nic(sp) != 0) {
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
dev->name);
+ s2io_reset(sp);
return -ENODEV;
}
- if (sp->intr_type == MSI)
- ret = s2io_enable_msi(sp);
- else if (sp->intr_type == MSI_X)
- ret = s2io_enable_msi_x(sp);
- if (ret) {
- DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
- sp->intr_type = INTA;
- }
-
/*
* Initializing the Rx buffers. For now we are considering only 1
* Rx ring and initializing buffers into 30 Rx blocks
@@ -6361,21 +6344,39 @@ static int s2io_card_up(nic_t * sp)
sp->lro_max_aggr_per_sess = lro_max_pkts;
}
- /* Enable tasklet for the device */
- tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
-
/* Enable Rx Traffic and interrupts on the NIC */
if (start_nic(sp)) {
DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name);
- tasklet_kill(&sp->task);
s2io_reset(sp);
- free_irq(dev->irq, dev);
+ free_rx_buffers(sp);
+ return -ENODEV;
+ }
+
+ /* Add interrupt service routine */
+ if (s2io_add_isr(sp) != 0) {
+ if (sp->intr_type == MSI_X)
+ s2io_rem_isr(sp);
+ s2io_reset(sp);
free_rx_buffers(sp);
return -ENODEV;
}
S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+ /* Enable tasklet for the device */
+ tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
+
+ /* Enable select interrupts */
+ if (sp->intr_type != INTA)
+ en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
+ else {
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+ en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
+ }
+
+
atomic_set(&sp->card_state, CARD_UP);
return 0;
}
@@ -6395,7 +6396,7 @@ static void s2io_restart_nic(unsigned long data)
struct net_device *dev = (struct net_device *) data;
nic_t *sp = dev->priv;
- s2io_card_down(sp, 0);
+ s2io_card_down(sp);
if (s2io_card_up(sp)) {
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
dev->name);
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index c43f52179708..217097bc22f1 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -829,8 +829,7 @@ struct s2io_nic {
#define MSIX_FLG 0xA5
struct msix_entry *entries;
struct s2io_msix_entry *s2io_entries;
- char desc1[35];
- char desc2[35];
+ char desc[MAX_REQUESTED_MSI_X][25];
int avail_msix_vectors; /* No. of MSI-X vectors granted by system */
@@ -1002,7 +1001,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
static void s2io_set_link(unsigned long data);
static int s2io_set_swapper(nic_t * sp);
-static void s2io_card_down(nic_t *nic, int flag);
+static void s2io_card_down(nic_t *nic);
static int s2io_card_up(nic_t *nic);
static int get_xena_rev_id(struct pci_dev *pdev);
static void restore_xmsi_data(nic_t *nic);
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
index 2b19f8ad0318..7f8e6d0084c7 100644
--- a/drivers/net/sk98lin/h/xmac_ii.h
+++ b/drivers/net/sk98lin/h/xmac_ii.h
@@ -1473,7 +1473,7 @@ extern "C" {
#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */
#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */
#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK (1<<10) /* Bit 12..10: Collision Threshold */
+#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold */
#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK)
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index ed19ff47ce11..593387b3c0dd 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -1734,11 +1734,11 @@ enum {
GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */
GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */
- GM_TXCR_COL_THR_MSK = 1<<10, /* Bit 12..10: Collision Threshold */
+ GM_TXCR_COL_THR_MSK = 7<<10, /* Bit 12..10: Collision Threshold */
};
#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
-#define TX_COL_DEF 0x04
+#define TX_COL_DEF 0x04 /* late collision after 64 byte */
/* GM_RX_CTRL 16 bit r/w Receive Control Register */
enum {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 418f169a6a31..d98f28c34e5c 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -65,6 +65,7 @@
#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
#define RX_DEF_PENDING RX_MAX_PENDING
#define RX_SKB_ALIGN 8
+#define RX_BUF_WRITE 16
#define TX_RING_SIZE 512
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -234,7 +235,6 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
}
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
- sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
reg1 &= P_ASPM_CONTROL_MSK;
@@ -243,6 +243,7 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
}
sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ udelay(100);
break;
@@ -255,6 +256,7 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
else
reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ udelay(100);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
@@ -1159,7 +1161,7 @@ static unsigned tx_le_req(const struct sk_buff *skb)
count = sizeof(dma_addr_t) / sizeof(u32);
count += skb_shinfo(skb)->nr_frags * count;
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
++count;
if (skb->ip_summed == CHECKSUM_HW)
@@ -1389,7 +1391,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
}
sky2->tx_cons = put;
- if (tx_avail(sky2) > MAX_SKB_TX_LE)
+ if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
netif_wake_queue(dev);
}
@@ -1888,9 +1890,6 @@ resubmit:
re->skb->ip_summed = CHECKSUM_NONE;
sky2_rx_add(sky2, re->mapaddr);
- /* Tell receiver about new buffers. */
- sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put);
-
return skb;
oversize:
@@ -1937,7 +1936,9 @@ static inline int sky2_more_work(const struct sky2_hw *hw)
/* Process status response ring */
static int sky2_status_intr(struct sky2_hw *hw, int to_do)
{
+ struct sky2_port *sky2;
int work_done = 0;
+ unsigned buf_write[2] = { 0, 0 };
u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
rmb();
@@ -1945,7 +1946,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
while (hw->st_idx != hwidx) {
struct sky2_status_le *le = hw->st_le + hw->st_idx;
struct net_device *dev;
- struct sky2_port *sky2;
struct sk_buff *skb;
u32 status;
u16 length;
@@ -1978,6 +1978,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
#endif
netif_receive_skb(skb);
+ /* Update receiver after 16 frames */
+ if (++buf_write[le->link] == RX_BUF_WRITE) {
+ sky2_put_idx(hw, rxqaddr[le->link],
+ sky2->rx_put);
+ buf_write[le->link] = 0;
+ }
+
+ /* Stop after net poll weight */
if (++work_done >= to_do)
goto exit_loop;
break;
@@ -2016,6 +2024,16 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
}
exit_loop:
+ if (buf_write[0]) {
+ sky2 = netdev_priv(hw->dev[0]);
+ sky2_put_idx(hw, Q_R1, sky2->rx_put);
+ }
+
+ if (buf_write[1]) {
+ sky2 = netdev_priv(hw->dev[1]);
+ sky2_put_idx(hw, Q_R2, sky2->rx_put);
+ }
+
return work_done;
}
@@ -2286,7 +2304,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
}
-static int __devinit sky2_reset(struct sky2_hw *hw)
+static int sky2_reset(struct sky2_hw *hw)
{
u16 status;
u8 t8, pmd_type;
@@ -3437,17 +3455,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
return -EINVAL;
del_timer_sync(&hw->idle_timer);
+ netif_poll_disable(hw->dev[0]);
for (i = 0; i < hw->ports; i++) {
struct net_device *dev = hw->dev[i];
- if (dev) {
- if (!netif_running(dev))
- continue;
-
+ if (netif_running(dev)) {
sky2_down(dev);
netif_device_detach(dev);
- netif_poll_disable(dev);
}
}
@@ -3474,9 +3489,8 @@ static int sky2_resume(struct pci_dev *pdev)
for (i = 0; i < hw->ports; i++) {
struct net_device *dev = hw->dev[i];
- if (dev && netif_running(dev)) {
+ if (netif_running(dev)) {
netif_device_attach(dev);
- netif_poll_enable(dev);
err = sky2_up(dev);
if (err) {
@@ -3488,6 +3502,7 @@ static int sky2_resume(struct pci_dev *pdev)
}
}
+ netif_poll_enable(hw->dev[0]);
sky2_idle_start(hw);
out:
return err;
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 8a0bc5525f0a..2db8d19b22d1 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1480,7 +1480,7 @@ enum {
GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */
GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */
- GM_TXCR_COL_THR_MSK = 1<<10, /* Bit 12..10: Collision Threshold */
+ GM_TXCR_COL_THR_MSK = 7<<10, /* Bit 12..10: Collision Threshold */
};
#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index b4028049ed76..4ec4b4d23ae5 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -354,6 +354,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#define SMC_IRQ_FLAGS (0)
+#elif defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT 1
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 1
+#define SMC_NOWAIT 1
+
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS (0)
+
#else
#define SMC_CAN_USE_8BIT 1
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index f645921aff8b..ce6f3be86da0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10078,6 +10078,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
static struct pci_device_id write_reorder_chipsets[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_8131_BRIDGE) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_8385_0) },
{ },
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 063816f2b11e..4103c37172f9 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
* If problems develop with TSO, check this first.
*/
numDesc = skb_shinfo(skb)->nr_frags + 1;
- if(skb_tso_size(skb))
+ if (skb_is_gso(skb))
numDesc++;
/* When checking for free space in the ring, we need to also
@@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
TYPHOON_TX_PF_VLAN_TAG_SHIFT);
}
- if(skb_tso_size(skb)) {
+ if (skb_is_gso(skb)) {
first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
first_txd->numDesc++;
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index c92ac9fde083..2c09ec908a3f 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -116,27 +116,33 @@ static inline void openwin(card_t *card, u8 page)
#include "hd6457x.c"
+static inline void set_carrier(port_t *port)
+{
+ if (!sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD)
+ netif_carrier_on(port_to_dev(port));
+ else
+ netif_carrier_off(port_to_dev(port));
+}
+
+
static void sca_msci_intr(port_t *port)
{
- struct net_device *dev = port_to_dev(port);
- card_t* card = port_to_card(port);
- u8 stat = sca_in(MSCI1_OFFSET + ST1, card); /* read MSCI ST1 status */
+ u8 stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI ST1 status */
/* Reset MSCI TX underrun status bit */
- sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, card);
+ sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, port);
if (stat & ST1_UDRN) {
- struct net_device_stats *stats = hdlc_stats(dev);
+ struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
stats->tx_errors++; /* TX Underrun error detected */
stats->tx_fifo_errors++;
}
/* Reset MSCI CDCD status bit - uses ch#2 DCD input */
- sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, card);
+ sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, port);
if (stat & ST1_CDCD)
- hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD),
- dev);
+ set_carrier(port);
}
@@ -190,7 +196,7 @@ static int c101_open(struct net_device *dev)
sca_out(IE1_UDRN, MSCI0_OFFSET + IE1, port);
sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port);
- hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), dev);
+ set_carrier(port);
printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port));
/* enable MSCI1 CDCD interrupt */
@@ -378,7 +384,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
}
sca_init_sync_port(card); /* Set up C101 memory */
- hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev);
+ set_carrier(card);
printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
" using %u TX + %u RX packets rings\n",
diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
index d3743321a977..dce2bb317b82 100644
--- a/drivers/net/wan/hd6457x.c
+++ b/drivers/net/wan/hd6457x.c
@@ -168,6 +168,23 @@ static inline u32 buffer_offset(port_t *port, u16 desc, int transmit)
}
+static inline void sca_set_carrier(port_t *port)
+{
+ if (!(sca_in(get_msci(port) + ST3, port_to_card(port)) & ST3_DCD)) {
+#ifdef DEBUG_LINK
+ printk(KERN_DEBUG "%s: sca_set_carrier on\n",
+ port_to_dev(port)->name);
+#endif
+ netif_carrier_on(port_to_dev(port));
+ } else {
+#ifdef DEBUG_LINK
+ printk(KERN_DEBUG "%s: sca_set_carrier off\n",
+ port_to_dev(port)->name);
+#endif
+ netif_carrier_off(port_to_dev(port));
+ }
+}
+
static void sca_init_sync_port(port_t *port)
{
@@ -237,9 +254,7 @@ static void sca_init_sync_port(port_t *port)
sca_out(DIR_BOFE, DIR_TX(phy_node(port)), card);
}
}
-
- hdlc_set_carrier(!(sca_in(get_msci(port) + ST3, card) & ST3_DCD),
- port_to_dev(port));
+ sca_set_carrier(port);
}
@@ -262,8 +277,7 @@ static inline void sca_msci_intr(port_t *port)
}
if (stat & ST1_CDCD)
- hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD),
- port_to_dev(port));
+ sca_set_carrier(port);
}
#endif
@@ -566,7 +580,7 @@ static void sca_open(struct net_device *dev)
- all DMA interrupts
*/
- hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), dev);
+ sca_set_carrier(port);
#ifdef __HD64570_H
/* MSCI TX INT and RX INT A IRQ enable */
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 1fd04662c4fc..f289daba0c7b 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -192,9 +192,7 @@ static int cisco_rx(struct sk_buff *skb)
"uptime %ud%uh%um%us)\n",
dev->name, days, hrs,
min, sec);
-#if 0
- netif_carrier_on(dev);
-#endif
+ netif_dormant_off(dev);
hdlc->state.cisco.up = 1;
}
}
@@ -227,9 +225,7 @@ static void cisco_timer(unsigned long arg)
hdlc->state.cisco.settings.timeout * HZ)) {
hdlc->state.cisco.up = 0;
printk(KERN_INFO "%s: Link down\n", dev->name);
-#if 0
- netif_carrier_off(dev);
-#endif
+ netif_dormant_on(dev);
}
cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
@@ -265,10 +261,7 @@ static void cisco_stop(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
del_timer_sync(&hdlc->state.cisco.timer);
-#if 0
- if (netif_carrier_ok(dev))
- netif_carrier_off(dev);
-#endif
+ netif_dormant_on(dev);
hdlc->state.cisco.up = 0;
hdlc->state.cisco.request_sent = 0;
}
@@ -328,6 +321,7 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
dev->type = ARPHRD_CISCO;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->addr_len = 0;
+ netif_dormant_on(dev);
return 0;
}
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 523afe17564e..7bb737bbdeb9 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -301,7 +301,7 @@ static int pvc_open(struct net_device *dev)
if (pvc->open_count++ == 0) {
hdlc_device *hdlc = dev_to_hdlc(pvc->master);
if (hdlc->state.fr.settings.lmi == LMI_NONE)
- pvc->state.active = hdlc->carrier;
+ pvc->state.active = netif_carrier_ok(pvc->master);
pvc_carrier(pvc->state.active, pvc);
hdlc->state.fr.dce_changed = 1;
@@ -545,11 +545,7 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
hdlc->state.fr.reliable = reliable;
if (reliable) {
-#if 0
- if (!netif_carrier_ok(dev))
- netif_carrier_on(dev);
-#endif
-
+ netif_dormant_off(dev);
hdlc->state.fr.n391cnt = 0; /* Request full status */
hdlc->state.fr.dce_changed = 1;
@@ -562,11 +558,7 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
}
}
} else {
-#if 0
- if (netif_carrier_ok(dev))
- netif_carrier_off(dev);
-#endif
-
+ netif_dormant_on(dev);
while (pvc) { /* Deactivate all PVCs */
pvc_carrier(0, pvc);
pvc->state.exist = pvc->state.active = 0;
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index b7da55140fbd..04ca1f7b6424 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -34,10 +34,11 @@
#include <linux/inetdevice.h>
#include <linux/lapb.h>
#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
#include <linux/hdlc.h>
-static const char* version = "HDLC support module revision 1.18";
+static const char* version = "HDLC support module revision 1.19";
#undef DEBUG_LINK
@@ -73,57 +74,51 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
-static void __hdlc_set_carrier_on(struct net_device *dev)
+static inline void hdlc_proto_start(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.start)
return hdlc->proto.start(dev);
-#if 0
-#ifdef DEBUG_LINK
- if (netif_carrier_ok(dev))
- printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
-#endif
- netif_carrier_on(dev);
-#endif
}
-static void __hdlc_set_carrier_off(struct net_device *dev)
+static inline void hdlc_proto_stop(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.stop)
return hdlc->proto.stop(dev);
-
-#if 0
-#ifdef DEBUG_LINK
- if (!netif_carrier_ok(dev))
- printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
-#endif
- netif_carrier_off(dev);
-#endif
}
-void hdlc_set_carrier(int on, struct net_device *dev)
+static int hdlc_device_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
{
- hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct net_device *dev = ptr;
+ hdlc_device *hdlc;
unsigned long flags;
- on = on ? 1 : 0;
+ int on;
+
+ if (dev->get_stats != hdlc_get_stats)
+ return NOTIFY_DONE; /* not an HDLC device */
+
+ if (event != NETDEV_CHANGE)
+ return NOTIFY_DONE; /* Only interrested in carrier changes */
+
+ on = netif_carrier_ok(dev);
#ifdef DEBUG_LINK
- printk(KERN_DEBUG "hdlc_set_carrier %i\n", on);
+ printk(KERN_DEBUG "%s: hdlc_device_event NETDEV_CHANGE, carrier %i\n",
+ dev->name, on);
#endif
+ hdlc = dev_to_hdlc(dev);
spin_lock_irqsave(&hdlc->state_lock, flags);
if (hdlc->carrier == on)
goto carrier_exit; /* no change in DCD line level */
-#ifdef DEBUG_LINK
- printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off");
-#endif
hdlc->carrier = on;
if (!hdlc->open)
@@ -131,14 +126,15 @@ void hdlc_set_carrier(int on, struct net_device *dev)
if (hdlc->carrier) {
printk(KERN_INFO "%s: Carrier detected\n", dev->name);
- __hdlc_set_carrier_on(dev);
+ hdlc_proto_start(dev);
} else {
printk(KERN_INFO "%s: Carrier lost\n", dev->name);
- __hdlc_set_carrier_off(dev);
+ hdlc_proto_stop(dev);
}
carrier_exit:
spin_unlock_irqrestore(&hdlc->state_lock, flags);
+ return NOTIFY_DONE;
}
@@ -165,7 +161,7 @@ int hdlc_open(struct net_device *dev)
if (hdlc->carrier) {
printk(KERN_INFO "%s: Carrier detected\n", dev->name);
- __hdlc_set_carrier_on(dev);
+ hdlc_proto_start(dev);
} else
printk(KERN_INFO "%s: No carrier\n", dev->name);
@@ -190,7 +186,7 @@ void hdlc_close(struct net_device *dev)
hdlc->open = 0;
if (hdlc->carrier)
- __hdlc_set_carrier_off(dev);
+ hdlc_proto_stop(dev);
spin_unlock_irq(&hdlc->state_lock);
@@ -303,7 +299,6 @@ MODULE_LICENSE("GPL v2");
EXPORT_SYMBOL(hdlc_open);
EXPORT_SYMBOL(hdlc_close);
-EXPORT_SYMBOL(hdlc_set_carrier);
EXPORT_SYMBOL(hdlc_ioctl);
EXPORT_SYMBOL(hdlc_setup);
EXPORT_SYMBOL(alloc_hdlcdev);
@@ -315,9 +310,18 @@ static struct packet_type hdlc_packet_type = {
};
+static struct notifier_block hdlc_notifier = {
+ .notifier_call = hdlc_device_event,
+};
+
+
static int __init hdlc_module_init(void)
{
+ int result;
+
printk(KERN_INFO "%s\n", version);
+ if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
+ return result;
dev_add_pack(&hdlc_packet_type);
return 0;
}
@@ -327,6 +331,7 @@ static int __init hdlc_module_init(void)
static void __exit hdlc_module_exit(void)
{
dev_remove_pack(&hdlc_packet_type);
+ unregister_netdevice_notifier(&hdlc_notifier);
}
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index d564224cdca9..b2031dfc4bb1 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -149,7 +149,10 @@ static inline void wanxl_cable_intr(port_t *port)
printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
port->dev->name, pm, dte, cable, dsr, dcd);
- hdlc_set_carrier(value & STATUS_CABLE_DCD, port->dev);
+ if (value & STATUS_CABLE_DCD)
+ netif_carrier_on(port->dev);
+ else
+ netif_carrier_off(port->dev);
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index e1c5a939bca4..3889f79e7128 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -1547,7 +1547,7 @@ static void handle_irq_noise(struct bcm43xx_private *bcm)
goto generate_new;
/* Get the noise samples. */
- assert(bcm->noisecalc.nr_samples <= 8);
+ assert(bcm->noisecalc.nr_samples < 8);
i = bcm->noisecalc.nr_samples;
noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 15465278c789..7f78b7801fb3 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -34,8 +34,6 @@
#include "orinoco.h"
-static unsigned char *primsym;
-static unsigned char *secsym;
static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
@@ -440,7 +438,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
*/
static int
spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
- const unsigned char *image)
+ const unsigned char *image, int secondary)
{
int ret;
const unsigned char *ptr;
@@ -455,7 +453,7 @@ spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
first_block = (const struct dblock *) ptr;
/* Read the PDA */
- if (image != primsym) {
+ if (secondary) {
ret = spectrum_read_pda(hw, pda, sizeof(pda));
if (ret)
return ret;
@@ -472,7 +470,7 @@ spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
return ret;
/* Write the PDA to the adapter */
- if (image != primsym) {
+ if (secondary) {
ret = spectrum_apply_pda(hw, first_block, pda);
if (ret)
return ret;
@@ -487,7 +485,7 @@ spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
ret = hermes_init(hw);
/* hermes_reset() should return 0 with the secondary firmware */
- if (image != primsym && ret != 0)
+ if (secondary && ret != 0)
return -ENODEV;
/* And this should work with any firmware */
@@ -509,33 +507,30 @@ spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
const struct firmware *fw_entry;
if (request_firmware(&fw_entry, primary_fw_name,
- &handle_to_dev(link)) == 0) {
- primsym = fw_entry->data;
- } else {
+ &handle_to_dev(link)) != 0) {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
primary_fw_name);
return -ENOENT;
}
- if (request_firmware(&fw_entry, secondary_fw_name,
- &handle_to_dev(link)) == 0) {
- secsym = fw_entry->data;
- } else {
- printk(KERN_ERR PFX "Cannot find firmware: %s\n",
- secondary_fw_name);
- return -ENOENT;
- }
-
/* Load primary firmware */
- ret = spectrum_dl_image(hw, link, primsym);
+ ret = spectrum_dl_image(hw, link, fw_entry->data, 0);
+ release_firmware(fw_entry);
if (ret) {
printk(KERN_ERR PFX "Primary firmware download failed\n");
return ret;
}
- /* Load secondary firmware */
- ret = spectrum_dl_image(hw, link, secsym);
+ if (request_firmware(&fw_entry, secondary_fw_name,
+ &handle_to_dev(link)) != 0) {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ secondary_fw_name);
+ return -ENOENT;
+ }
+ /* Load secondary firmware */
+ ret = spectrum_dl_image(hw, link, fw_entry->data, 1);
+ release_firmware(fw_entry);
if (ret) {
printk(KERN_ERR PFX "Secondary firmware download failed\n");
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index ce1cb2c6aa8d..72f90525bf68 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -375,10 +375,8 @@ static void int_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
case -ENODEV:
case -ENOENT:
case -ECONNRESET:
- goto kfree;
case -EPIPE:
- usb_clear_halt(urb->dev, EP_INT_IN);
- /* FALL-THROUGH */
+ goto kfree;
default:
goto resubmit;
}
@@ -580,10 +578,8 @@ static void rx_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
case -ENODEV:
case -ENOENT:
case -ECONNRESET:
- return;
case -EPIPE:
- usb_clear_halt(urb->dev, EP_DATA_IN);
- /* FALL-THROUGH */
+ return;
default:
dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
goto resubmit;
@@ -749,11 +745,9 @@ static void tx_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
case -ENODEV:
case -ENOENT:
case -ECONNRESET:
+ case -EPIPE:
dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
break;
- case -EPIPE:
- usb_clear_halt(urb->dev, EP_DATA_OUT);
- /* FALL-THROUGH */
default:
dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
goto resubmit;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 222a1cc4aa28..3fae77ffb2fa 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -6,8 +6,7 @@ menu "PCI Hotplug Support"
config HOTPLUG_PCI
tristate "Support for PCI Hotplug (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
- select HOTPLUG
+ depends on PCI && EXPERIMENTAL && HOTPLUG
---help---
Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is
@@ -77,7 +76,7 @@ config HOTPLUG_PCI_IBM
config HOTPLUG_PCI_ACPI
tristate "ACPI PCI Hotplug driver"
- depends on ACPI && HOTPLUG_PCI
+ depends on ACPI_DOCK && HOTPLUG_PCI
help
Say Y here if you have a system that supports PCI Hotplug using
ACPI.
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 36bc7c415af7..a83c1f5735d6 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -47,13 +47,13 @@ msi_register(struct msi_ops *ops)
static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
{
- memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
+ memset(p, 0, sizeof(struct msi_desc));
}
static int msi_cache_init(void)
{
msi_cachep = kmem_cache_create("msi_cache",
- NR_IRQS * sizeof(struct msi_desc),
+ sizeof(struct msi_desc),
0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL);
if (!msi_cachep)
return -ENOMEM;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index cf57d7de3765..9f79dd6d51ab 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -19,6 +19,7 @@
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
+unsigned int pci_pm_d3_delay = 10;
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
@@ -313,6 +314,14 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
} else if (dev->current_state == state)
return 0; /* we're already there */
+ /*
+ * If the device or the parent bridge can't support PCI PM, ignore
+ * the request if we're doing anything besides putting it into D0
+ * (which would only happen on boot).
+ */
+ if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
+ return 0;
+
/* find PCI PM capability in list */
pm = pci_find_capability(dev, PCI_CAP_ID_PM);
@@ -363,7 +372,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
/* Mandatory power management transition delays */
/* see PCI PM 1.1 5.6.1 table 18 */
if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
- msleep(10);
+ msleep(pci_pm_d3_delay);
else if (state == PCI_D2 || dev->current_state == PCI_D2)
udelay(200);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 9cc842b666eb..08d58fc78ee1 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -47,7 +47,7 @@ extern int pci_msi_quirk;
#else
#define pci_msi_quirk 0
#endif
-
+extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
void disable_msi_mode(struct pci_dev *dev, int pos, int type);
void pci_no_msi(void);
@@ -66,7 +66,15 @@ static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; }
static inline void pci_restore_msi_state(struct pci_dev *dev) {}
static inline void pci_restore_msix_state(struct pci_dev *dev) {}
#endif
+static inline int pci_no_d1d2(struct pci_dev *dev)
+{
+ unsigned int parent_dstates = 0;
+ if (dev->bus->self)
+ parent_dstates = dev->bus->self->no_d1d2;
+ return (dev->no_d1d2 || parent_dstates);
+
+}
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
extern struct class_device_attribute class_device_attr_cpuaffinity;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f89dbc3738b7..c5a58d1c6c1c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -815,6 +815,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;
dev->cfg_size = pci_cfg_space_size(dev);
+ dev->error_state = pci_channel_io_normal;
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index d1d7333bb71b..e3c78c39b7e4 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -400,6 +400,7 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
piix4_io_quirk(dev, "PIIX4 devres J", 0x7c, 1 << 20);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi );
/*
* ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
@@ -682,6 +683,33 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id );
+#ifdef CONFIG_ACPI_SLEEP
+
+/*
+ * Some VIA systems boot with the abnormal status flag set. This can cause
+ * the BIOS to re-POST the system on resume rather than passing control
+ * back to the OS. Clear the flag on boot
+ */
+static void __devinit quirk_via_abnormal_poweroff(struct pci_dev *dev)
+{
+ u32 reg;
+
+ acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
+ &reg);
+
+ if (reg & 0x800) {
+ printk("Clearing abnormal poweroff flag\n");
+ acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS,
+ (u16)0x800);
+ }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_via_abnormal_poweroff);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_abnormal_poweroff);
+
+#endif
+
/*
* CardBus controllers have a legacy base address that enables them
* to respond as i82365 pcmcia controllers. We don't want them to
@@ -1174,6 +1202,55 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
+#if defined(CONFIG_SCSI_SATA) || defined(CONFIG_SCSI_SATA_MODULE)
+
+/*
+ * If we are using libata we can drive this chip properly but must
+ * do this early on to make the additional device appear during
+ * the PCI scanning.
+ */
+
+static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
+{
+ u32 conf;
+ u8 hdr;
+
+ /* Only poke fn 0 */
+ if (PCI_FUNC(pdev->devfn))
+ return;
+
+ switch(pdev->device) {
+ case PCI_DEVICE_ID_JMICRON_JMB365:
+ case PCI_DEVICE_ID_JMICRON_JMB366:
+ /* Redirect IDE second PATA port to the right spot */
+ pci_read_config_dword(pdev, 0x80, &conf);
+ conf |= (1 << 24);
+ /* Fall through */
+ pci_write_config_dword(pdev, 0x80, conf);
+ case PCI_DEVICE_ID_JMICRON_JMB361:
+ case PCI_DEVICE_ID_JMICRON_JMB363:
+ pci_read_config_dword(pdev, 0x40, &conf);
+ /* Enable dual function mode, AHCI on fn 0, IDE fn1 */
+ /* Set the class codes correctly and then direct IDE 0 */
+ conf &= ~0x000F0200; /* Clear bit 9 and 16-19 */
+ conf |= 0x00C20002; /* Set bit 1, 17, 22, 23 */
+ pci_write_config_dword(pdev, 0x40, conf);
+
+ /* Reconfigure so that the PCI scanner discovers the
+ device is now multifunction */
+
+ pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr);
+ pdev->hdr_type = hdr & 0x7f;
+ pdev->multifunction = !!(hdr & 0x80);
+
+ break;
+ }
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
+
+#endif
+
#ifdef CONFIG_X86_IO_APIC
static void __init quirk_alder_ioapic(struct pci_dev *pdev)
{
@@ -1341,6 +1418,37 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_pc
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pcie_pxh);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh);
+/*
+ * Some Intel PCI Express chipsets have trouble with downstream
+ * device power management.
+ */
+static void quirk_intel_pcie_pm(struct pci_dev * dev)
+{
+ pci_pm_d3_delay = 120;
+ dev->no_d1d2 = 1;
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25e2, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25e3, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25e4, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25e5, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25e6, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25e7, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25f7, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25f8, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25f9, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x25fa, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2601, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2602, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2603, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2604, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2605, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2606, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2607, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2608, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
/*
* Fixup the cardbus bridges on the IBM Dock II docking station
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 61cb4b29f55c..35f88649d3b7 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -6,7 +6,7 @@ menu "PCCARD (PCMCIA/CardBus) support"
config PCCARD
tristate "PCCard (PCMCIA/CardBus) support"
- select HOTPLUG
+ depends on HOTPLUG
---help---
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
computer. These are credit-card size devices such as network cards,
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d7295386821c..7f6fdac74706 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -394,7 +394,7 @@ dasd_add_busid(char *bus_id, int features)
if (!new)
return ERR_PTR(-ENOMEM);
spin_lock(&dasd_devmap_lock);
- devmap = 0;
+ devmap = NULL;
hash = dasd_hash_busid(bus_id);
list_for_each_entry(tmp, &dasd_hashlists[hash], list)
if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
@@ -406,10 +406,10 @@ dasd_add_busid(char *bus_id, int features)
new->devindex = dasd_max_devindex++;
strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
new->features = features;
- new->device = 0;
+ new->device = NULL;
list_add(&new->list, &dasd_hashlists[hash]);
devmap = new;
- new = 0;
+ new = NULL;
}
spin_unlock(&dasd_devmap_lock);
kfree(new);
@@ -479,7 +479,7 @@ dasd_device_from_devindex(int devindex)
int i;
spin_lock(&dasd_devmap_lock);
- devmap = 0;
+ devmap = NULL;
for (i = 0; (i < 256) && !devmap; i++)
list_for_each_entry(tmp, &dasd_hashlists[i], list)
if (tmp->devindex == devindex) {
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 2e655f466743..39c2281371b5 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -65,16 +65,16 @@ struct dasd_eckd_private {
/* The ccw bus type uses this table to find devices that it sends to
* dasd_eckd_probe */
static struct ccw_device_id dasd_eckd_ids[] = {
- { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), driver_info: 0x1},
- { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), driver_info: 0x2},
- { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), driver_info: 0x3},
- { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), driver_info: 0x4},
- { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), driver_info: 0x5},
- { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), driver_info: 0x6},
- { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), driver_info: 0x7},
- { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), driver_info: 0x8},
- { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), driver_info: 0x9},
- { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), driver_info: 0xa},
+ { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), .driver_info = 0x1},
+ { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), .driver_info = 0x2},
+ { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), .driver_info = 0x3},
+ { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), .driver_info = 0x4},
+ { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), .driver_info = 0x5},
+ { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), .driver_info = 0x6},
+ { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), .driver_info = 0x7},
+ { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), .driver_info = 0x8},
+ { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), .driver_info = 0x9},
+ { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), .driver_info = 0xa},
{ /* end of list */ },
};
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 808434d38526..e85015be109b 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -44,8 +44,8 @@ struct dasd_fba_private {
};
static struct ccw_device_id dasd_fba_ids[] = {
- { CCW_DEVICE_DEVTYPE (0x6310, 0, 0x9336, 0), driver_info: 0x1},
- { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3370, 0), driver_info: 0x2},
+ { CCW_DEVICE_DEVTYPE (0x6310, 0, 0x9336, 0), .driver_info = 0x1},
+ { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3370, 0), .driver_info = 0x2},
{ /* end of list */ },
};
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 12c7d296eaa8..4c272b70f41a 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -84,9 +84,9 @@ void
dasd_gendisk_free(struct dasd_device *device)
{
del_gendisk(device->gdp);
- device->gdp->queue = 0;
+ device->gdp->queue = NULL;
put_disk(device->gdp);
- device->gdp = 0;
+ device->gdp = NULL;
}
/*
@@ -136,7 +136,7 @@ dasd_destroy_partitions(struct dasd_device * device)
* device->bdev to lower the offline open_count limit again.
*/
bdev = device->bdev;
- device->bdev = 0;
+ device->bdev = NULL;
/*
* See fs/partition/check.c:delete_partition
@@ -145,7 +145,7 @@ dasd_destroy_partitions(struct dasd_device * device)
*/
memset(&bpart, 0, sizeof(struct blkpg_partition));
memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
- barg.data = &bpart;
+ barg.data = (void __user *) &bpart;
barg.op = BLKPG_DEL_PARTITION;
for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index e97f5316ad2d..8fed3603e9ea 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -345,7 +345,7 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
if (bdev != bdev->bd_contains)
// ro setting is not allowed for partitions
return -EINVAL;
- if (get_user(intval, (int *)argp))
+ if (get_user(intval, (int __user *)argp))
return -EFAULT;
set_disk_ro(bdev->bd_disk, intval);
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 4c1e56b9b98d..4cd879cb9bdd 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -71,11 +71,11 @@ static int xpram_devs;
/*
* Parameter parsing functions.
*/
-static int devs = XPRAM_DEVS;
-static unsigned int sizes[XPRAM_MAX_DEVS];
+static int __initdata devs = XPRAM_DEVS;
+static char __initdata *sizes[XPRAM_MAX_DEVS];
module_param(devs, int, 0);
-module_param_array(sizes, int, NULL, 0);
+module_param_array(sizes, charp, NULL, 0);
MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \
"the default is " __MODULE_STRING(XPRAM_DEVS) "\n");
@@ -86,59 +86,6 @@ MODULE_PARM_DESC(sizes, "list of device (partition) sizes " \
"claimed by explicit sizes\n");
MODULE_LICENSE("GPL");
-#ifndef MODULE
-/*
- * Parses the kernel parameters given in the kernel parameter line.
- * The expected format is
- * <number_of_partitions>[","<partition_size>]*
- * where
- * devices is a positive integer that initializes xpram_devs
- * each size is a non-negative integer possibly followed by a
- * magnitude (k,K,m,M,g,G), the list of sizes initialises
- * xpram_sizes
- *
- * Arguments
- * str: substring of kernel parameter line that contains xprams
- * kernel parameters.
- *
- * Result 0 on success, -EINVAL else -- only for Version > 2.3
- *
- * Side effects
- * the global variabls devs is set to the value of
- * <number_of_partitions> and sizes[i] is set to the i-th
- * partition size (if provided). A parsing error of a value
- * results in this value being set to -EINVAL.
- */
-static int __init xpram_setup (char *str)
-{
- char *cp;
- int i;
-
- devs = simple_strtoul(str, &cp, 10);
- if (cp <= str || devs > XPRAM_MAX_DEVS)
- return 0;
- for (i = 0; (i < devs) && (*cp++ == ','); i++) {
- sizes[i] = simple_strtoul(cp, &cp, 10);
- if (*cp == 'g' || *cp == 'G') {
- sizes[i] <<= 20;
- cp++;
- } else if (*cp == 'm' || *cp == 'M') {
- sizes[i] <<= 10;
- cp++;
- } else if (*cp == 'k' || *cp == 'K')
- cp++;
- while (isspace(*cp)) cp++;
- }
- if (*cp == ',' && i >= devs)
- PRINT_WARN("partition sizes list has too many entries.\n");
- else if (*cp != 0)
- PRINT_WARN("ignored '%s' at end of parameter string.\n", cp);
- return 1;
-}
-
-__setup("xpram_parts=", xpram_setup);
-#endif
-
/*
* Copy expanded memory page (4kB) into main memory
* Arguments
@@ -374,7 +321,9 @@ static int __init xpram_setup_sizes(unsigned long pages)
mem_needed = 0;
mem_auto_no = 0;
for (i = 0; i < xpram_devs; i++) {
- xpram_sizes[i] = (sizes[i] + 3) & -4UL;
+ if (sizes[i])
+ xpram_sizes[i] =
+ (memparse(sizes[i], &sizes[i]) + 3) & -4UL;
if (xpram_sizes[i])
mem_needed += xpram_sizes[i];
else
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index f25c6d116f6f..2fa566fa6da4 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -693,7 +693,7 @@ raw3215_probe (struct ccw_device *cdev)
GFP_KERNEL|GFP_DMA);
if (raw->buffer == NULL) {
spin_lock(&raw3215_device_lock);
- raw3215[line] = 0;
+ raw3215[line] = NULL;
spin_unlock(&raw3215_device_lock);
kfree(raw);
return -ENOMEM;
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index 0ea6f36a2527..d83eb6358bac 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -23,7 +23,7 @@ ctrlchar_handle_sysrq(void *tty)
handle_sysrq(ctrlchar_sysrq_key, NULL, (struct tty_struct *) tty);
}
-static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq, 0);
+static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq, NULL);
#endif
diff --git a/drivers/s390/char/defkeymap.c b/drivers/s390/char/defkeymap.c
index ca15adb140d1..17027d918cf7 100644
--- a/drivers/s390/char/defkeymap.c
+++ b/drivers/s390/char/defkeymap.c
@@ -83,8 +83,8 @@ static u_short shift_ctrl_map[NR_KEYS] = {
};
ushort *key_maps[MAX_NR_KEYMAPS] = {
- plain_map, shift_map, 0, 0,
- ctrl_map, shift_ctrl_map, 0
+ plain_map, shift_map, NULL, NULL,
+ ctrl_map, shift_ctrl_map, NULL,
};
unsigned int keymap_count = 4;
@@ -145,7 +145,7 @@ char *func_table[MAX_NR_FUNC] = {
func_buf + 97,
func_buf + 103,
func_buf + 109,
- 0,
+ NULL,
};
struct kbdiacr accent_table[MAX_DIACR] = {
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 6099c14de429..ef004d089712 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -236,7 +236,7 @@ fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb)
* Process reads from fullscreen 3270.
*/
static ssize_t
-fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
+fs3270_read(struct file *filp, char __user *data, size_t count, loff_t *off)
{
struct fs3270 *fp;
struct raw3270_request *rq;
@@ -281,7 +281,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
* Process writes to fullscreen 3270.
*/
static ssize_t
-fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
+fs3270_write(struct file *filp, const char __user *data, size_t count, loff_t *off)
{
struct fs3270 *fp;
struct raw3270_request *rq;
@@ -338,10 +338,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
fp->write_command = arg;
break;
case TUBGETI:
- rc = put_user(fp->read_command, (char *) arg);
+ rc = put_user(fp->read_command, (char __user *) arg);
break;
case TUBGETO:
- rc = put_user(fp->write_command,(char *) arg);
+ rc = put_user(fp->write_command,(char __user *) arg);
break;
case TUBGETMOD:
iocb.model = fp->view.model;
@@ -350,7 +350,7 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
iocb.pf_cnt = 24;
iocb.re_cnt = 20;
iocb.map = 0;
- if (copy_to_user((char *) arg, &iocb,
+ if (copy_to_user((char __user *) arg, &iocb,
sizeof(struct raw3270_iocb)))
rc = -EFAULT;
break;
@@ -479,7 +479,7 @@ fs3270_close(struct inode *inode, struct file *filp)
struct fs3270 *fp;
fp = filp->private_data;
- filp->private_data = 0;
+ filp->private_data = NULL;
if (fp) {
fp->fs_pid = 0;
raw3270_reset(&fp->view);
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 547ef906ae2c..3be06569180d 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -103,7 +103,7 @@ out_maps:
out_kbd:
kfree(kbd);
out:
- return 0;
+ return NULL;
}
void
@@ -304,7 +304,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
if (kbd->sysrq) {
if (kbd->sysrq == K(KT_LATIN, '-')) {
kbd->sysrq = 0;
- handle_sysrq(value, 0, kbd->tty);
+ handle_sysrq(value, NULL, kbd->tty);
return;
}
if (value == '-') {
@@ -363,7 +363,7 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe,
/* disallocate map */
key_map = kbd->key_maps[tmp.kb_table];
if (key_map) {
- kbd->key_maps[tmp.kb_table] = 0;
+ kbd->key_maps[tmp.kb_table] = NULL;
kfree(key_map);
}
break;
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index e95b56f810db..95e285b2e25c 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -555,7 +555,7 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
#ifdef CONFIG_TN3270_CONSOLE
if (raw3270_registered == 0) {
spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
- rq->callback = 0;
+ rq->callback = NULL;
rc = __raw3270_start(rp, view, rq);
if (rc == 0)
while (!raw3270_request_final(rq)) {
@@ -719,8 +719,8 @@ raw3270_size_device(struct raw3270 *rp)
rc = __raw3270_size_device_vm(rp);
else
rc = __raw3270_size_device(rp);
- raw3270_init_view.dev = 0;
- rp->view = 0;
+ raw3270_init_view.dev = NULL;
+ rp->view = NULL;
up(&raw3270_init_sem);
if (rc == 0) { /* Found something. */
/* Try to find a model. */
@@ -761,8 +761,8 @@ raw3270_reset_device(struct raw3270 *rp)
rp->view = &raw3270_init_view;
raw3270_init_view.dev = rp;
rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
- raw3270_init_view.dev = 0;
- rp->view = 0;
+ raw3270_init_view.dev = NULL;
+ rp->view = NULL;
up(&raw3270_init_sem);
return rc;
}
@@ -934,7 +934,7 @@ raw3270_activate_view(struct raw3270_view *view)
else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
rc = -ENODEV;
else {
- oldview = 0;
+ oldview = NULL;
if (rp->view) {
oldview = rp->view;
oldview->fn->deactivate(oldview);
@@ -951,7 +951,7 @@ raw3270_activate_view(struct raw3270_view *view)
rp->view = nv;
if (nv->fn->activate(nv) == 0)
break;
- rp->view = 0;
+ rp->view = NULL;
}
}
}
@@ -975,7 +975,7 @@ raw3270_deactivate_view(struct raw3270_view *view)
spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
if (rp->view == view) {
view->fn->deactivate(view);
- rp->view = 0;
+ rp->view = NULL;
/* Move deactivated view to end of list. */
list_del_init(&view->list);
list_add_tail(&view->list, &rp->view_list);
@@ -985,7 +985,7 @@ raw3270_deactivate_view(struct raw3270_view *view)
rp->view = view;
if (view->fn->activate(view) == 0)
break;
- rp->view = 0;
+ rp->view = NULL;
}
}
}
@@ -1076,7 +1076,7 @@ raw3270_del_view(struct raw3270_view *view)
spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
if (rp->view == view) {
view->fn->deactivate(view);
- rp->view = 0;
+ rp->view = NULL;
}
list_del_init(&view->list);
if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
@@ -1117,9 +1117,9 @@ raw3270_delete_device(struct raw3270 *rp)
/* Disconnect from ccw_device. */
cdev = rp->cdev;
- rp->cdev = 0;
- cdev->dev.driver_data = 0;
- cdev->handler = 0;
+ rp->cdev = NULL;
+ cdev->dev.driver_data = NULL;
+ cdev->handler = NULL;
/* Put ccw_device structure. */
put_device(&cdev->dev);
@@ -1144,7 +1144,7 @@ raw3270_model_show(struct device *dev, struct device_attribute *attr, char *buf)
return snprintf(buf, PAGE_SIZE, "%i\n",
((struct raw3270 *) dev->driver_data)->model);
}
-static DEVICE_ATTR(model, 0444, raw3270_model_show, 0);
+static DEVICE_ATTR(model, 0444, raw3270_model_show, NULL);
static ssize_t
raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1152,7 +1152,7 @@ raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
return snprintf(buf, PAGE_SIZE, "%i\n",
((struct raw3270 *) dev->driver_data)->rows);
}
-static DEVICE_ATTR(rows, 0444, raw3270_rows_show, 0);
+static DEVICE_ATTR(rows, 0444, raw3270_rows_show, NULL);
static ssize_t
raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1160,7 +1160,7 @@ raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *bu
return snprintf(buf, PAGE_SIZE, "%i\n",
((struct raw3270 *) dev->driver_data)->cols);
}
-static DEVICE_ATTR(columns, 0444, raw3270_columns_show, 0);
+static DEVICE_ATTR(columns, 0444, raw3270_columns_show, NULL);
static struct attribute * raw3270_attrs[] = {
&dev_attr_model.attr,
@@ -1296,7 +1296,7 @@ raw3270_remove (struct ccw_device *cdev)
spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
if (rp->view) {
rp->view->fn->deactivate(rp->view);
- rp->view = 0;
+ rp->view = NULL;
}
while (!list_empty(&rp->view_list)) {
v = list_entry(rp->view_list.next, struct raw3270_view, list);
diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h
index b635bf8e7775..90beaa80a782 100644
--- a/drivers/s390/char/raw3270.h
+++ b/drivers/s390/char/raw3270.h
@@ -231,7 +231,7 @@ alloc_string(struct list_head *free_list, unsigned long len)
INIT_LIST_HEAD(&cs->update);
return cs;
}
- return 0;
+ return NULL;
}
static inline unsigned long
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 48b4d30a7256..7b95dab913d0 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1309,9 +1309,9 @@ static struct tape_discipline tape_discipline_34xx = {
};
static struct ccw_device_id tape_34xx_ids[] = {
- { CCW_DEVICE_DEVTYPE(0x3480, 0, 0x3480, 0), driver_info: tape_3480},
- { CCW_DEVICE_DEVTYPE(0x3490, 0, 0x3490, 0), driver_info: tape_3490},
- { /* end of list */ }
+ { CCW_DEVICE_DEVTYPE(0x3480, 0, 0x3480, 0), .driver_info = tape_3480},
+ { CCW_DEVICE_DEVTYPE(0x3490, 0, 0x3490, 0), .driver_info = tape_3490},
+ { /* end of list */ },
};
static int
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index f496f236b9c0..29718042c6c9 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -437,7 +437,7 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
{
struct string *s;
- tp->rcl_walk = 0;
+ tp->rcl_walk = NULL;
if (len <= 0)
return;
if (tp->rcl_nr >= tp->rcl_max) {
@@ -466,12 +466,12 @@ tty3270_rcl_backward(struct kbd_data *kbd)
else if (!list_empty(&tp->rcl_lines))
tp->rcl_walk = tp->rcl_lines.prev;
s = tp->rcl_walk ?
- list_entry(tp->rcl_walk, struct string, list) : 0;
+ list_entry(tp->rcl_walk, struct string, list) : NULL;
if (tp->rcl_walk) {
s = list_entry(tp->rcl_walk, struct string, list);
tty3270_update_prompt(tp, s->string, s->len);
} else
- tty3270_update_prompt(tp, 0, 0);
+ tty3270_update_prompt(tp, NULL, 0);
tty3270_set_timer(tp, 1);
}
spin_unlock_bh(&tp->view.lock);
@@ -553,7 +553,7 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
* has to be emitted to the tty and for 0x6d the screen
* needs to be redrawn.
*/
- input = 0;
+ input = NULL;
len = 0;
if (tp->input->string[0] == 0x7d) {
/* Enter: write input to tty. */
@@ -567,7 +567,7 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
tty3270_update_status(tp);
}
/* Clear input area. */
- tty3270_update_prompt(tp, 0, 0);
+ tty3270_update_prompt(tp, NULL, 0);
tty3270_set_timer(tp, 1);
} else if (tp->input->string[0] == 0x6d) {
/* Display has been cleared. Redraw. */
@@ -808,8 +808,8 @@ tty3270_release(struct raw3270_view *view)
tp = (struct tty3270 *) view;
tty = tp->tty;
if (tty) {
- tty->driver_data = 0;
- tp->tty = tp->kbd->tty = 0;
+ tty->driver_data = NULL;
+ tp->tty = tp->kbd->tty = NULL;
tty_hangup(tty);
raw3270_put_view(&tp->view);
}
@@ -948,8 +948,8 @@ tty3270_close(struct tty_struct *tty, struct file * filp)
return;
tp = (struct tty3270 *) tty->driver_data;
if (tp) {
- tty->driver_data = 0;
- tp->tty = tp->kbd->tty = 0;
+ tty->driver_data = NULL;
+ tp->tty = tp->kbd->tty = NULL;
raw3270_put_view(&tp->view);
}
}
@@ -1673,7 +1673,7 @@ tty3270_set_termios(struct tty_struct *tty, struct termios *old)
new = L_ECHO(tty) ? TF_INPUT: TF_INPUTN;
if (new != tp->inattr) {
tp->inattr = new;
- tty3270_update_prompt(tp, 0, 0);
+ tty3270_update_prompt(tp, NULL, 0);
tty3270_set_timer(tp, 1);
}
}
@@ -1759,7 +1759,7 @@ void
tty3270_notifier(int index, int active)
{
if (active)
- tty_register_device(tty3270_driver, index, 0);
+ tty_register_device(tty3270_driver, index, NULL);
else
tty_unregister_device(tty3270_driver, index);
}
@@ -1818,7 +1818,7 @@ tty3270_exit(void)
raw3270_unregister_notifier(tty3270_notifier);
driver = tty3270_driver;
- tty3270_driver = 0;
+ tty3270_driver = NULL;
tty_unregister_driver(driver);
tty3270_del_views();
}
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index c625b69ebd19..6cb23040954b 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -86,8 +86,8 @@ struct vmlogrdr_priv_t {
*/
static int vmlogrdr_open(struct inode *, struct file *);
static int vmlogrdr_release(struct inode *, struct file *);
-static ssize_t vmlogrdr_read (struct file *filp, char *data, size_t count,
- loff_t * ppos);
+static ssize_t vmlogrdr_read (struct file *filp, char __user *data,
+ size_t count, loff_t * ppos);
static struct file_operations vmlogrdr_fops = {
.owner = THIS_MODULE,
@@ -515,7 +515,7 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
static ssize_t
-vmlogrdr_read (struct file *filp, char *data, size_t count, loff_t * ppos)
+vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
{
int rc;
struct vmlogrdr_priv_t * priv = filp->private_data;
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 5acc0ace3d7d..807320a41fa4 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -193,7 +193,7 @@ static int vmwdt_ioctl(struct inode *i, struct file *f,
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
- return put_user(0, (int *)arg);
+ return put_user(0, (int __user *)arg);
case WDIOC_GETTEMP:
return -EINVAL;
case WDIOC_SETOPTIONS:
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index c7319a07ba35..f26a2ee3aad8 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -319,7 +319,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
if (!try_module_get(gdrv->owner))
return -EINVAL;
- value = simple_strtoul(buf, 0, 0);
+ value = simple_strtoul(buf, NULL, 0);
ret = count;
if (value == 1)
ccwgroup_set_online(gdev);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index a01f3bba4a7b..61ce3f1d5228 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1464,6 +1464,40 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
return desc;
}
+static int reset_channel_path(struct channel_path *chp)
+{
+ int cc;
+
+ cc = rchp(chp->id);
+ switch (cc) {
+ case 0:
+ return 0;
+ case 2:
+ return -EBUSY;
+ default:
+ return -ENODEV;
+ }
+}
+
+static void reset_channel_paths_css(struct channel_subsystem *css)
+{
+ int i;
+
+ for (i = 0; i <= __MAX_CHPID; i++) {
+ if (css->chps[i])
+ reset_channel_path(css->chps[i]);
+ }
+}
+
+void cio_reset_channel_paths(void)
+{
+ int i;
+
+ for (i = 0; i <= __MAX_CSSID; i++) {
+ if (css[i] && css[i]->valid)
+ reset_channel_paths_css(css[i]);
+ }
+}
static int __init
chsc_alloc_sei_area(void)
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 6fec90eab00e..89320c1ad825 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -519,6 +519,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
memset(sch, 0, sizeof(struct subchannel));
spin_lock_init(&sch->lock);
+ mutex_init(&sch->reg_mutex);
/* Set a name for the subchannel */
snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
@@ -797,7 +798,7 @@ struct subchannel *
cio_get_console_subchannel(void)
{
if (!console_subchannel_in_use)
- return 0;
+ return NULL;
return &console_subchannel;
}
@@ -875,5 +876,6 @@ void
reipl(unsigned long devno)
{
clear_all_subchannels();
+ cio_reset_channel_paths();
do_reipl(devno);
}
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 0ca987344e07..4541c1af4b66 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -2,6 +2,7 @@
#define S390_CIO_H
#include "schid.h"
+#include <linux/mutex.h>
/*
* where we put the ssd info
@@ -87,7 +88,7 @@ struct orb {
struct subchannel {
struct subchannel_id schid;
spinlock_t lock; /* subchannel lock */
-
+ struct mutex reg_mutex;
enum {
SUBCHANNEL_TYPE_IO = 0,
SUBCHANNEL_TYPE_CHSC = 1,
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 1c3e8e9012b0..0df3af1f08de 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1140,7 +1140,7 @@ static struct attribute *cmf_attributes[] = {
&dev_attr_avg_device_disconnect_time.attr,
&dev_attr_avg_control_unit_queuing_time.attr,
&dev_attr_avg_device_active_only_time.attr,
- 0,
+ NULL,
};
static struct attribute_group cmf_attr_group = {
@@ -1160,7 +1160,7 @@ static struct attribute *cmf_attributes_ext[] = {
&dev_attr_avg_device_active_only_time.attr,
&dev_attr_avg_device_busy_time.attr,
&dev_attr_avg_initial_command_response_time.attr,
- 0,
+ NULL,
};
static struct attribute_group cmf_attr_group_ext = {
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 1d3be80797f8..13eeea3d547f 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -108,6 +108,24 @@ css_subchannel_release(struct device *dev)
extern int css_get_ssd_info(struct subchannel *sch);
+
+int css_sch_device_register(struct subchannel *sch)
+{
+ int ret;
+
+ mutex_lock(&sch->reg_mutex);
+ ret = device_register(&sch->dev);
+ mutex_unlock(&sch->reg_mutex);
+ return ret;
+}
+
+void css_sch_device_unregister(struct subchannel *sch)
+{
+ mutex_lock(&sch->reg_mutex);
+ device_unregister(&sch->dev);
+ mutex_unlock(&sch->reg_mutex);
+}
+
static int
css_register_subchannel(struct subchannel *sch)
{
@@ -119,7 +137,7 @@ css_register_subchannel(struct subchannel *sch)
sch->dev.release = &css_subchannel_release;
/* make it known to the system */
- ret = device_register(&sch->dev);
+ ret = css_sch_device_register(sch);
if (ret)
printk (KERN_WARNING "%s: could not register %s\n",
__func__, sch->dev.bus_id);
@@ -250,7 +268,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
* The device will be killed automatically.
*/
cio_disable_subchannel(sch);
- device_unregister(&sch->dev);
+ css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
@@ -264,7 +282,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
* away in any case.
*/
if (!disc) {
- device_unregister(&sch->dev);
+ css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
@@ -605,9 +623,13 @@ init_channel_subsystem (void)
ret = device_register(&css[i]->device);
if (ret)
goto out_free;
- if (css_characteristics_avail && css_chsc_characteristics.secm)
- device_create_file(&css[i]->device,
- &dev_attr_cm_enable);
+ if (css_characteristics_avail &&
+ css_chsc_characteristics.secm) {
+ ret = device_create_file(&css[i]->device,
+ &dev_attr_cm_enable);
+ if (ret)
+ goto out_device;
+ }
}
css_init_done = 1;
@@ -615,6 +637,8 @@ init_channel_subsystem (void)
for_each_subchannel(__init_channel_subsystem, NULL);
return 0;
+out_device:
+ device_unregister(&css[i]->device);
out_free:
kfree(css[i]);
out_unregister:
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index e210f89a2449..8aabb4adeb5f 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -100,7 +100,7 @@ struct ccw_device_private {
struct qdio_irq *qdio_data;
struct irb irb; /* device status */
struct senseid senseid; /* SenseID info */
- struct pgid pgid; /* path group ID */
+ struct pgid pgid[8]; /* path group IDs per chpid*/
struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */
struct work_struct kick_work;
wait_queue_head_t wait_q;
@@ -136,6 +136,8 @@ extern struct bus_type css_bus_type;
extern struct css_driver io_subchannel_driver;
extern int css_probe_device(struct subchannel_id);
+extern int css_sch_device_register(struct subchannel *);
+extern void css_sch_device_unregister(struct subchannel *);
extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 67f0de6aed33..585fa04233c3 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -100,7 +100,7 @@ ccw_uevent (struct device *dev, char **envp, int num_envp,
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
- envp[i] = 0;
+ envp[i] = NULL;
return 0;
}
@@ -280,7 +280,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
* 'throw away device'.
*/
sch = to_subchannel(cdev->dev.parent);
- device_unregister(&sch->dev);
+ css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
@@ -625,7 +625,7 @@ ccw_device_do_unreg_rereg(void *data)
other_sch->schib.pmcw.intparm = 0;
cio_modify(other_sch);
}
- device_unregister(&other_sch->dev);
+ css_sch_device_unregister(other_sch);
}
}
/* Update ssd info here. */
@@ -709,7 +709,7 @@ ccw_device_call_sch_unregister(void *data)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- device_unregister(&sch->dev);
+ css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
@@ -1057,7 +1057,7 @@ get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
__ccwdev_check_busid);
put_driver(drv);
- return dev ? to_ccwdev(dev) : 0;
+ return dev ? to_ccwdev(dev) : NULL;
}
/************************** device driver handling ************************/
@@ -1082,7 +1082,7 @@ ccw_device_probe (struct device *dev)
ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
if (ret) {
- cdev->drv = 0;
+ cdev->drv = NULL;
return ret;
}
@@ -1113,7 +1113,7 @@ ccw_device_remove (struct device *dev)
ret, cdev->dev.bus_id);
}
ccw_device_set_timeout(cdev, 0);
- cdev->drv = 0;
+ cdev->drv = NULL;
return 0;
}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index cb1af0b6f033..ac6e0c7e43d9 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -378,6 +378,56 @@ ccw_device_done(struct ccw_device *cdev, int state)
put_device (&cdev->dev);
}
+static inline int cmp_pgid(struct pgid *p1, struct pgid *p2)
+{
+ char *c1;
+ char *c2;
+
+ c1 = (char *)p1;
+ c2 = (char *)p2;
+
+ return memcmp(c1 + 1, c2 + 1, sizeof(struct pgid) - 1);
+}
+
+static void __ccw_device_get_common_pgid(struct ccw_device *cdev)
+{
+ int i;
+ int last;
+
+ last = 0;
+ for (i = 0; i < 8; i++) {
+ if (cdev->private->pgid[i].inf.ps.state1 == SNID_STATE1_RESET)
+ /* No PGID yet */
+ continue;
+ if (cdev->private->pgid[last].inf.ps.state1 ==
+ SNID_STATE1_RESET) {
+ /* First non-zero PGID */
+ last = i;
+ continue;
+ }
+ if (cmp_pgid(&cdev->private->pgid[i],
+ &cdev->private->pgid[last]) == 0)
+ /* Non-conflicting PGIDs */
+ continue;
+
+ /* PGID mismatch, can't pathgroup. */
+ CIO_MSG_EVENT(0, "SNID - pgid mismatch for device "
+ "0.%x.%04x, can't pathgroup\n",
+ cdev->private->ssid, cdev->private->devno);
+ cdev->private->options.pgroup = 0;
+ return;
+ }
+ if (cdev->private->pgid[last].inf.ps.state1 ==
+ SNID_STATE1_RESET)
+ /* No previous pgid found */
+ memcpy(&cdev->private->pgid[0], &css[0]->global_pgid,
+ sizeof(struct pgid));
+ else
+ /* Use existing pgid */
+ memcpy(&cdev->private->pgid[0], &cdev->private->pgid[last],
+ sizeof(struct pgid));
+}
+
/*
* Function called from device_pgid.c after sense path ground has completed.
*/
@@ -388,24 +438,26 @@ ccw_device_sense_pgid_done(struct ccw_device *cdev, int err)
sch = to_subchannel(cdev->dev.parent);
switch (err) {
- case 0:
- /* Start Path Group verification. */
- sch->vpm = 0; /* Start with no path groups set. */
- cdev->private->state = DEV_STATE_VERIFY;
- ccw_device_verify_start(cdev);
+ case -EOPNOTSUPP: /* path grouping not supported, use nop instead. */
+ cdev->private->options.pgroup = 0;
+ break;
+ case 0: /* success */
+ case -EACCES: /* partial success, some paths not operational */
+ /* Check if all pgids are equal or 0. */
+ __ccw_device_get_common_pgid(cdev);
break;
case -ETIME: /* Sense path group id stopped by timeout. */
case -EUSERS: /* device is reserved for someone else. */
ccw_device_done(cdev, DEV_STATE_BOXED);
- break;
- case -EOPNOTSUPP: /* path grouping not supported, just set online. */
- cdev->private->options.pgroup = 0;
- ccw_device_done(cdev, DEV_STATE_ONLINE);
- break;
+ return;
default:
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
- break;
+ return;
}
+ /* Start Path Group verification. */
+ sch->vpm = 0; /* Start with no path groups set. */
+ cdev->private->state = DEV_STATE_VERIFY;
+ ccw_device_verify_start(cdev);
}
/*
@@ -562,8 +614,9 @@ ccw_device_online(struct ccw_device *cdev)
}
/* Do we want to do path grouping? */
if (!cdev->private->options.pgroup) {
- /* No, set state online immediately. */
- ccw_device_done(cdev, DEV_STATE_ONLINE);
+ /* Start initial path verification. */
+ cdev->private->state = DEV_STATE_VERIFY;
+ ccw_device_verify_start(cdev);
return 0;
}
/* Do a SensePGID first. */
@@ -609,6 +662,7 @@ ccw_device_offline(struct ccw_device *cdev)
/* Are we doing path grouping? */
if (!cdev->private->options.pgroup) {
/* No, set state offline immediately. */
+ sch->vpm = 0;
ccw_device_done(cdev, DEV_STATE_OFFLINE);
return 0;
}
@@ -705,8 +759,6 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
{
struct subchannel *sch;
- if (!cdev->private->options.pgroup)
- return;
if (cdev->private->state == DEV_STATE_W4SENSE) {
cdev->private->flags.doverify = 1;
return;
@@ -995,8 +1047,7 @@ static void
ccw_device_wait4io_verify(struct ccw_device *cdev, enum dev_event dev_event)
{
/* When the I/O has terminated, we have to start verification. */
- if (cdev->private->options.pgroup)
- cdev->private->flags.doverify = 1;
+ cdev->private->flags.doverify = 1;
}
static void
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 54cb64ed0786..32610fd8868e 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -33,12 +33,17 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
struct subchannel *sch;
struct ccw1 *ccw;
int ret;
+ int i;
sch = to_subchannel(cdev->dev.parent);
+ /* Return if we already checked on all paths. */
+ if (cdev->private->imask == 0)
+ return (sch->lpm == 0) ? -ENODEV : -EACCES;
+ i = 8 - ffs(cdev->private->imask);
+
/* Setup sense path group id channel program. */
ccw = cdev->private->iccws;
ccw->cmd_code = CCW_CMD_SENSE_PGID;
- ccw->cda = (__u32) __pa (&cdev->private->pgid);
ccw->count = sizeof (struct pgid);
ccw->flags = CCW_FLAG_SLI;
@@ -48,6 +53,7 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
ret = -ENODEV;
while (cdev->private->imask != 0) {
/* Try every path multiple times. */
+ ccw->cda = (__u32) __pa (&cdev->private->pgid[i]);
if (cdev->private->iretry > 0) {
cdev->private->iretry--;
ret = cio_start (sch, cdev->private->iccws,
@@ -64,7 +70,9 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
}
cdev->private->imask >>= 1;
cdev->private->iretry = 5;
+ i++;
}
+
return ret;
}
@@ -76,7 +84,7 @@ ccw_device_sense_pgid_start(struct ccw_device *cdev)
cdev->private->state = DEV_STATE_SENSE_PGID;
cdev->private->imask = 0x80;
cdev->private->iretry = 5;
- memset (&cdev->private->pgid, 0, sizeof (struct pgid));
+ memset (&cdev->private->pgid, 0, sizeof (cdev->private->pgid));
ret = __ccw_device_sense_pgid_start(cdev);
if (ret && ret != -EBUSY)
ccw_device_sense_pgid_done(cdev, ret);
@@ -91,6 +99,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
{
struct subchannel *sch;
struct irb *irb;
+ int i;
sch = to_subchannel(cdev->dev.parent);
irb = &cdev->private->irb;
@@ -124,7 +133,8 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
sch->schid.sch_no, sch->orb.lpm);
return -EACCES;
}
- if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
+ i = 8 - ffs(cdev->private->imask);
+ if (cdev->private->pgid[i].inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
"is reserved by someone else\n",
cdev->private->devno, sch->schid.ssid,
@@ -162,12 +172,6 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
memset(&cdev->private->irb, 0, sizeof(struct irb));
switch (ret) {
/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
- case 0: /* Sense Path Group ID successful. */
- if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
- memcpy(&cdev->private->pgid, &css[0]->global_pgid,
- sizeof(struct pgid));
- ccw_device_sense_pgid_done(cdev, 0);
- break;
case -EOPNOTSUPP: /* Sense Path Group ID not supported */
ccw_device_sense_pgid_done(cdev, -EOPNOTSUPP);
break;
@@ -176,13 +180,15 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
break;
case -EACCES: /* channel is not operational. */
sch->lpm &= ~cdev->private->imask;
+ /* Fall through. */
+ case 0: /* Sense Path Group ID successful. */
cdev->private->imask >>= 1;
cdev->private->iretry = 5;
/* Fall through. */
case -EAGAIN: /* Try again. */
ret = __ccw_device_sense_pgid_start(cdev);
if (ret != 0 && ret != -EBUSY)
- ccw_device_sense_pgid_done(cdev, -ENODEV);
+ ccw_device_sense_pgid_done(cdev, ret);
break;
case -EUSERS: /* device is reserved for someone else. */
ccw_device_sense_pgid_done(cdev, -EUSERS);
@@ -203,20 +209,20 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
sch = to_subchannel(cdev->dev.parent);
/* Setup sense path group id channel program. */
- cdev->private->pgid.inf.fc = func;
+ cdev->private->pgid[0].inf.fc = func;
ccw = cdev->private->iccws;
if (!cdev->private->flags.pgid_single) {
- cdev->private->pgid.inf.fc |= SPID_FUNC_MULTI_PATH;
+ cdev->private->pgid[0].inf.fc |= SPID_FUNC_MULTI_PATH;
ccw->cmd_code = CCW_CMD_SUSPEND_RECONN;
ccw->cda = 0;
ccw->count = 0;
ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ccw++;
} else
- cdev->private->pgid.inf.fc |= SPID_FUNC_SINGLE_PATH;
+ cdev->private->pgid[0].inf.fc |= SPID_FUNC_SINGLE_PATH;
ccw->cmd_code = CCW_CMD_SET_PGID;
- ccw->cda = (__u32) __pa (&cdev->private->pgid);
+ ccw->cda = (__u32) __pa (&cdev->private->pgid[0]);
ccw->count = sizeof (struct pgid);
ccw->flags = CCW_FLAG_SLI;
@@ -244,6 +250,48 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
}
/*
+ * Helper function to send a nop ccw down a path.
+ */
+static int __ccw_device_do_nop(struct ccw_device *cdev)
+{
+ struct subchannel *sch;
+ struct ccw1 *ccw;
+ int ret;
+
+ sch = to_subchannel(cdev->dev.parent);
+
+ /* Setup nop channel program. */
+ ccw = cdev->private->iccws;
+ ccw->cmd_code = CCW_CMD_NOOP;
+ ccw->cda = 0;
+ ccw->count = 0;
+ ccw->flags = CCW_FLAG_SLI;
+
+ /* Reset device status. */
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+
+ /* Try multiple times. */
+ ret = -ENODEV;
+ if (cdev->private->iretry > 0) {
+ cdev->private->iretry--;
+ ret = cio_start (sch, cdev->private->iccws,
+ cdev->private->imask);
+ /* ret is 0, -EBUSY, -EACCES or -ENODEV */
+ if ((ret != -EACCES) && (ret != -ENODEV))
+ return ret;
+ }
+ /* nop command failed on this path. Switch it off. */
+ sch->lpm &= ~cdev->private->imask;
+ sch->vpm &= ~cdev->private->imask;
+ CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel "
+ "0.%x.%04x, lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
+ return ret;
+}
+
+
+/*
* Called from interrupt context to check if a valid answer
* to Set Path Group ID was received.
*/
@@ -282,6 +330,29 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
return 0;
}
+/*
+ * Called from interrupt context to check the path status after a nop has
+ * been send.
+ */
+static int __ccw_device_check_nop(struct ccw_device *cdev)
+{
+ struct subchannel *sch;
+ struct irb *irb;
+
+ sch = to_subchannel(cdev->dev.parent);
+ irb = &cdev->private->irb;
+ if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
+ return -ETIME;
+ if (irb->scsw.cc == 3) {
+ CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
+ " lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
+ return -EACCES;
+ }
+ return 0;
+}
+
static void
__ccw_device_verify_start(struct ccw_device *cdev)
{
@@ -296,9 +367,12 @@ __ccw_device_verify_start(struct ccw_device *cdev)
if ((sch->vpm & imask) != (sch->lpm & imask))
break;
cdev->private->imask = imask;
- func = (sch->vpm & imask) ?
- SPID_FUNC_RESIGN : SPID_FUNC_ESTABLISH;
- ret = __ccw_device_do_pgid(cdev, func);
+ if (cdev->private->options.pgroup) {
+ func = (sch->vpm & imask) ?
+ SPID_FUNC_RESIGN : SPID_FUNC_ESTABLISH;
+ ret = __ccw_device_do_pgid(cdev, func);
+ } else
+ ret = __ccw_device_do_nop(cdev);
if (ret == 0 || ret == -EBUSY)
return;
cdev->private->iretry = 5;
@@ -327,7 +401,10 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
return;
sch = to_subchannel(cdev->dev.parent);
- ret = __ccw_device_check_pgid(cdev);
+ if (cdev->private->options.pgroup)
+ ret = __ccw_device_check_pgid(cdev);
+ else
+ ret = __ccw_device_check_nop(cdev);
memset(&cdev->private->irb, 0, sizeof(struct irb));
switch (ret) {
/* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */
@@ -345,11 +422,10 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
* One of those strange devices which claim to be able
* to do multipathing but not for Set Path Group ID.
*/
- if (cdev->private->flags.pgid_single) {
- ccw_device_verify_done(cdev, -EOPNOTSUPP);
- break;
- }
- cdev->private->flags.pgid_single = 1;
+ if (cdev->private->flags.pgid_single)
+ cdev->private->options.pgroup = 0;
+ else
+ cdev->private->flags.pgid_single = 1;
/* fall through. */
case -EAGAIN: /* Try again. */
__ccw_device_verify_start(cdev);
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 14bef2c179bf..caf148d5caad 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -67,8 +67,7 @@ ccw_device_path_notoper(struct ccw_device *cdev)
sch->schib.pmcw.pnom);
sch->lpm &= ~sch->schib.pmcw.pnom;
- if (cdev->private->options.pgroup)
- cdev->private->flags.doverify = 1;
+ cdev->private->flags.doverify = 1;
}
/*
@@ -180,7 +179,7 @@ ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
cdev_irb->esw.esw0.erw.auth = irb->esw.esw0.erw.auth;
/* Copy path verification required flag. */
cdev_irb->esw.esw0.erw.pvrf = irb->esw.esw0.erw.pvrf;
- if (irb->esw.esw0.erw.pvrf && cdev->private->options.pgroup)
+ if (irb->esw.esw0.erw.pvrf)
cdev->private->flags.doverify = 1;
/* Copy concurrent sense bit. */
cdev_irb->esw.esw0.erw.cons = irb->esw.esw0.erw.cons;
@@ -354,7 +353,7 @@ ccw_device_accumulate_basic_sense(struct ccw_device *cdev, struct irb *irb)
}
/* Check if path verification is required. */
if (ccw_device_accumulate_esw_valid(irb) &&
- irb->esw.esw0.erw.pvrf && cdev->private->options.pgroup)
+ irb->esw.esw0.erw.pvrf)
cdev->private->flags.doverify = 1;
}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index b70039af70d6..7c93a8798d23 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -2735,7 +2735,7 @@ qdio_free(struct ccw_device *cdev)
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
- cdev->private->qdio_data = 0;
+ cdev->private->qdio_data = NULL;
up(&irq_ptr->setting_up_sema);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 23d53bf9daf1..95f4e105cb96 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -529,7 +529,7 @@ claw_open(struct net_device *dev)
printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
#endif
CLAW_DBF_TEXT(4,trace,"open");
- if (!dev | (dev->name[0] == 0x00)) {
+ if (!dev || (dev->name[0] == 0x00)) {
CLAW_DBF_TEXT(2,trace,"BadDev");
printk(KERN_WARNING "claw: Bad device at open failing \n");
return -ENODEV;
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 189a49275433..0e863df4027a 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -692,7 +692,7 @@ iucv_retrieve_buffer (void)
iucv_debug(1, "entering");
if (iucv_cpuid != -1) {
smp_call_function_on(iucv_retrieve_buffer_cpuid,
- 0, 0, 1, iucv_cpuid);
+ NULL, 0, 1, iucv_cpuid);
/* Release the cpu reserved by iucv_declare_buffer. */
smp_put_cpu(iucv_cpuid);
iucv_cpuid = -1;
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index b452cc1afd55..5d6e6cbfa360 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -2029,7 +2029,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
count = IFNAMSIZ-1;
for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
- if ((*p == '\n') | (*p == ' ')) {
+ if ((*p == '\n') || (*p == ' ')) {
/* trailing lf, grr */
break;
} else {
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 8e8963f15731..103c41470bd2 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -4420,8 +4420,10 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
int tx_bytes = skb->len;
+#ifdef CONFIG_QETH_PERF_STATS
unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
unsigned short tso_size = skb_shinfo(skb)->gso_size;
+#endif
int rc;
QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4457,7 +4459,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
queue = card->qdio.out_qs
[qeth_get_priority_queue(card, skb, ipv, cast_type)];
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
large_send = card->options.large_send;
/*are we able to do TSO ? If so ,prepare and send it from here */
@@ -4802,7 +4804,7 @@ static struct qeth_cmd_buffer *
qeth_get_setassparms_cmd(struct qeth_card *, enum qeth_ipa_funcs,
__u16, __u16, enum qeth_prot_versions);
static int
-qeth_arp_query(struct qeth_card *card, char *udata)
+qeth_arp_query(struct qeth_card *card, char __user *udata)
{
struct qeth_cmd_buffer *iob;
struct qeth_arp_query_info qinfo = {0, };
@@ -4935,7 +4937,7 @@ qeth_get_adapter_cmd(struct qeth_card *card, __u32 command, __u32 cmdlen)
* function to send SNMP commands to OSA-E card
*/
static int
-qeth_snmp_command(struct qeth_card *card, char *udata)
+qeth_snmp_command(struct qeth_card *card, char __user *udata)
{
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
@@ -7907,9 +7909,9 @@ qeth_set_online(struct ccwgroup_device *gdev)
}
static struct ccw_device_id qeth_ids[] = {
- {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
- {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
- {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN},
+ {CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
+ {CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
+ {CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
{},
};
MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -8378,7 +8380,7 @@ out:
static struct notifier_block qeth_ip_notifier = {
qeth_ip_event,
- 0
+ NULL,
};
#ifdef CONFIG_QETH_IPV6
@@ -8431,7 +8433,7 @@ out:
static struct notifier_block qeth_ip6_notifier = {
qeth_ip6_event,
- 0
+ NULL,
};
#endif
@@ -8458,7 +8460,7 @@ qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
static struct notifier_block qeth_reboot_notifier = {
qeth_reboot_event,
- 0
+ NULL,
};
static int
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 185a9cfbcbdc..001497bbea16 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1755,7 +1755,7 @@ qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
}
-static DRIVER_ATTR(group, 0200, 0, qeth_driver_group_store);
+static DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store);
static ssize_t
qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
@@ -1783,7 +1783,7 @@ qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
return count;
}
-static DRIVER_ATTR(notifier_register, 0200, 0,
+static DRIVER_ATTR(notifier_register, 0200, NULL,
qeth_driver_notifier_register_store);
int
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 72118ee68954..b8179c27ceb6 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -66,7 +66,7 @@ smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
return;
}
rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls,
- msg, len, 0, 0, 0);
+ msg, len, NULL, NULL, NULL);
if (rc == 0) {
msg[len] = 0;
EBCASC(msg, len);
@@ -122,7 +122,7 @@ smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
struct smsg_callback *cb, *tmp;
spin_lock(&smsg_list_lock);
- cb = 0;
+ cb = NULL;
list_for_each_entry(tmp, &smsg_list, list)
if (tmp->callback == callback &&
strcmp(tmp->prefix, prefix) == 0) {
@@ -139,7 +139,7 @@ smsg_exit(void)
{
if (smsg_handle > 0) {
cpcmd("SET SMSG OFF", NULL, 0, NULL);
- iucv_sever(smsg_pathid, 0);
+ iucv_sever(smsg_pathid, NULL);
iucv_unregister_program(smsg_handle);
driver_unregister(&smsg_driver);
}
@@ -162,19 +162,19 @@ smsg_init(void)
return rc;
}
smsg_handle = iucv_register_program("SMSGIUCV ", "*MSG ",
- pgmmask, &smsg_ops, 0);
+ pgmmask, &smsg_ops, NULL);
if (!smsg_handle) {
printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
driver_unregister(&smsg_driver);
return -EIO; /* better errno ? */
}
- rc = iucv_connect (&smsg_pathid, 255, 0, "*MSG ", 0, 0, 0, 0,
- smsg_handle, 0);
+ rc = iucv_connect (&smsg_pathid, 255, NULL, "*MSG ", NULL, 0,
+ NULL, NULL, smsg_handle, NULL);
if (rc) {
printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
iucv_unregister_program(smsg_handle);
driver_unregister(&smsg_driver);
- smsg_handle = 0;
+ smsg_handle = NULL;
return -EIO;
}
cpcmd("SET SMSG IUCV", NULL, 0, NULL);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index ffb3677e354f..5399c5d99b81 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -111,6 +111,16 @@ repeat:
break;
case CRW_RSC_CPATH:
pr_debug("source is channel path %02X\n", crw[0].rsid);
+ /*
+ * Check for solicited machine checks. These are
+ * created by reset channel path and need not be
+ * reported to the common I/O layer.
+ */
+ if (crw[chain].slct) {
+ DBG(KERN_INFO"solicited machine check for "
+ "channel path %02X\n", crw[0].rsid);
+ break;
+ }
switch (crw[0].erc) {
case CRW_ERC_IPARM: /* Path has come. */
ret = chp_process_crw(crw[0].rsid, 1);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 6335f9229184..31db2b06faba 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -2227,7 +2227,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
/* setup new FSF request */
retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0,
- 0, &lock_flags, &fsf_req);
+ NULL, &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Out of resources. Could not create an "
"exchange port data request for"
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 46e14f22ec18..671f4a6a5d18 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -44,30 +44,29 @@ struct scsi_transport_template *zfcp_transport_template;
struct zfcp_data zfcp_data = {
.scsi_host_template = {
- name: ZFCP_NAME,
- proc_name: "zfcp",
- proc_info: NULL,
- detect: NULL,
- slave_alloc: zfcp_scsi_slave_alloc,
- slave_configure: zfcp_scsi_slave_configure,
- slave_destroy: zfcp_scsi_slave_destroy,
- queuecommand: zfcp_scsi_queuecommand,
- eh_abort_handler: zfcp_scsi_eh_abort_handler,
- eh_device_reset_handler: zfcp_scsi_eh_device_reset_handler,
- eh_bus_reset_handler: zfcp_scsi_eh_bus_reset_handler,
- eh_host_reset_handler: zfcp_scsi_eh_host_reset_handler,
- /* FIXME(openfcp): Tune */
- can_queue: 4096,
- this_id: -1,
- /*
- * FIXME:
- * one less? can zfcp_create_sbale cope with it?
- */
- sg_tablesize: ZFCP_MAX_SBALES_PER_REQ,
- cmd_per_lun: 1,
- unchecked_isa_dma: 0,
- use_clustering: 1,
- sdev_attrs: zfcp_sysfs_sdev_attrs,
+ .name = ZFCP_NAME,
+ .proc_name = "zfcp",
+ .proc_info = NULL,
+ .detect = NULL,
+ .slave_alloc = zfcp_scsi_slave_alloc,
+ .slave_configure = zfcp_scsi_slave_configure,
+ .slave_destroy = zfcp_scsi_slave_destroy,
+ .queuecommand = zfcp_scsi_queuecommand,
+ .eh_abort_handler = zfcp_scsi_eh_abort_handler,
+ .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
+ .eh_bus_reset_handler = zfcp_scsi_eh_bus_reset_handler,
+ .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler,
+ .can_queue = 4096,
+ .this_id = -1,
+ /*
+ * FIXME:
+ * one less? can zfcp_create_sbale cope with it?
+ */
+ .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ,
+ .cmd_per_lun = 1,
+ .unchecked_isa_dma = 0,
+ .use_clustering = 1,
+ .sdev_attrs = zfcp_sysfs_sdev_attrs,
},
.driver_version = ZFCP_VERSION,
/* rest initialised with zeros */
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 9e871de23835..601340d84410 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -93,7 +93,6 @@
#endif
/********************************** Misc Macros *******************************/
-#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#define powerof2(x) ((((x)-1)&(x))==0)
/************************* Forward Declarations *******************************/
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f9013baba05b..93bdaa3169fc 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1406,25 +1406,35 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
struct device_node *dp = op->node;
struct uart_sunsu_port *up;
struct resource *rp;
+ enum su_type type;
int err;
- if (inst >= UART_NR)
- return -EINVAL;
+ type = su_get_type(dp);
+ if (type == SU_PORT_PORT) {
+ if (inst >= UART_NR)
+ return -EINVAL;
+ up = &sunsu_ports[inst];
+ } else {
+ up = kzalloc(sizeof(*up), GFP_KERNEL);
+ if (!up)
+ return -ENOMEM;
+ }
- up = &sunsu_ports[inst];
up->port.line = inst;
spin_lock_init(&up->port.lock);
- up->su_type = su_get_type(dp);
+ up->su_type = type;
rp = &op->resource[0];
- up->port.mapbase = op->resource[0].start;
-
+ up->port.mapbase = rp->start;
up->reg_size = (rp->end - rp->start) + 1;
up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
- if (!up->port.membase)
+ if (!up->port.membase) {
+ if (type != SU_PORT_PORT)
+ kfree(up);
return -ENOMEM;
+ }
up->port.irq = op->irqs[0];
@@ -1436,8 +1446,11 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
err = 0;
if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
err = sunsu_kbd_ms_init(up);
- if (err)
+ if (err) {
+ kfree(up);
goto out_unmap;
+ }
+ dev_set_drvdata(&op->dev, up);
return 0;
}
@@ -1476,8 +1489,12 @@ static int __devexit su_remove(struct of_device *dev)
#ifdef CONFIG_SERIO
serio_unregister_port(&up->serio);
#endif
- } else if (up->port.type != PORT_UNKNOWN)
+ kfree(up);
+ } else if (up->port.type != PORT_UNKNOWN) {
uart_remove_one_port(&sunsu_reg, &up->port);
+ }
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 7fdbc5dad5fd..2ee742d40c43 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -23,6 +23,7 @@ config USB_ARCH_HAS_OHCI
default y if ARCH_LH7A404
default y if ARCH_S3C2410
default y if PXA27x
+ default y if ARCH_EP93XX
default y if ARCH_AT91RM9200
# PPC:
default y if STB03xxx
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index c7123bf71c58..4710eb02ed64 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -48,7 +48,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB_AUERSWALD) += misc/
-obj-$(CONFIG_USB_CY7C63) += misc/
+obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
obj-$(CONFIG_USB_CYTHERM) += misc/
obj-$(CONFIG_USB_EMI26) += misc/
obj-$(CONFIG_USB_EMI62) += misc/
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 3670d77e912c..ca90326f2f5c 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -291,13 +291,13 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
struct acm_ru *rcv = urb->context;
struct acm *acm = rcv->instance;
int status = urb->status;
- dbg("Entering acm_read_bulk with status %d\n", urb->status);
+ dbg("Entering acm_read_bulk with status %d", urb->status);
if (!ACM_READY(acm))
return;
if (status)
- dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
+ dev_dbg(&acm->data->dev, "bulk rx status %d", status);
buf = rcv->buffer;
buf->size = urb->actual_length;
@@ -343,7 +343,7 @@ next_buffer:
list_del(&buf->list);
spin_unlock(&acm->read_lock);
- dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
+ dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
tty_buffer_request_room(tty, buf->size);
if (!acm->throttle)
@@ -394,7 +394,7 @@ urbs:
rcv->urb->transfer_dma = buf->dma;
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
+ dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
/* This shouldn't kill the driver as unsuccessful URBs are returned to the
free-urbs-pool and resubmited ASAP */
@@ -413,7 +413,7 @@ static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
{
struct acm *acm = (struct acm *)urb->context;
- dbg("Entering acm_write_bulk with status %d\n", urb->status);
+ dbg("Entering acm_write_bulk with status %d", urb->status);
acm_write_done(acm);
acm_write_start(acm);
@@ -424,7 +424,7 @@ static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
static void acm_softint(void *private)
{
struct acm *acm = private;
- dbg("Entering acm_softint.\n");
+ dbg("Entering acm_softint.");
if (!ACM_READY(acm))
return;
@@ -440,7 +440,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
struct acm *acm;
int rv = -EINVAL;
int i;
- dbg("Entering acm_tty_open.\n");
+ dbg("Entering acm_tty_open.");
mutex_lock(&open_mutex);
@@ -541,7 +541,7 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
int wbn;
struct acm_wb *wb;
- dbg("Entering acm_tty_write to write %d bytes,\n", count);
+ dbg("Entering acm_tty_write to write %d bytes,", count);
if (!ACM_READY(acm))
return -EINVAL;
@@ -793,7 +793,7 @@ static int acm_probe (struct usb_interface *intf,
if (!buflen) {
if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
- dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
+ dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint");
buflen = intf->cur_altsetting->endpoint->extralen;
buffer = intf->cur_altsetting->endpoint->extra;
} else {
@@ -842,24 +842,24 @@ next_desc:
if (!union_header) {
if (call_interface_num > 0) {
- dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
+ dev_dbg(&intf->dev,"No union descriptor, using call management descriptor");
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
control_interface = intf;
} else {
- dev_dbg(&intf->dev,"No union descriptor, giving up\n");
+ dev_dbg(&intf->dev,"No union descriptor, giving up");
return -ENODEV;
}
} else {
control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
if (!control_interface || !data_interface) {
- dev_dbg(&intf->dev,"no interfaces\n");
+ dev_dbg(&intf->dev,"no interfaces");
return -ENODEV;
}
}
if (data_interface_num != call_interface_num)
- dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
+ dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
skip_normal_probe:
@@ -867,7 +867,7 @@ skip_normal_probe:
if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
struct usb_interface *t;
- dev_dbg(&intf->dev,"Your device has switched interfaces.\n");
+ dev_dbg(&intf->dev,"Your device has switched interfaces.");
t = control_interface;
control_interface = data_interface;
@@ -878,7 +878,7 @@ skip_normal_probe:
}
if (usb_interface_claimed(data_interface)) { /* valid in this context */
- dev_dbg(&intf->dev,"The data interface isn't available\n");
+ dev_dbg(&intf->dev,"The data interface isn't available");
return -EBUSY;
}
@@ -895,7 +895,7 @@ skip_normal_probe:
if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
/* descriptors are swapped */
struct usb_endpoint_descriptor *t;
- dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
+ dev_dbg(&intf->dev,"The data interface has switched endpoints");
t = epread;
epread = epwrite;
@@ -910,7 +910,7 @@ skip_normal_probe:
}
if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
+ dev_dbg(&intf->dev, "out of memory (acm kzalloc)");
goto alloc_fail;
}
@@ -936,26 +936,26 @@ skip_normal_probe:
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
- dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
+ dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)");
goto alloc_fail2;
}
acm->ctrl_buffer = buf;
if (acm_write_buffers_alloc(acm) < 0) {
- dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
+ dev_dbg(&intf->dev, "out of memory (write buffer alloc)");
goto alloc_fail4;
}
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->ctrlurb) {
- dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
+ dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)");
goto alloc_fail5;
}
for (i = 0; i < num_rx_buf; i++) {
struct acm_ru *rcv = &(acm->ru[i]);
if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
+ dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)");
goto alloc_fail7;
}
@@ -966,13 +966,13 @@ skip_normal_probe:
struct acm_rb *buf = &(acm->rb[i]);
if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
- dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
+ dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)");
goto alloc_fail7;
}
}
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->writeurb) {
- dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
+ dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)");
goto alloc_fail7;
}
@@ -1086,6 +1086,9 @@ static struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */
.driver_info = SINGLE_RX_URB, /* firmware bug */
},
+ { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
+ .driver_info = SINGLE_RX_URB, /* firmware bug */
+ },
/* control interfaces with various AT-command sets */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_ACM_PROTO_AT_V25TER) },
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index a08787e253aa..6e3b5358a760 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -31,9 +31,6 @@ config USB_DEVICEFS
For the format of the various /proc/bus/usb/ files, please read
<file:Documentation/usb/proc_usb_info.txt>.
- Please note that this code is completely unrelated to devfs, the
- "/dev file system support".
-
Most users want to say Y here.
config USB_BANDWIDTH
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 875596e98e42..26c8cb5f3e67 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1790,7 +1790,10 @@ static int finish_device_resume(struct usb_device *udev)
* and device drivers will know about any resume quirks.
*/
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
- if (status < 2)
+ if (status >= 0)
+ status = (status == 2 ? 0 : -ENODEV);
+
+ if (status)
dev_dbg(&udev->dev,
"gone after usb resume? status %d\n",
status);
@@ -1879,7 +1882,12 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
dev_dbg(hub->intfdev,
"port %d status %04x.%04x after resume, %d\n",
port1, portchange, devstatus, status);
+ if (status >= 0)
+ status = -ENODEV;
} else {
+ if (portchange & USB_PORT_STAT_C_SUSPEND)
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_SUSPEND);
/* TRSMRCY = 10 msec */
msleep(10);
if (udev)
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index f48c3dbc367a..3182c2224ba2 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -695,7 +695,7 @@ static void usbfs_remove_device(struct usb_device *dev)
wake_up_all(&ds->wait);
list_del_init(&ds->list);
if (ds->discsignr) {
- sinfo.si_signo = SIGPIPE;
+ sinfo.si_signo = ds->discsignr;
sinfo.si_errno = EPIPE;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = ds->disccontext;
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index f7c6d758e1b0..53d584589c26 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -34,12 +34,12 @@
/* we must assign addresses for configurable endpoints (like net2280) */
-static __initdata unsigned epnum;
+static __devinitdata unsigned epnum;
// #define MANY_ENDPOINTS
#ifdef MANY_ENDPOINTS
/* more than 15 configurable endpoints */
-static __initdata unsigned in_epnum;
+static __devinitdata unsigned in_epnum;
#endif
@@ -59,7 +59,7 @@ static __initdata unsigned in_epnum;
* NOTE: each endpoint is unidirectional, as specified by its USB
* descriptor; and isn't specific to a configuration or altsetting.
*/
-static int __init
+static int __devinit
ep_matches (
struct usb_gadget *gadget,
struct usb_ep *ep,
@@ -73,7 +73,7 @@ ep_matches (
/* endpoint already claimed? */
if (0 != ep->driver_data)
return 0;
-
+
/* only support ep0 for portable CONTROL traffic */
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (USB_ENDPOINT_XFER_CONTROL == type)
@@ -186,7 +186,7 @@ ep_matches (
return 1;
}
-static struct usb_ep * __init
+static struct usb_ep * __devinit
find_ep (struct usb_gadget *gadget, const char *name)
{
struct usb_ep *ep;
@@ -228,7 +228,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
*
* On failure, this returns a null endpoint descriptor.
*/
-struct usb_ep * __init usb_ep_autoconfig (
+struct usb_ep * __devinit usb_ep_autoconfig (
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
)
@@ -276,7 +276,7 @@ struct usb_ep * __init usb_ep_autoconfig (
return ep;
}
- /* Second, look at endpoints until an unclaimed one looks usable */
+ /* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (ep_matches (gadget, ep, desc))
return ep;
@@ -295,7 +295,7 @@ struct usb_ep * __init usb_ep_autoconfig (
* state such as ep->driver_data and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
-void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
+void __devinit usb_ep_autoconfig_reset (struct usb_gadget *gadget)
{
struct usb_ep *ep;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8320fcef0425..4fe1bec1c255 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2131,7 +2131,7 @@ eth_req_free (struct usb_ep *ep, struct usb_request *req)
}
-static void __exit
+static void /* __init_or_exit */
eth_unbind (struct usb_gadget *gadget)
{
struct eth_dev *dev = get_gadget_data (gadget);
@@ -2158,7 +2158,7 @@ eth_unbind (struct usb_gadget *gadget)
set_gadget_data (gadget, NULL);
}
-static u8 __init nibble (unsigned char c)
+static u8 __devinit nibble (unsigned char c)
{
if (likely (isdigit (c)))
return c - '0';
@@ -2168,7 +2168,7 @@ static u8 __init nibble (unsigned char c)
return 0;
}
-static int __init get_ether_addr(const char *str, u8 *dev_addr)
+static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
{
if (str) {
unsigned i;
@@ -2189,7 +2189,7 @@ static int __init get_ether_addr(const char *str, u8 *dev_addr)
return 1;
}
-static int __init
+static int __devinit
eth_bind (struct usb_gadget *gadget)
{
struct eth_dev *dev;
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index b1a9cf06f3e6..8d7f1e84cd7b 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3691,7 +3691,7 @@ static void lun_release(struct device *dev)
kref_put(&fsg->ref, fsg_release);
}
-static void __exit fsg_unbind(struct usb_gadget *gadget)
+static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
{
struct fsg_dev *fsg = get_gadget_data(gadget);
int i;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 354670d12308..408c3380d602 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1398,7 +1398,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-int __init rndis_init (void)
+int __devinit rndis_init (void)
{
u8 i;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 2956608be751..4c3c7259f019 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -264,7 +264,7 @@ int rndis_signal_disconnect (int configNr);
int rndis_state (int configNr);
extern void rndis_set_host_mac (int configNr, const u8 *addr);
-int __init rndis_init (void);
+int __devinit rndis_init (void);
void rndis_exit (void);
#endif /* _LINUX_RNDIS_H */
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 30d7664d449d..e762aa19ab0a 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1473,7 +1473,7 @@ autoconf_fail:
* Called on module unload. Frees the control request and device
* structure.
*/
-static void __exit gs_unbind(struct usb_gadget *gadget)
+static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
{
struct gs_dev *dev = get_gadget_data(gadget);
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 3a08a7ab4ce0..b7018ee487ea 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1121,7 +1121,7 @@ zero_autoresume (unsigned long _dev)
/*-------------------------------------------------------------------------*/
-static void __exit
+static void /* __init_or_exit */
zero_unbind (struct usb_gadget *gadget)
{
struct zero_dev *dev = get_gadget_data (gadget);
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index d66867aa527e..26ed757d22a6 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -41,8 +41,6 @@
#endif
#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
-#endif /* Au1200 */
-
extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
@@ -107,9 +105,9 @@ int usb_ehci_au1xxx_probe(const struct hc_driver *driver,
/* Au1200 AB USB does not support coherent memory */
if (!(read_c0_prid() & 0xff)) {
- pr_info("%s: this is chip revision AB!\n", dev->dev.name);
+ pr_info("%s: this is chip revision AB!\n", dev->name);
pr_info("%s: update your board or re-configure the kernel\n",
- dev->dev.name);
+ dev->name);
return -ENODEV;
}
#endif
@@ -228,9 +226,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int ehci_hcd_au1xxx_drv_probe(struct device *dev)
+static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct usb_hcd *hcd = NULL;
int ret;
@@ -243,10 +240,9 @@ static int ehci_hcd_au1xxx_drv_probe(struct device *dev)
return ret;
}
-static int ehci_hcd_au1xxx_drv_remove(struct device *dev)
+static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_ehci_au1xxx_remove(hcd, pdev);
return 0;
@@ -269,12 +265,13 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
}
*/
MODULE_ALIAS("au1xxx-ehci");
-/* FIXME use "struct platform_driver" */
-static struct device_driver ehci_hcd_au1xxx_driver = {
- .name = "au1xxx-ehci",
- .bus = &platform_bus_type,
+static struct platform_driver ehci_hcd_au1xxx_driver = {
.probe = ehci_hcd_au1xxx_drv_probe,
.remove = ehci_hcd_au1xxx_drv_remove,
/*.suspend = ehci_hcd_au1xxx_drv_suspend, */
/*.resume = ehci_hcd_au1xxx_drv_resume, */
+ .driver = {
+ .name = "au1xxx-ehci",
+ .bus = &platform_bus_type
+ }
};
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index cee6f538de0a..85b0b4ad4c16 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -625,10 +625,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
writel (status | CMD_RUN, &ehci->regs->command);
while (i--) {
- status = readl (&ehci->regs->port_status [i]);
- if (status & PORT_OWNER)
+ int pstatus = readl (&ehci->regs->port_status [i]);
+
+ if (pstatus & PORT_OWNER)
continue;
- if (!(status & PORT_RESUME)
+ if (!(pstatus & PORT_RESUME)
|| ehci->reset_done [i] != 0)
continue;
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 689261e44018..822914e2f43b 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -101,13 +101,16 @@ static void au1xxx_start_ohc(struct platform_device *dev)
#endif /* Au1200 */
+#ifndef CONFIG_SOC_AU1200
/* wait for reset complete (read register twice; see au1500 errata) */
while (au_readl(USB_HOST_CONFIG),
!(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
+#endif
udelay(1000);
printk(KERN_DEBUG __FILE__
": Clock to USB host has been enabled \n");
+#endif
}
static void au1xxx_stop_ohc(struct platform_device *dev)
@@ -157,9 +160,9 @@ static int usb_ohci_au1xxx_probe(const struct hc_driver *driver,
/* Au1200 AB USB does not support coherent memory */
if (!(read_c0_prid() & 0xff)) {
pr_info("%s: this is chip revision AB !!\n",
- dev->dev.name);
+ dev->name);
pr_info("%s: update your board or re-configure the kernel\n",
- dev->dev.name);
+ dev->name);
return -ENODEV;
}
#endif
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
new file mode 100644
index 000000000000..6531c4d26527
--- /dev/null
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -0,0 +1,225 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ *
+ * Bus Glue for ep93xx.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ * Based on fragments of previous driver by Russell King et al.
+ *
+ * Modified for LH7A404 from ohci-sa1111.c
+ * by Durgesh Pattamatta <pattamattad@sharpsec.com>
+ *
+ * Modified for pxa27x from ohci-lh7a404.c
+ * by Nick Bane <nick@cecomputing.co.uk> 26-8-2004
+ *
+ * Modified for ep93xx from ohci-pxa27x.c
+ * by Lennert Buytenhek <buytenh@wantstofly.org> 28-2-2006
+ * Based on an earlier driver by Ray Lehtiniemi
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/signal.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+static struct clk *usb_host_clock;
+
+static void ep93xx_start_hc(struct device *dev)
+{
+ clk_enable(usb_host_clock);
+}
+
+static void ep93xx_stop_hc(struct device *dev)
+{
+ clk_disable(usb_host_clock);
+}
+
+static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
+ struct platform_device *pdev)
+{
+ int retval;
+ struct usb_hcd *hcd;
+
+ if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+ pr_debug("resource[1] is not IORESOURCE_IRQ");
+ return -ENOMEM;
+ }
+
+ hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx");
+ if (hcd == NULL)
+ return -ENOMEM;
+
+ hcd->rsrc_start = pdev->resource[0].start;
+ hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ usb_put_hcd(hcd);
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (hcd->regs == NULL) {
+ pr_debug("ioremap failed");
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ usb_host_clock = clk_get(&pdev->dev, "usb_host");
+ ep93xx_start_hc(&pdev->dev);
+
+ ohci_hcd_init(hcd_to_ohci(hcd));
+
+ retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+ if (retval == 0)
+ return retval;
+
+ ep93xx_stop_hc(&pdev->dev);
+ iounmap(hcd->regs);
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
+
+ return retval;
+}
+
+static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
+ struct platform_device *pdev)
+{
+ usb_remove_hcd(hcd);
+ ep93xx_stop_hc(&pdev->dev);
+ clk_put(usb_host_clock);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+}
+
+static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int ret;
+
+ if ((ret = ohci_init(ohci)) < 0)
+ return ret;
+
+ if ((ret = ohci_run(ohci)) < 0) {
+ err("can't start %s", hcd->self.bus_name);
+ ohci_stop(hcd);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct hc_driver ohci_ep93xx_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "EP93xx OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
+ .irq = ohci_irq,
+ .flags = HCD_USB11 | HCD_MEMORY,
+ .start = ohci_ep93xx_start,
+ .stop = ohci_stop,
+ .urb_enqueue = ohci_urb_enqueue,
+ .urb_dequeue = ohci_urb_dequeue,
+ .endpoint_disable = ohci_endpoint_disable,
+ .get_frame_number = ohci_get_frame,
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
+};
+
+extern int usb_disabled(void);
+
+static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = -ENODEV;
+ if (!usb_disabled())
+ ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev);
+
+ return ret;
+}
+
+static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_hcd_ep93xx_remove(hcd, pdev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ochi_hcd *ohci = hcd_to_ohci(hcd);
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ ep93xx_stop_hc(&pdev->dev);
+ hcd->state = HC_STATE_SUSPENDED;
+ pdev->dev.power.power_state = PMSG_SUSPEND;
+
+ return 0;
+}
+
+static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int status;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ ep93xx_start_hc(&pdev->dev);
+ pdev->dev.power.power_state = PMSG_ON;
+ usb_hcd_resume_root_hub(hcd);
+
+ return 0;
+}
+#endif
+
+
+static struct platform_driver ohci_hcd_ep93xx_driver = {
+ .probe = ohci_hcd_ep93xx_drv_probe,
+ .remove = ohci_hcd_ep93xx_drv_remove,
+#ifdef CONFIG_PM
+ .suspend = ohci_hcd_ep93xx_drv_suspend,
+ .resume = ohci_hcd_ep93xx_drv_resume,
+#endif
+ .driver = {
+ .name = "ep93xx-ohci",
+ },
+};
+
+static int __init ohci_hcd_ep93xx_init(void)
+{
+ return platform_driver_register(&ohci_hcd_ep93xx_driver);
+}
+
+static void __exit ohci_hcd_ep93xx_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_ep93xx_driver);
+}
+
+module_init(ohci_hcd_ep93xx_init);
+module_exit(ohci_hcd_ep93xx_cleanup);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 8fb842ed5f6e..afef5ac35b4a 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -901,6 +901,10 @@ MODULE_LICENSE ("GPL");
#include "ohci-pxa27x.c"
#endif
+#ifdef CONFIG_ARCH_EP93XX
+#include "ohci-ep93xx.c"
+#endif
+
#ifdef CONFIG_SOC_AU1X00
#include "ohci-au1xxx.c"
#endif
@@ -919,6 +923,7 @@ MODULE_LICENSE ("GPL");
|| defined(CONFIG_ARCH_OMAP) \
|| defined (CONFIG_ARCH_LH7A404) \
|| defined (CONFIG_PXA27x) \
+ || defined (CONFIG_ARCH_EP93XX) \
|| defined (CONFIG_SOC_AU1X00) \
|| defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
|| defined (CONFIG_ARCH_AT91RM9200) \
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 0bb972b58336..5b0a23fd798b 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -581,14 +581,14 @@ static int ohci_hub_control (
break;
case GetHubStatus:
temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
- *(__le32 *) buf = cpu_to_le32 (temp);
+ put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
break;
case GetPortStatus:
if (!wIndex || wIndex > ports)
goto error;
wIndex--;
temp = roothub_portstatus (ohci, wIndex);
- *(__le32 *) buf = cpu_to_le32 (temp);
+ put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
#ifndef OHCI_VERBOSE_DEBUG
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index dff60568b4a1..20861650905e 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -167,8 +167,6 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
{
void __iomem *base;
- int wait_time;
- u32 control;
if (!mmio_resource_enabled(pdev, 0))
return;
@@ -179,9 +177,10 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
#ifndef __hppa__
- control = readl(base + OHCI_CONTROL);
+{
+ u32 control = readl(base + OHCI_CONTROL);
if (control & OHCI_CTRL_IR) {
- wait_time = 500; /* arbitrary; 5 seconds */
+ int wait_time = 500; /* arbitrary; 5 seconds */
writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
writel(OHCI_OCR, base + OHCI_CMDSTATUS);
while (wait_time > 0 &&
@@ -198,6 +197,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
/* reset controller, preserving RWC */
writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
}
+}
#endif
/*
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index b9fb9687f926..8ea9c915fbf9 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1507,6 +1507,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866
+#define USB_VENDOR_ID_WISEGROUP_LTD 0x6677
+#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+
#define USB_VENDOR_ID_CODEMERCS 0x07c0
#define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500
#define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501
@@ -1670,6 +1673,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index daa486dde8cf..88928a4be805 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -88,19 +88,19 @@ config USB_LED
To compile this driver as a module, choose M here: the
module will be called usbled.
-config USB_CY7C63
+config USB_CYPRESS_CY7C63
tristate "Cypress CY7C63xxx USB driver support"
depends on USB
help
Say Y here if you want to connect a Cypress CY7C63xxx
- micro controller to your computer's USB port. This driver
- supports the pre-programmed devices (incl. firmware) by
- AK Modul-Bus Computer GmbH.
+ micro controller to your computer's USB port. Currently this
+ driver supports the pre-programmed devices (incl. firmware)
+ by AK Modul-Bus Computer GmbH.
Please see: http://www.ak-modul-bus.de/stat/mikrocontroller.html
To compile this driver as a module, choose M here: the
- module will be called cy7c63.
+ module will be called cypress_cy7c63.
config USB_CYTHERM
tristate "Cypress USB thermometer driver support"
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index f25a97227297..2927260c5812 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -4,7 +4,7 @@
#
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
-obj-$(CONFIG_USB_CY7C63) += cy7c63.o
+obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
obj-$(CONFIG_USB_EMI26) += emi26.o
obj-$(CONFIG_USB_EMI62) += emi62.o
diff --git a/drivers/usb/misc/cy7c63.c b/drivers/usb/misc/cy7c63.c
deleted file mode 100644
index 8a1c10b89b76..000000000000
--- a/drivers/usb/misc/cy7c63.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-* cy7c63.c
-*
-* Copyright (c) 2006 Oliver Bock (bock@fh-wolfenbuettel.de)
-*
-* This driver is based on the Cypress Thermometer USB Driver by
-* Marcus Maul and the 2.0 version of Greg Kroah-Hartman's
-* USB Skeleton driver.
-*
-* Is is a generic driver for the Cypress CY7C63000 family.
-* For the time being it enables you to toggle the single I/O ports
-* of the device.
-*
-* Supported vendors: AK Modul-Bus Computer GmbH
-* Supported devices: CY7C63001A-PC (to be continued...)
-* Supported functions: Read/Write Ports (to be continued...)
-*
-* Chipsets families: CY7C63000, CY7C63001, CY7C63100, CY7C63101
-*
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, version 2.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-
-#define DRIVER_AUTHOR "Oliver Bock (bock@fh-wolfenbuettel.de)"
-#define DRIVER_DESC "Cypress CY7C63xxx USB driver"
-
-#define CY7C63_VENDOR_ID 0xa2c
-#define CY7C63_PRODUCT_ID 0x8
-
-#define CY7C63_READ_PORT 0x4
-#define CY7C63_WRITE_PORT 0x5
-#define CY7C63_READ_RAM 0x2
-#define CY7C63_WRITE_RAM 0x3
-#define CY7C63_READ_ROM 0x1
-
-#define CY7C63_READ_PORT_ID0 0
-#define CY7C63_WRITE_PORT_ID0 0
-#define CY7C63_READ_PORT_ID1 0x2
-#define CY7C63_WRITE_PORT_ID1 1
-
-#define CY7C63_MAX_REQSIZE 8
-
-
-/* table of devices that work with this driver */
-static struct usb_device_id cy7c63_table [] = {
- { USB_DEVICE(CY7C63_VENDOR_ID, CY7C63_PRODUCT_ID) },
- { }
-};
-MODULE_DEVICE_TABLE(usb, cy7c63_table);
-
-/* structure to hold all of our device specific stuff */
-struct cy7c63 {
- struct usb_device * udev;
- char port0;
- char port1;
-};
-
-/* used to send usb control messages to device */
-int vendor_command(struct cy7c63 *dev, unsigned char request,
- unsigned char address, unsigned char data) {
-
- int retval = 0;
- unsigned int pipe;
- unsigned char *iobuf;
-
- /* allocate some memory for the i/o buffer*/
- iobuf = kzalloc(CY7C63_MAX_REQSIZE, GFP_KERNEL);
- if (!iobuf) {
- dev_err(&dev->udev->dev, "Out of memory!\n");
- retval = -ENOMEM;
- goto error;
- }
-
- dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
-
- /* prepare usb control message and send it upstream */
- pipe = usb_rcvctrlpipe(dev->udev, 0);
- retval = usb_control_msg(dev->udev, pipe, request,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- address, data, iobuf, CY7C63_MAX_REQSIZE,
- USB_CTRL_GET_TIMEOUT);
-
- /* store returned data (more READs to be added!) */
- switch (request) {
- case CY7C63_READ_PORT:
- if (address == CY7C63_READ_PORT_ID0) {
- dev->port0 = iobuf[1];
- dev_dbg(&dev->udev->dev,
- "READ_PORT0 returned: %d\n",dev->port0);
- }
- else if (address == CY7C63_READ_PORT_ID1) {
- dev->port1 = iobuf[1];
- dev_dbg(&dev->udev->dev,
- "READ_PORT1 returned: %d\n",dev->port1);
- }
- break;
- }
-
- kfree(iobuf);
-error:
- return retval;
-}
-
-#define get_set_port(num,read_id,write_id) \
-static ssize_t set_port##num(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t count) { \
- \
- int value; \
- int result = 0; \
- \
- struct usb_interface *intf = to_usb_interface(dev); \
- struct cy7c63 *cyp = usb_get_intfdata(intf); \
- \
- dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", num); \
- \
- /* validate input data */ \
- if (sscanf(buf, "%d", &value) < 1) { \
- result = -EINVAL; \
- goto error; \
- } \
- if (value>255 || value<0) { \
- result = -EINVAL; \
- goto error; \
- } \
- \
- result = vendor_command(cyp, CY7C63_WRITE_PORT, write_id, \
- (unsigned char)value); \
- \
- dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n",result); \
-error: \
- return result < 0 ? result : count; \
-} \
- \
-static ssize_t get_port##num(struct device *dev, \
- struct device_attribute *attr, char *buf) { \
- \
- int result = 0; \
- \
- struct usb_interface *intf = to_usb_interface(dev); \
- struct cy7c63 *cyp = usb_get_intfdata(intf); \
- \
- dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", num); \
- \
- result = vendor_command(cyp, CY7C63_READ_PORT, read_id, 0); \
- \
- dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); \
- \
- return sprintf(buf, "%d", cyp->port##num); \
-} \
-static DEVICE_ATTR(port##num, S_IWUGO | S_IRUGO, get_port##num, set_port##num);
-
-get_set_port(0, CY7C63_READ_PORT_ID0, CY7C63_WRITE_PORT_ID0);
-get_set_port(1, CY7C63_READ_PORT_ID1, CY7C63_WRITE_PORT_ID1);
-
-static int cy7c63_probe(struct usb_interface *interface,
- const struct usb_device_id *id) {
-
- struct cy7c63 *dev = NULL;
- int retval = -ENOMEM;
-
- /* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&dev->udev->dev, "Out of memory!\n");
- goto error;
- }
-
- dev->udev = usb_get_dev(interface_to_usbdev(interface));
-
- /* save our data pointer in this interface device */
- usb_set_intfdata(interface, dev);
-
- /* create device attribute files */
- device_create_file(&interface->dev, &dev_attr_port0);
- device_create_file(&interface->dev, &dev_attr_port1);
-
- /* let the user know what node this device is now attached to */
- dev_info(&interface->dev,
- "Cypress CY7C63xxx device now attached\n");
-
- retval = 0;
-error:
- return retval;
-}
-
-static void cy7c63_disconnect(struct usb_interface *interface) {
-
- struct cy7c63 *dev;
-
- dev = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
-
- /* remove device attribute files */
- device_remove_file(&interface->dev, &dev_attr_port0);
- device_remove_file(&interface->dev, &dev_attr_port1);
-
- usb_put_dev(dev->udev);
-
- dev_info(&interface->dev,
- "Cypress CY7C63xxx device now disconnected\n");
-
- kfree(dev);
-}
-
-static struct usb_driver cy7c63_driver = {
- .name = "cy7c63",
- .probe = cy7c63_probe,
- .disconnect = cy7c63_disconnect,
- .id_table = cy7c63_table,
-};
-
-static int __init cy7c63_init(void) {
-
- int result;
-
- /* register this driver with the USB subsystem */
- result = usb_register(&cy7c63_driver);
- if (result) {
- err("Function usb_register failed! Error number: %d\n", result);
- }
-
- return result;
-}
-
-static void __exit cy7c63_exit(void) {
-
- /* deregister this driver with the USB subsystem */
- usb_deregister(&cy7c63_driver);
-}
-
-module_init(cy7c63_init);
-module_exit(cy7c63_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
new file mode 100644
index 000000000000..e091d327bd9e
--- /dev/null
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -0,0 +1,279 @@
+/*
+* cypress_cy7c63.c
+*
+* Copyright (c) 2006 Oliver Bock (o.bock@fh-wolfenbuettel.de)
+*
+* This driver is based on the Cypress USB Driver by Marcus Maul
+* (cyport) and the 2.0 version of Greg Kroah-Hartman's
+* USB Skeleton driver.
+*
+* This is a generic driver for the Cypress CY7C63xxx family.
+* For the time being it enables you to read from and write to
+* the single I/O ports of the device.
+*
+* Supported vendors: AK Modul-Bus Computer GmbH
+* Supported devices: CY7C63001A-PC (to be continued...)
+* Supported functions: Read/Write Ports (to be continued...)
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation, version 2.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+
+#define DRIVER_AUTHOR "Oliver Bock (o.bock@fh-wolfenbuettel.de)"
+#define DRIVER_DESC "Cypress CY7C63xxx USB driver"
+
+#define CYPRESS_VENDOR_ID 0xa2c
+#define CYPRESS_PRODUCT_ID 0x8
+
+#define CYPRESS_READ_PORT 0x4
+#define CYPRESS_WRITE_PORT 0x5
+
+#define CYPRESS_READ_RAM 0x2
+#define CYPRESS_WRITE_RAM 0x3
+#define CYPRESS_READ_ROM 0x1
+
+#define CYPRESS_READ_PORT_ID0 0
+#define CYPRESS_WRITE_PORT_ID0 0
+#define CYPRESS_READ_PORT_ID1 0x2
+#define CYPRESS_WRITE_PORT_ID1 1
+
+#define CYPRESS_MAX_REQSIZE 8
+
+
+/* table of devices that work with this driver */
+static struct usb_device_id cypress_table [] = {
+ { USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, cypress_table);
+
+/* structure to hold all of our device specific stuff */
+struct cypress {
+ struct usb_device * udev;
+ unsigned char port[2];
+};
+
+/* used to send usb control messages to device */
+static int vendor_command(struct cypress *dev, unsigned char request,
+ unsigned char address, unsigned char data)
+{
+ int retval = 0;
+ unsigned int pipe;
+ unsigned char *iobuf;
+
+ /* allocate some memory for the i/o buffer*/
+ iobuf = kzalloc(CYPRESS_MAX_REQSIZE, GFP_KERNEL);
+ if (!iobuf) {
+ dev_err(&dev->udev->dev, "Out of memory!\n");
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
+
+ /* prepare usb control message and send it upstream */
+ pipe = usb_rcvctrlpipe(dev->udev, 0);
+ retval = usb_control_msg(dev->udev, pipe, request,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ address, data, iobuf, CYPRESS_MAX_REQSIZE,
+ USB_CTRL_GET_TIMEOUT);
+
+ /* store returned data (more READs to be added) */
+ switch (request) {
+ case CYPRESS_READ_PORT:
+ if (address == CYPRESS_READ_PORT_ID0) {
+ dev->port[0] = iobuf[1];
+ dev_dbg(&dev->udev->dev,
+ "READ_PORT0 returned: %d\n",
+ dev->port[0]);
+ }
+ else if (address == CYPRESS_READ_PORT_ID1) {
+ dev->port[1] = iobuf[1];
+ dev_dbg(&dev->udev->dev,
+ "READ_PORT1 returned: %d\n",
+ dev->port[1]);
+ }
+ break;
+ }
+
+ kfree(iobuf);
+error:
+ return retval;
+}
+
+/* write port value */
+static ssize_t write_port(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count,
+ int port_num, int write_id)
+{
+ int value = -1;
+ int result = 0;
+
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct cypress *cyp = usb_get_intfdata(intf);
+
+ dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", port_num);
+
+ /* validate input data */
+ if (sscanf(buf, "%d", &value) < 1) {
+ result = -EINVAL;
+ goto error;
+ }
+ if (value < 0 || value > 255) {
+ result = -EINVAL;
+ goto error;
+ }
+
+ result = vendor_command(cyp, CYPRESS_WRITE_PORT, write_id,
+ (unsigned char)value);
+
+ dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
+error:
+ return result < 0 ? result : count;
+}
+
+/* attribute callback handler (write) */
+static ssize_t set_port0_handler(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return write_port(dev, attr, buf, count, 0, CYPRESS_WRITE_PORT_ID0);
+}
+
+/* attribute callback handler (write) */
+static ssize_t set_port1_handler(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return write_port(dev, attr, buf, count, 1, CYPRESS_WRITE_PORT_ID1);
+}
+
+/* read port value */
+static ssize_t read_port(struct device *dev, struct device_attribute *attr,
+ char *buf, int port_num, int read_id)
+{
+ int result = 0;
+
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct cypress *cyp = usb_get_intfdata(intf);
+
+ dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", port_num);
+
+ result = vendor_command(cyp, CYPRESS_READ_PORT, read_id, 0);
+
+ dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
+
+ return sprintf(buf, "%d", cyp->port[port_num]);
+}
+
+/* attribute callback handler (read) */
+static ssize_t get_port0_handler(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0);
+}
+
+/* attribute callback handler (read) */
+static ssize_t get_port1_handler(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1);
+}
+
+static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO,
+ get_port0_handler, set_port0_handler);
+
+static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO,
+ get_port1_handler, set_port1_handler);
+
+
+static int cypress_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct cypress *dev = NULL;
+ int retval = -ENOMEM;
+
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ dev_err(&dev->udev->dev, "Out of memory!\n");
+ goto error;
+ }
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
+ /* create device attribute files */
+ device_create_file(&interface->dev, &dev_attr_port0);
+ device_create_file(&interface->dev, &dev_attr_port1);
+
+ /* let the user know that the device is now attached */
+ dev_info(&interface->dev,
+ "Cypress CY7C63xxx device now attached\n");
+
+ retval = 0;
+error:
+ return retval;
+}
+
+static void cypress_disconnect(struct usb_interface *interface)
+{
+ struct cypress *dev;
+
+ dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+ /* remove device attribute files */
+ device_remove_file(&interface->dev, &dev_attr_port0);
+ device_remove_file(&interface->dev, &dev_attr_port1);
+
+ usb_put_dev(dev->udev);
+
+ dev_info(&interface->dev,
+ "Cypress CY7C63xxx device now disconnected\n");
+
+ kfree(dev);
+}
+
+static struct usb_driver cypress_driver = {
+ .name = "cypress_cy7c63",
+ .probe = cypress_probe,
+ .disconnect = cypress_disconnect,
+ .id_table = cypress_table,
+};
+
+static int __init cypress_init(void)
+{
+ int result;
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&cypress_driver);
+ if (result) {
+ err("Function usb_register failed! Error number: %d\n", result);
+ }
+
+ return result;
+}
+
+static void __exit cypress_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&cypress_driver);
+}
+
+module_init(cypress_init);
+module_exit(cypress_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index c82c402285a0..e095772dd8e9 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -200,10 +200,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
/* create a urb, and a buffer for it, and copy the data to the urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- retval = -ENOMEM;
- goto error;
- }
+ if (!urb)
+ return -ENOMEM;
buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index e02c1a30c4cd..f961a770cee2 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -64,7 +64,6 @@ struct mon_reader_text {
};
static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
-static void mon_text_dtor(void *, kmem_cache_t *, unsigned long);
/*
* mon_text_submit
@@ -268,7 +267,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
(long)rp);
rp->e_slab = kmem_cache_create(rp->slab_name,
sizeof(struct mon_event_text), sizeof(long), 0,
- mon_text_ctor, mon_text_dtor);
+ mon_text_ctor, NULL);
if (rp->e_slab == NULL) {
rc = -ENOMEM;
goto err_slab;
@@ -459,7 +458,3 @@ static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
memset(mem, 0xe5, sizeof(struct mon_event_text));
}
-static void mon_text_dtor(void *mem, kmem_cache_t *slab, unsigned long sflags)
-{
- ;
-}
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 718f8e2b552b..e5e6e4f3ef87 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -128,11 +128,13 @@
#define VENDOR_ID_MELCO 0x0411
#define VENDOR_ID_MICRONET 0x3980
#define VENDOR_ID_LONGSHINE 0x07b8
+#define VENDOR_ID_ZYXEL 0x0586
#define PRODUCT_ID_RTL8150 0x8150
#define PRODUCT_ID_LUAKTX 0x0012
#define PRODUCT_ID_LCS8138TX 0x401a
#define PRODUCT_ID_SP128AR 0x0003
+#define PRODUCT_ID_PRESTIGE 0x401a
#undef EEPROM_WRITE
@@ -142,6 +144,7 @@ static struct usb_device_id rtl8150_table[] = {
{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
{USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},
{USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},
+ {USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)},
{}
};
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 8bd44fda5eaf..ac33bd47cfce 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -456,6 +456,17 @@ config USB_SERIAL_SAFE_PADDED
bool "USB Secure Encapsulated Driver - Padded"
depends on USB_SERIAL_SAFE
+config USB_SERIAL_SIERRAWIRELESS
+ tristate "USB Sierra Wireless Driver"
+ depends on USB_SERIAL
+ help
+ Say M here if you want to use a Sierra Wireless device (if
+ using an PC 5220 or AC580 please use the Airprime driver
+ instead).
+
+ To compile this driver as a module, choose M here: the
+ module will be called sierra.
+
config USB_SERIAL_TI
tristate "USB TI 3410/5052 Serial Driver"
depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 5a0960fc9d3e..35d4acc7f1d3 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
+obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 94b9ba0ff875..62082532a8b3 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -13,7 +13,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c
index 343f6f228220..01843ef8c11e 100644
--- a/drivers/usb/serial/anydata.c
+++ b/drivers/usb/serial/anydata.c
@@ -13,7 +13,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x16d5, 0x6501) }, /* AirData CDMA device */
@@ -71,7 +71,7 @@ static int anydata_open(struct usb_serial_port *port, struct file *filp)
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
- usb_serial_generic_write_bulk_callback, port);
+ usb_serial_generic_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 8dec796222a0..970d9ef0a7a5 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -21,7 +21,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static int debug;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 3faa7aa0111a..70ece9e01ce4 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -74,7 +74,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "belkin_sa.h"
static int debug;
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index f2d993b70c18..6542f220468f 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -13,7 +13,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
{
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 3d456b32c316..3a9073dbfe6a 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -17,11 +17,10 @@
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
static int debug;
-#include "usb-serial.h"
-
struct usbcons_info {
int magic;
int break_flag;
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index df0a4f98b4ae..486c7411b9a7 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -26,7 +26,7 @@
#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <asm/uaccess.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
/*
* Version Information
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 49b51ab0d4cb..6286aba86fae 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -39,7 +39,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#define CYBERJACK_LOCAL_BUF_SIZE 32
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 4ff2dfb299bd..ee70fddcab60 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -59,11 +59,11 @@
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
#include <linux/serial.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
-#include "usb-serial.h"
#include "cypress_m8.h"
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 6953d3ef5738..9b225183fc7a 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -246,7 +246,7 @@
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/wait.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
/* Defines */
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 1e2b31eeb497..daafe405d86d 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -62,7 +62,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static int debug;
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index debc3b0f9662..5169c2d154ab 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -15,7 +15,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 8a74b19f1283..b458aedc5fb6 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -257,7 +257,7 @@
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/serial.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "ftdi_sio.h"
/*
@@ -313,6 +313,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -500,6 +501,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
+ { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -548,11 +551,17 @@ struct ftdi_private {
spinlock_t rx_lock; /* spinlock for receive state */
struct work_struct rx_work;
int rx_processed;
+ unsigned long rx_bytes;
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
int force_baud; /* if non-zero, force the baud rate to this value */
int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
+
+ spinlock_t tx_lock; /* spinlock for transmit state */
+ unsigned long tx_bytes;
+ unsigned long tx_outstanding_bytes;
+ unsigned long tx_outstanding_urbs;
};
/* Used for TIOCMIWAIT */
@@ -626,6 +635,9 @@ static struct usb_serial_driver ftdi_sio_device = {
#define HIGH 1
#define LOW 0
+/* number of outstanding urbs to prevent userspace DoS from happening */
+#define URB_UPPER_LIMIT 42
+
/*
* ***************************************************************************
* Utlity functions
@@ -1156,6 +1168,7 @@ static int ftdi_sio_attach (struct usb_serial *serial)
}
spin_lock_init(&priv->rx_lock);
+ spin_lock_init(&priv->tx_lock);
init_waitqueue_head(&priv->delta_msr_wait);
/* This will push the characters through immediately rather
than queue a task to deliver them */
@@ -1270,6 +1283,13 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
dbg("%s", __FUNCTION__);
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ priv->tx_bytes = 0;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ priv->rx_bytes = 0;
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+
if (port->tty)
port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
@@ -1372,6 +1392,7 @@ static int ftdi_write (struct usb_serial_port *port,
int data_offset ; /* will be 1 for the SIO and 0 otherwise */
int status;
int transfer_size;
+ unsigned long flags;
dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
@@ -1379,6 +1400,13 @@ static int ftdi_write (struct usb_serial_port *port,
dbg("write request of 0 bytes");
return 0;
}
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ dbg("%s - write limit hit\n", __FUNCTION__);
+ return 0;
+ }
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
data_offset = priv->write_offset;
dbg("data_offset set to %d",data_offset);
@@ -1445,6 +1473,12 @@ static int ftdi_write (struct usb_serial_port *port,
err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
count = status;
kfree (buffer);
+ } else {
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ ++priv->tx_outstanding_urbs;
+ priv->tx_outstanding_bytes += count;
+ priv->tx_bytes += count;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
}
/* we are done with this urb, so let the host driver
@@ -1460,7 +1494,11 @@ static int ftdi_write (struct usb_serial_port *port,
static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
+ unsigned long flags;
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct ftdi_private *priv;
+ int data_offset; /* will be 1 for the SIO and 0 otherwise */
+ unsigned long countback;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
@@ -1472,34 +1510,67 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
return;
}
+ priv = usb_get_serial_port_data(port);
+ if (!priv) {
+ dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
+ return;
+ }
+ /* account for transferred data */
+ countback = urb->actual_length;
+ data_offset = priv->write_offset;
+ if (data_offset > 0) {
+ /* Subtract the control bytes */
+ countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
+ }
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ --priv->tx_outstanding_urbs;
+ priv->tx_outstanding_bytes -= countback;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
usb_serial_port_softint(port);
} /* ftdi_write_bulk_callback */
static int ftdi_write_room( struct usb_serial_port *port )
{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ int room;
+ unsigned long flags;
+
dbg("%s - port %d", __FUNCTION__, port->number);
- /*
- * We really can take anything the user throws at us
- * but let's pick a nice big number to tell the tty
- * layer that we have lots of free space
- */
- return 2048;
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
+ /*
+ * We really can take anything the user throws at us
+ * but let's pick a nice big number to tell the tty
+ * layer that we have lots of free space
+ */
+ room = 2048;
+ } else {
+ room = 0;
+ }
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ return room;
} /* ftdi_write_room */
static int ftdi_chars_in_buffer (struct usb_serial_port *port)
{ /* ftdi_chars_in_buffer */
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ int buffered;
+ unsigned long flags;
+
dbg("%s - port %d", __FUNCTION__, port->number);
- /*
- * We can't really account for how much data we
- * have sent out, but hasn't made it through to the
- * device, so just tell the tty layer that everything
- * is flushed.
- */
- return 0;
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ buffered = (int)priv->tx_outstanding_bytes;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ if (buffered < 0) {
+ err("%s outstanding tx bytes is negative!", __FUNCTION__);
+ buffered = 0;
+ }
+ return buffered;
} /* ftdi_chars_in_buffer */
@@ -1509,6 +1580,8 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty;
struct ftdi_private *priv;
+ unsigned long countread;
+ unsigned long flags;
if (urb->number_of_packets > 0) {
err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
@@ -1543,6 +1616,13 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
return;
}
+ /* count data bytes, but not status bytes */
+ countread = urb->actual_length;
+ countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ);
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ priv->rx_bytes += countread;
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+
ftdi_process_read(port);
} /* ftdi_read_bulk_callback */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 6ab2ac845bd7..04ef90fcb876 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -36,6 +36,9 @@
#define FTDI_ACTZWAVE_PID 0xF2D0
+/* www.starting-point-systems.com µChameleon device */
+#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */
+
/* www.irtrans.de device */
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
@@ -442,6 +445,18 @@
*/
#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */
+/*
+ * ThorLabs USB motor drivers
+ */
+#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */
+
+/*
+ * Testo products (http://www.testo.com/)
+ * Submitted by Colin Leroy
+ */
+#define TESTO_VID 0x128D
+#define TESTO_USB_INTERFACE_PID 0x0001
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 803721b97e2e..77b977206a8c 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -13,7 +13,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1404, 0xcddc) },
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 1f5d1620baa1..727852634be9 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
/* the mode to be set when the port ist opened */
static int initial_mode = 1;
@@ -42,8 +43,6 @@ static int initial_mode = 1;
/* debug flag */
static int debug = 0;
-#include "usb-serial.h"
-
#define GARMIN_VENDOR_ID 0x091E
/*
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 945b8bb38c92..172713556393 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -17,8 +17,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
#include <asm/uaccess.h>
-#include "usb-serial.h"
static int debug;
@@ -285,6 +285,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
+EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 7e06358b0310..ebcac701b069 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -17,7 +17,7 @@
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
/*
* Version Information
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index bd2c05dac2a9..c49976c3ad52 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -44,7 +44,7 @@
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "io_edgeport.h"
#include "io_ionsp.h" /* info for the iosp messages */
#include "io_16654.h" /* 16654 UART defines */
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 723a12ae87b5..17c5b1d2311a 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -39,8 +39,8 @@
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
-#include "usb-serial.h"
#include "io_16654.h"
#include "io_usbvend.h"
#include "io_ti.h"
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index dbcfe172a5cc..59c5d999009a 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -55,7 +55,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "ipaq.h"
#define KP_RETRIES 100
@@ -70,6 +70,8 @@
static __u16 product, vendor;
static int debug;
+static int connect_retries = KP_RETRIES;
+static int initial_wait;
/* Function prototypes for an ipaq */
static int ipaq_open (struct usb_serial_port *port, struct file *filp);
@@ -582,7 +584,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
struct ipaq_private *priv;
struct ipaq_packet *pkt;
int i, result = 0;
- int retries = KP_RETRIES;
+ int retries = connect_retries;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -646,16 +648,12 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
port->read_urb->transfer_buffer_length = URBDATA_SIZE;
port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
+ msleep(1000*initial_wait);
/* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ipaq_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result) {
- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
- goto error;
- }
/*
* Send out control message observed in win98 sniffs. Not sure what
@@ -670,8 +668,14 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
0x1, 0, NULL, 0, 100);
if (result == 0) {
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+ err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+ goto error;
+ }
return 0;
}
+ msleep(1000);
}
err("%s - failed doing control urb, error %d", __FUNCTION__, result);
goto error;
@@ -854,6 +858,7 @@ static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
if (urb->status) {
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ return;
}
spin_lock_irqsave(&write_list_lock, flags);
@@ -966,3 +971,9 @@ MODULE_PARM_DESC(vendor, "User specified USB idVendor");
module_param(product, ushort, 0);
MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+module_param(connect_retries, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)");
+
+module_param(initial_wait, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(initial_wait, "Time to wait before attempting a connection (in seconds)");
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index a4a0bfeaab00..87306cb6f9f5 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -46,8 +46,8 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
#include <asm/uaccess.h>
-#include "usb-serial.h"
/*
* Version Information
@@ -373,6 +373,8 @@ static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
dbg("%s", __FUNCTION__);
+ port->write_urb_busy = 0;
+
if (urb->status)
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 2cf1fed3de43..1738b0b6a376 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -57,7 +57,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
/*
* Version Information
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index d7c58f1bc960..015ad6cc1bbb 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -107,7 +107,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "keyspan.h"
static int debug;
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 03ab3c0f3cce..49b8dc039d1f 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -78,6 +78,7 @@
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
static int debug;
@@ -107,8 +108,6 @@ struct ezusb_hex_record {
#include "xircom_pgs_fw.h"
#endif
-#include "usb-serial.h"
-
/*
* Version Information
*/
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index b45ff3e7ab40..2a2f3e2da055 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -55,7 +55,7 @@
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "kl5kusb105.h"
static int debug;
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 457733374772..d50dce034958 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -46,8 +46,8 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
#include <linux/ioctl.h>
-#include "usb-serial.h"
#include "kobil_sct.h"
static int debug;
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index ca05d3275f3e..f4d4305c2c02 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -75,7 +75,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "mct_u232.h"
/*
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 7f544081032e..ac3f8b5d2c49 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -14,7 +14,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static int debug;
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index cfb711a21a45..e49f40913c27 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -46,7 +46,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
static int debug;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 78ad4b3126a6..f0530c1d7b7a 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -35,6 +35,7 @@
2006-06-01 v0.6.2 add backwards-compatibility stuff
2006-06-01 v0.6.3 add Novatel Wireless
2006-06-01 v0.7 Option => GSM
+ 2006-06-01 v0.7.1 add COBRA2
Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
@@ -53,7 +54,7 @@
device features.
*/
-#define DRIVER_VERSION "v0.7.0"
+#define DRIVER_VERSION "v0.7.1"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "USB Driver for GSM modems"
@@ -64,7 +65,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
/* Function prototypes */
static int option_open(struct usb_serial_port *port, struct file *filp);
@@ -102,6 +103,7 @@ static int option_send_setup(struct usb_serial_port *port);
#define OPTION_PRODUCT_FUSION 0x6000
#define OPTION_PRODUCT_FUSION2 0x6300
#define OPTION_PRODUCT_COBRA 0x6500
+#define OPTION_PRODUCT_COBRA2 0x6600
#define HUAWEI_PRODUCT_E600 0x1001
#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802
@@ -112,6 +114,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
@@ -124,6 +127,7 @@ static struct usb_device_id option_ids1[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index de93a2b909e7..259db31b65c1 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -27,7 +27,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "pl2303.h"
/*
@@ -52,6 +52,7 @@ struct pl2303_buf {
static struct usb_device_id id_table [] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
@@ -79,6 +80,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
{ USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) },
+ { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 7f29e81d3e35..d9c1e6e0b4b3 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -10,6 +10,7 @@
#define PL2303_VENDOR_ID 0x067b
#define PL2303_PRODUCT_ID 0x2303
#define PL2303_PRODUCT_ID_RSAQ2 0x04bb
+#define PL2303_PRODUCT_ID_DCU11 0x1234
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0
#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2
@@ -84,3 +85,7 @@
/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */
#define OTI_VENDOR_ID 0x0ea0
#define OTI_PRODUCT_ID 0x6858
+
+/* DATAPILOT Universal-2 Phone Cable */
+#define DATAPILOT_U2_VENDOR_ID 0x0731
+#define DATAPILOT_U2_PRODUCT_ID 0x2003
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 897d8447252b..789771ecdb11 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -71,7 +71,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#ifndef CONFIG_USB_SAFE_PADDED
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
new file mode 100644
index 000000000000..d29638daa987
--- /dev/null
+++ b/drivers/usb/serial/sierra.c
@@ -0,0 +1,75 @@
+/*
+ * Sierra Wireless CDMA Wireless Serial USB driver
+ *
+ * Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com>
+ * Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
+ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
+ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
+ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
+ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
+ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
+ /* Following devices are supported in the airprime.c driver */
+ /* { USB_DEVICE(0x1199, 0x0112) }, */ /* Sierra Wireless AirCard 580 */
+ /* { USB_DEVICE(0x0F3D, 0x0112) }, */ /* AirPrime/Sierra PC 5220 */
+ { }
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver sierra_driver = {
+ .name = "sierra_wireless",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+};
+
+static struct usb_serial_driver sierra_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "Sierra_Wireless",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 3,
+};
+
+static int __init sierra_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&sierra_device);
+ if (retval)
+ return retval;
+ retval = usb_register(&sierra_driver);
+ if (retval)
+ usb_serial_deregister(&sierra_device);
+ return retval;
+}
+
+static void __exit sierra_exit(void)
+{
+ usb_deregister(&sierra_driver);
+ usb_serial_deregister(&sierra_device);
+}
+
+module_init(sierra_init);
+module_exit(sierra_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a9afff31a921..ac9b8ee52d44 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -83,8 +83,8 @@
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <linux/usb.h>
+#include <linux/usb/serial.h>
-#include "usb-serial.h"
#include "ti_usb_3410_5052.h"
#include "ti_fw_3410.h" /* firmware image for 3410 */
#include "ti_fw_5052.h" /* firmware image for 5052 */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index b59a0536ea5c..12c1694d322e 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -31,7 +31,7 @@
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "pl2303.h"
/*
@@ -40,6 +40,8 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
+static void port_free(struct usb_serial_port *port);
+
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
.name = "usbserial",
@@ -146,23 +148,10 @@ static void destroy_serial(struct kref *kref)
port = serial->port[i];
if (!port)
continue;
- usb_kill_urb(port->read_urb);
- usb_free_urb(port->read_urb);
- usb_kill_urb(port->write_urb);
- usb_free_urb(port->write_urb);
- usb_kill_urb(port->interrupt_in_urb);
- usb_free_urb(port->interrupt_in_urb);
- usb_kill_urb(port->interrupt_out_urb);
- usb_free_urb(port->interrupt_out_urb);
- kfree(port->bulk_in_buffer);
- kfree(port->bulk_out_buffer);
- kfree(port->interrupt_in_buffer);
- kfree(port->interrupt_out_buffer);
+ port_free(port);
}
}
- flush_scheduled_work(); /* port->work */
-
usb_put_dev(serial->dev);
/* free up any memory that we allocated */
@@ -564,6 +553,11 @@ static void port_release(struct device *dev)
struct usb_serial_port *port = to_usb_serial_port(dev);
dbg ("%s - %s", __FUNCTION__, dev->bus_id);
+ port_free(port);
+}
+
+static void port_free(struct usb_serial_port *port)
+{
usb_kill_urb(port->read_urb);
usb_free_urb(port->read_urb);
usb_kill_urb(port->write_urb);
@@ -576,6 +570,7 @@ static void port_release(struct device *dev)
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
+ flush_scheduled_work(); /* port->work */
kfree(port);
}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
deleted file mode 100644
index 0f2802a60194..000000000000
--- a/drivers/usb/serial/usb-serial.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * USB Serial Converter driver
- *
- * Copyright (C) 1999 - 2005
- * Greg Kroah-Hartman (greg@kroah.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- */
-
-
-#ifndef __LINUX_USB_SERIAL_H
-#define __LINUX_USB_SERIAL_H
-
-#include <linux/kref.h>
-#include <linux/mutex.h>
-
-#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
-#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
-
-#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */
-
-/* parity check flag */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-/**
- * usb_serial_port: structure for the specific ports of a device.
- * @serial: pointer back to the struct usb_serial owner of this port.
- * @tty: pointer to the corresponding tty for this port.
- * @lock: spinlock to grab when updating portions of this structure.
- * @mutex: mutex used to synchronize serial_open() and serial_close()
- * access for this port.
- * @number: the number of the port (the minor number).
- * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
- * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
- * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe
- * for this port.
- * @interrupt_out_buffer: pointer to the interrupt out buffer for this port.
- * @interrupt_out_size: the size of the interrupt_out_buffer, in bytes.
- * @interrupt_out_urb: pointer to the interrupt out struct urb for this port.
- * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe
- * for this port.
- * @bulk_in_buffer: pointer to the bulk in buffer for this port.
- * @read_urb: pointer to the bulk in struct urb for this port.
- * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this
- * port.
- * @bulk_out_buffer: pointer to the bulk out buffer for this port.
- * @bulk_out_size: the size of the bulk_out_buffer, in bytes.
- * @write_urb: pointer to the bulk out struct urb for this port.
- * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
- * port.
- * @write_wait: a wait_queue_head_t used by the port.
- * @work: work queue entry for the line discipline waking up.
- * @open_count: number of times this port has been opened.
- *
- * This structure is used by the usb-serial core and drivers for the specific
- * ports of a device.
- */
-struct usb_serial_port {
- struct usb_serial * serial;
- struct tty_struct * tty;
- spinlock_t lock;
- struct mutex mutex;
- unsigned char number;
-
- unsigned char * interrupt_in_buffer;
- struct urb * interrupt_in_urb;
- __u8 interrupt_in_endpointAddress;
-
- unsigned char * interrupt_out_buffer;
- int interrupt_out_size;
- struct urb * interrupt_out_urb;
- __u8 interrupt_out_endpointAddress;
-
- unsigned char * bulk_in_buffer;
- int bulk_in_size;
- struct urb * read_urb;
- __u8 bulk_in_endpointAddress;
-
- unsigned char * bulk_out_buffer;
- int bulk_out_size;
- struct urb * write_urb;
- int write_urb_busy;
- __u8 bulk_out_endpointAddress;
-
- wait_queue_head_t write_wait;
- struct work_struct work;
- int open_count;
- struct device dev;
-};
-#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
-
-/* get and set the port private data pointer helper functions */
-static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
-{
- return dev_get_drvdata(&port->dev);
-}
-
-static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
-{
- dev_set_drvdata(&port->dev, data);
-}
-
-/**
- * usb_serial - structure used by the usb-serial core for a device
- * @dev: pointer to the struct usb_device for this device
- * @type: pointer to the struct usb_serial_driver for this device
- * @interface: pointer to the struct usb_interface for this device
- * @minor: the starting minor number for this device
- * @num_ports: the number of ports this device has
- * @num_interrupt_in: number of interrupt in endpoints we have
- * @num_interrupt_out: number of interrupt out endpoints we have
- * @num_bulk_in: number of bulk in endpoints we have
- * @num_bulk_out: number of bulk out endpoints we have
- * @port: array of struct usb_serial_port structures for the different ports.
- * @private: place to put any driver specific information that is needed. The
- * usb-serial driver is required to manage this data, the usb-serial core
- * will not touch this. Use usb_get_serial_data() and
- * usb_set_serial_data() to access this.
- */
-struct usb_serial {
- struct usb_device * dev;
- struct usb_serial_driver * type;
- struct usb_interface * interface;
- unsigned char minor;
- unsigned char num_ports;
- unsigned char num_port_pointers;
- char num_interrupt_in;
- char num_interrupt_out;
- char num_bulk_in;
- char num_bulk_out;
- struct usb_serial_port * port[MAX_NUM_PORTS];
- struct kref kref;
- void * private;
-};
-#define to_usb_serial(d) container_of(d, struct usb_serial, kref)
-
-#define NUM_DONT_CARE (-1)
-
-/* get and set the serial private data pointer helper functions */
-static inline void *usb_get_serial_data (struct usb_serial *serial)
-{
- return serial->private;
-}
-
-static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
-{
- serial->private = data;
-}
-
-/**
- * usb_serial_driver - describes a usb serial driver
- * @description: pointer to a string that describes this driver. This string used
- * in the syslog messages when a device is inserted or removed.
- * @id_table: pointer to a list of usb_device_id structures that define all
- * of the devices this structure can support.
- * @num_interrupt_in: the number of interrupt in endpoints this device will
- * have.
- * @num_interrupt_out: the number of interrupt out endpoints this device will
- * have.
- * @num_bulk_in: the number of bulk in endpoints this device will have.
- * @num_bulk_out: the number of bulk out endpoints this device will have.
- * @num_ports: the number of different ports this device will have.
- * @calc_num_ports: pointer to a function to determine how many ports this
- * device has dynamically. It will be called after the probe()
- * callback is called, but before attach()
- * @probe: pointer to the driver's probe function.
- * This will be called when the device is inserted into the system,
- * but before the device has been fully initialized by the usb_serial
- * subsystem. Use this function to download any firmware to the device,
- * or any other early initialization that might be needed.
- * Return 0 to continue on with the initialization sequence. Anything
- * else will abort it.
- * @attach: pointer to the driver's attach function.
- * This will be called when the struct usb_serial structure is fully set
- * set up. Do any local initialization of the device, or any private
- * memory structure allocation at this point in time.
- * @shutdown: pointer to the driver's shutdown function. This will be
- * called when the device is removed from the system.
- *
- * This structure is defines a USB Serial driver. It provides all of
- * the information that the USB serial core code needs. If the function
- * pointers are defined, then the USB serial core code will call them when
- * the corresponding tty port functions are called. If they are not
- * called, the generic serial function will be used instead.
- *
- * The driver.owner field should be set to the module owner of this driver.
- * The driver.name field should be set to the name of this driver (remember
- * it will show up in sysfs, so it needs to be short and to the point.
- * Useing the module name is a good idea.)
- */
-struct usb_serial_driver {
- const char *description;
- const struct usb_device_id *id_table;
- char num_interrupt_in;
- char num_interrupt_out;
- char num_bulk_in;
- char num_bulk_out;
- char num_ports;
-
- struct list_head driver_list;
- struct device_driver driver;
-
- int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
- int (*attach) (struct usb_serial *serial);
- int (*calc_num_ports) (struct usb_serial *serial);
-
- void (*shutdown) (struct usb_serial *serial);
-
- int (*port_probe) (struct usb_serial_port *port);
- int (*port_remove) (struct usb_serial_port *port);
-
- /* serial function calls */
- int (*open) (struct usb_serial_port *port, struct file * filp);
- void (*close) (struct usb_serial_port *port, struct file * filp);
- int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count);
- int (*write_room) (struct usb_serial_port *port);
- int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
- void (*set_termios) (struct usb_serial_port *port, struct termios * old);
- void (*break_ctl) (struct usb_serial_port *port, int break_state);
- int (*chars_in_buffer) (struct usb_serial_port *port);
- void (*throttle) (struct usb_serial_port *port);
- void (*unthrottle) (struct usb_serial_port *port);
- int (*tiocmget) (struct usb_serial_port *port, struct file *file);
- int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-
- void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
- void (*write_int_callback)(struct urb *urb, struct pt_regs *regs);
- void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
- void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
-};
-#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
-
-extern int usb_serial_register(struct usb_serial_driver *driver);
-extern void usb_serial_deregister(struct usb_serial_driver *driver);
-extern void usb_serial_port_softint(struct usb_serial_port *port);
-
-extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
-extern void usb_serial_disconnect(struct usb_interface *iface);
-
-extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
-extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
-
-/* USB Serial console functions */
-#ifdef CONFIG_USB_SERIAL_CONSOLE
-extern void usb_serial_console_init (int debug, int minor);
-extern void usb_serial_console_exit (void);
-extern void usb_serial_console_disconnect(struct usb_serial *serial);
-#else
-static inline void usb_serial_console_init (int debug, int minor) { }
-static inline void usb_serial_console_exit (void) { }
-static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
-#endif
-
-/* Functions needed by other parts of the usbserial core */
-extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
-extern void usb_serial_put(struct usb_serial *serial);
-extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
-extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
-extern int usb_serial_generic_write_room (struct usb_serial_port *port);
-extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
-extern void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-extern void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-extern void usb_serial_generic_shutdown (struct usb_serial *serial);
-extern int usb_serial_generic_register (int debug);
-extern void usb_serial_generic_deregister (void);
-
-extern int usb_serial_bus_register (struct usb_serial_driver *device);
-extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
-
-extern struct usb_serial_driver usb_serial_generic_device;
-extern struct bus_type usb_serial_bus_type;
-extern struct tty_driver *usb_serial_tty_driver;
-
-static inline void usb_serial_debug_data(int debug,
- struct device *dev,
- const char *function, int size,
- const unsigned char *data)
-{
- int i;
-
- if (debug) {
- dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", function, size);
- for (i = 0; i < size; ++i)
- printk ("%.2x ", data[i]);
- printk ("\n");
- }
-}
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
-
-
-
-#endif /* ifdef __LINUX_USB_SERIAL_H */
-
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 95a2936e902e..88949f7884ca 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -25,7 +25,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "visor.h"
/*
@@ -302,7 +302,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
priv->bytes_in = 0;
priv->bytes_out = 0;
- priv->outstanding_urbs = 0;
priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -435,13 +434,25 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
static int visor_write_room (struct usb_serial_port *port)
{
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
dbg("%s - port %d", __FUNCTION__, port->number);
/*
* We really can take anything the user throws at us
* but let's pick a nice big number to tell the tty
- * layer that we have lots of free space
+ * layer that we have lots of free space, unless we don't.
*/
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ dbg("%s - write limit hit\n", __FUNCTION__);
+ return 0;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
return 2048;
}
@@ -758,15 +769,22 @@ static int visor_calc_num_ports (struct usb_serial *serial)
static int generic_startup(struct usb_serial *serial)
{
+ struct usb_serial_port **ports = serial->port;
struct visor_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
priv = kzalloc (sizeof(*priv), GFP_KERNEL);
- if (!priv)
+ if (!priv) {
+ while (i-- != 0) {
+ priv = usb_get_serial_port_data(ports[i]);
+ usb_set_serial_port_data(ports[i], NULL);
+ kfree(priv);
+ }
return -ENOMEM;
+ }
spin_lock_init(&priv->lock);
- usb_set_serial_port_data(serial->port[i], priv);
+ usb_set_serial_port_data(ports[i], priv);
}
return 0;
}
@@ -876,7 +894,18 @@ static int clie_5_attach (struct usb_serial *serial)
static void visor_shutdown (struct usb_serial *serial)
{
+ struct visor_private *priv;
+ int i;
+
dbg("%s", __FUNCTION__);
+
+ for (i = 0; i < serial->num_ports; i++) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+ if (priv) {
+ usb_set_serial_port_data(serial->port[i], NULL);
+ kfree(priv);
+ }
+ }
}
static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 540438c3f381..6e6c7934be32 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -79,7 +79,7 @@
#include <linux/usb.h>
#include <linux/serial_reg.h>
#include <linux/serial.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
#include "whiteheat_fw.h" /* firmware for the ConnectTech WhiteHEAT device */
#include "whiteheat.h" /* WhiteHEAT specific commands */
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 5715291ba540..a4b7df9ff8c1 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -112,13 +112,11 @@ static int slave_configure(struct scsi_device *sdev)
if (sdev->scsi_level < SCSI_2)
sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
- /* According to the technical support people at Genesys Logic,
- * devices using their chips have problems transferring more than
- * 32 KB at a time. In practice people have found that 64 KB
- * works okay and that's what Windows does. But we'll be
- * conservative; people can always use the sysfs interface to
- * increase max_sectors. */
- if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS &&
+ /* Many devices have trouble transfering more than 32KB at a time,
+ * while others have trouble with more than 64K. At this time we
+ * are limiting both to 32K (64 sectores).
+ */
+ if ((us->flags & US_FL_MAX_SECTORS_64) &&
sdev->request_queue->max_sectors > 64)
blk_queue_max_sectors(sdev->request_queue, 64);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index eb7188b3565c..d6acc92a4ae3 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -180,7 +180,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
if (timeleft <= 0) {
US_DEBUGP("%s -- cancelling URB\n",
timeleft == 0 ? "Timeout" : "Signal");
- usb_unlink_urb(us->current_urb);
+ usb_kill_urb(us->current_urb);
}
/* return the URB status */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c7e84e653df9..a5ca449f6e64 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -112,6 +112,19 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
+UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100,
+ "Samsung Info. Systems America, Inc.",
+ "MP3 Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Orgad Shaneh <orgads@gmail.com> */
+UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100,
+ "Samsung", "MP3 Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* Reported by Christian Leber <christian@leber.de> */
UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100,
"TrekStor",
@@ -132,6 +145,14 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
+ * Einar Th. Einarsson <einarthered@gmail.com> */
+UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100,
+ "Nokia",
+ "N91",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+
/* Reported by Jiri Slaby <jirislaby@gmail.com> and
* Rene C. Castberg <Rene@Castberg.org> */
UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100,
@@ -140,6 +161,13 @@ UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+/* Reported by Matthew Bloch <matthew@bytemark.co.uk> */
+UNUSUAL_DEV( 0x0421, 0x044e, 0x0100, 0x0100,
+ "Nokia",
+ "E61",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+
/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
"SMSC",
@@ -473,10 +501,11 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
US_SC_SCSI, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
-/* This entry is needed because the device reports Sub=ff */
-UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0600,
+/* Submitted by Lars Jacob <jacob.lars@googlemail.com>
+ * This entry is needed because the device reports Sub=ff */
+UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610,
"Sony",
- "DSC-T1/T5",
+ "DSC-T1/T5/H5",
US_SC_8070, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
@@ -708,18 +737,22 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113,
* They were originally reported by Alexander Oltu
* <alexander@all-2.com> and Peter Marks <peter.marks@turner.com>
* respectively.
+ *
+ * US_FL_GO_SLOW and US_FL_MAX_SECTORS_64 added by Phil Dibowitz
+ * <phil@ipom.com> as these flags were made and hard-coded
+ * special-cases were pulled from scsiglue.c.
*/
UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff,
"Genesys Logic",
"USB to IDE Optical",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_GO_SLOW ),
+ US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff,
"Genesys Logic",
"USB to IDE Disk",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_GO_SLOW ),
+ US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
/* Reported by Hanno Boeck <hanno@gmx.de>
* Taken from the Lycoris Kernel */
@@ -1196,6 +1229,14 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Benjamin Schiller <sbenni@gmx.de>
+ * It is also sold by Easylite as DJ 20 */
+UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103,
+ "Typhoon",
+ "My DJ 1820",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
+
/* Reported by Michael Stattmann <michael@stattmann.com> */
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
"Sony Ericsson",
@@ -1227,6 +1268,15 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
+ * and Renato Perini <rperini@email.it>
+ */
+UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001,
+ "Motorola",
+ "RAZR V3x",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+
/* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
"MPIO",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 1185acac4b21..5ee19be52f65 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -55,6 +55,7 @@
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
+#include <linux/utsrelease.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -373,8 +374,12 @@ static int usb_stor_control_thread(void * __us)
/* lock access to the state */
scsi_lock(host);
+ /* did the command already complete because of a disconnect? */
+ if (!us->srb)
+ ; /* nothing to do */
+
/* indicate that the command is done */
- if (us->srb->result != DID_ABORT << 16) {
+ else if (us->srb->result != DID_ABORT << 16) {
US_DEBUGP("scsi cmd done, result=0x%x\n",
us->srb->result);
us->srb->scsi_done(us->srb);
@@ -524,7 +529,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x,%04x S %02x P %02x)"
- " has %s in unusual_devs.h\n"
+ " has %s in unusual_devs.h (kernel"
+ " %s)\n"
" Please send a copy of this message to "
"<linux-usb-devel@lists.sourceforge.net>\n",
le16_to_cpu(ddesc->idVendor),
@@ -532,7 +538,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
le16_to_cpu(ddesc->bcdDevice),
idesc->bInterfaceSubClass,
idesc->bInterfaceProtocol,
- msgs[msg]);
+ msgs[msg],
+ UTS_RELEASE);
}
}
@@ -836,32 +843,34 @@ static void dissociate_dev(struct us_data *us)
* the host */
static void quiesce_and_remove_host(struct us_data *us)
{
+ struct Scsi_Host *host = us_to_host(us);
+
/* Prevent new USB transfers, stop the current command, and
* interrupt a SCSI-scan or device-reset delay */
+ scsi_lock(host);
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
+ scsi_unlock(host);
usb_stor_stop_transport(us);
wake_up(&us->delay_wait);
/* It doesn't matter if the SCSI-scanning thread is still running.
* The thread will exit when it sees the DISCONNECTING flag. */
- /* Wait for the current command to finish, then remove the host */
- mutex_lock(&us->dev_mutex);
- mutex_unlock(&us->dev_mutex);
-
/* queuecommand won't accept any new commands and the control
* thread won't execute a previously-queued command. If there
* is such a command pending, complete it with an error. */
+ mutex_lock(&us->dev_mutex);
if (us->srb) {
us->srb->result = DID_NO_CONNECT << 16;
- scsi_lock(us_to_host(us));
+ scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
- scsi_unlock(us_to_host(us));
+ scsi_unlock(host);
}
+ mutex_unlock(&us->dev_mutex);
/* Now we own no commands so it's safe to remove the SCSI host */
- scsi_remove_host(us_to_host(us));
+ scsi_remove_host(host);
}
/* Second stage of disconnect processing: deallocate all resources */
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 5284abe1b5eb..21f3ddbc9080 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -176,8 +176,4 @@ extern void fill_inquiry_response(struct us_data *us,
#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
#define scsi_lock(host) spin_lock_irq(host->host_lock)
-
-/* Vendor ID list for devices that require special handling */
-#define USB_VENDOR_ID_GENESYS 0x05e3 /* Genesys Logic */
-
#endif
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 78488bb41aeb..0dda73da8628 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -32,7 +32,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c
index e714e8449c1d..afd146f5f683 100644
--- a/drivers/video/S3triofb.c
+++ b/drivers/video/S3triofb.c
@@ -28,7 +28,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index f9bc9f777e75..f1ba54f4fc39 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -45,7 +45,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index fd95c2dbd4f7..70dd8115a4d8 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -39,7 +39,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index eaeaf4d1a094..1fd22f460b0f 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -34,7 +34,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index e69ab65f7843..5831893bf7a0 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -53,7 +53,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 72c589109471..c64a717e2d4b 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -52,7 +52,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
@@ -456,6 +455,7 @@ static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par);
static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
static void wait_for_idle(struct aty128fb_par *par);
static u32 depth_to_dst(u32 depth);
+static void aty128_bl_set_power(struct fb_info *info, int power);
#define BIOS_IN8(v) (readb(bios + (v)))
#define BIOS_IN16(v) (readb(bios + (v)) | \
@@ -1258,25 +1258,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
reg &= ~LVDS_DISPLAY_DIS;
aty_st_le32(LVDS_GEN_CNTL, reg);
#ifdef CONFIG_FB_ATY128_BACKLIGHT
- mutex_lock(&info->bl_mutex);
- if (info->bl_dev) {
- down(&info->bl_dev->sem);
- info->bl_dev->props->update_status(info->bl_dev);
- up(&info->bl_dev->sem);
- }
- mutex_unlock(&info->bl_mutex);
+ aty128_bl_set_power(info, FB_BLANK_UNBLANK);
#endif
} else {
#ifdef CONFIG_FB_ATY128_BACKLIGHT
- mutex_lock(&info->bl_mutex);
- if (info->bl_dev) {
- down(&info->bl_dev->sem);
- info->bl_dev->props->brightness = 0;
- info->bl_dev->props->power = FB_BLANK_POWERDOWN;
- info->bl_dev->props->update_status(info->bl_dev);
- up(&info->bl_dev->sem);
- }
- mutex_unlock(&info->bl_mutex);
+ aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
#endif
reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_DISPLAY_DIS;
@@ -1703,6 +1689,7 @@ static int __devinit aty128fb_setup(char *options)
static struct backlight_properties aty128_bl_data;
+/* Call with fb_info->bl_mutex held */
static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
int level)
{
@@ -1710,10 +1697,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
int atylevel;
/* Get and convert the value */
- mutex_lock(&info->bl_mutex);
atylevel = MAX_LEVEL -
(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
- mutex_unlock(&info->bl_mutex);
if (atylevel < 0)
atylevel = 0;
@@ -1731,7 +1716,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
/* That one prevents proper CRT output with LCD off */
#undef BACKLIGHT_DAC_OFF
-static int aty128_bl_update_status(struct backlight_device *bd)
+/* Call with fb_info->bl_mutex held */
+static int __aty128_bl_update_status(struct backlight_device *bd)
{
struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
@@ -1784,6 +1770,19 @@ static int aty128_bl_update_status(struct backlight_device *bd)
return 0;
}
+static int aty128_bl_update_status(struct backlight_device *bd)
+{
+ struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int ret;
+
+ mutex_lock(&info->bl_mutex);
+ ret = __aty128_bl_update_status(bd);
+ mutex_unlock(&info->bl_mutex);
+
+ return ret;
+}
+
static int aty128_bl_get_brightness(struct backlight_device *bd)
{
return bd->props->brightness;
@@ -1796,6 +1795,16 @@ static struct backlight_properties aty128_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
+static void aty128_bl_set_power(struct fb_info *info, int power)
+{
+ mutex_lock(&info->bl_mutex);
+ up(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __aty128_bl_update_status(info->bl_dev);
+ down(&info->bl_dev->sem);
+ mutex_unlock(&info->bl_mutex);
+}
+
static void aty128_bl_init(struct aty128fb_par *par)
{
struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2198,12 +2207,8 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
return 0;
#ifdef CONFIG_FB_ATY128_BACKLIGHT
- if (machine_is(powermac) && blank) {
- down(&fb->bl_dev->sem);
- fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
- fb->bl_dev->props->update_status(fb->bl_dev);
- up(&fb->bl_dev->sem);
- }
+ if (machine_is(powermac) && blank)
+ aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
#endif
if (blank & FB_BLANK_VSYNC_SUSPEND)
@@ -2219,14 +2224,12 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
aty128_set_crt_enable(par, par->crt_on && !blank);
aty128_set_lcd_enable(par, par->lcd_on && !blank);
}
+
#ifdef CONFIG_FB_ATY128_BACKLIGHT
- if (machine_is(powermac) && !blank) {
- down(&fb->bl_dev->sem);
- fb->bl_dev->props->power = FB_BLANK_UNBLANK;
- fb->bl_dev->props->update_status(fb->bl_dev);
- up(&fb->bl_dev->sem);
- }
+ if (machine_is(powermac) && !blank)
+ aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
#endif
+
return 0;
}
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 0c9706746d79..1507d19f481f 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2129,15 +2129,14 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
static struct backlight_properties aty_bl_data;
+/* Call with fb_info->bl_mutex held */
static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
{
struct fb_info *info = pci_get_drvdata(par->pdev);
int atylevel;
/* Get and convert the value */
- mutex_lock(&info->bl_mutex);
atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
- mutex_unlock(&info->bl_mutex);
if (atylevel < 0)
atylevel = 0;
@@ -2147,7 +2146,8 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
return atylevel;
}
-static int aty_bl_update_status(struct backlight_device *bd)
+/* Call with fb_info->bl_mutex held */
+static int __aty_bl_update_status(struct backlight_device *bd)
{
struct atyfb_par *par = class_get_devdata(&bd->class_dev);
unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
@@ -2172,6 +2172,19 @@ static int aty_bl_update_status(struct backlight_device *bd)
return 0;
}
+static int aty_bl_update_status(struct backlight_device *bd)
+{
+ struct atyfb_par *par = class_get_devdata(&bd->class_dev);
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int ret;
+
+ mutex_lock(&info->bl_mutex);
+ ret = __aty_bl_update_status(bd);
+ mutex_unlock(&info->bl_mutex);
+
+ return ret;
+}
+
static int aty_bl_get_brightness(struct backlight_device *bd)
{
return bd->props->brightness;
@@ -2184,6 +2197,16 @@ static struct backlight_properties aty_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
+static void aty_bl_set_power(struct fb_info *info, int power)
+{
+ mutex_lock(&info->bl_mutex);
+ up(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __aty_bl_update_status(info->bl_dev);
+ down(&info->bl_dev->sem);
+ mutex_unlock(&info->bl_mutex);
+}
+
static void aty_bl_init(struct atyfb_par *par)
{
struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2790,16 +2813,8 @@ static int atyfb_blank(int blank, struct fb_info *info)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac) && blank > FB_BLANK_NORMAL) {
- mutex_lock(&info->bl_mutex);
- if (info->bl_dev) {
- down(&info->bl_dev->sem);
- info->bl_dev->props->power = FB_BLANK_POWERDOWN;
- info->bl_dev->props->update_status(info->bl_dev);
- up(&info->bl_dev->sem);
- }
- mutex_unlock(&info->bl_mutex);
- }
+ if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
+ aty_bl_set_power(info, FB_BLANK_POWERDOWN);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2830,16 +2845,8 @@ static int atyfb_blank(int blank, struct fb_info *info)
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) {
- mutex_lock(&info->bl_mutex);
- if (info->bl_dev) {
- down(&info->bl_dev->sem);
- info->bl_dev->props->power = FB_BLANK_UNBLANK;
- info->bl_dev->props->update_status(info->bl_dev);
- up(&info->bl_dev->sem);
- }
- mutex_unlock(&info->bl_mutex);
- }
+ if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
+ aty_bl_set_power(info, FB_BLANK_UNBLANK);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 51b78f8de949..8d85fc58142e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -58,7 +58,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/time.h>
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 0e465c80ef24..73cb426bf2d7 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -19,7 +19,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
@@ -150,12 +149,11 @@ static int chipsfb_blank(int blank, struct fb_info *info)
mutex_lock(&pmac_backlight_mutex);
if (pmac_backlight) {
- down(&pmac_backlight->sem);
-
/* used to disable backlight only for blank > 1, but it seems
* useful at blank = 1 too (saves battery, extends backlight
* life)
*/
+ down(&pmac_backlight->sem);
if (blank)
pmac_backlight->props->power = FB_BLANK_POWERDOWN;
else
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 7355da09c721..daf43f535a0b 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -41,7 +41,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 878707a04398..d9315d99445f 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -7,9 +7,9 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
-#include <linux/tty.h>
#include <linux/console.h>
#include <linux/vt_kern.h>
+#include <linux/screen_info.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 94e9f7069bef..390439b3d899 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -64,7 +64,6 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/delay.h> /* MSch: for IRQ probe */
-#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/kd.h>
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index c89f90edf8ac..52ed12b12acc 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -31,7 +31,6 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/kd.h>
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 03041311711b..7fa1afeae8dc 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -12,7 +12,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/tty.h>
#include <linux/kd.h>
#include <linux/selection.h>
#include <linux/console.h>
diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c
index 5cd5e114d1e6..b78eac63459f 100644
--- a/drivers/video/console/promcon.c
+++ b/drivers/video/console/promcon.c
@@ -10,7 +10,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/console.h>
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 3957fc7523e2..557c563e4aed 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/string.h>
-#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/slab.h>
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 45c4f227e56e..45586aaabd1e 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -37,7 +37,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/tty.h>
#include <linux/console.h>
#include <linux/errno.h>
#include <linux/vt_kern.h>
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 05735ff4e9c5..0a2c10a1abf8 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -38,7 +38,6 @@
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/kd.h>
@@ -48,6 +47,7 @@
#include <linux/spinlock.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/screen_info.h>
#include <linux/smp_lock.h>
#include <video/vga.h>
#include <asm/io.h>
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index acdd6a103dbb..8cc6c0e2d27a 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -36,7 +36,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 2e2924957d8f..aae6d9c26e88 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -41,7 +41,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
index a3e189f90a7d..c40e72dafb0e 100644
--- a/drivers/video/cyberfb.c
+++ b/drivers/video/cyberfb.c
@@ -81,7 +81,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/zorro.h>
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 5abd3cb00671..b083ea7e9c69 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -2,7 +2,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index f0a621ecc288..737257d278f0 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -48,7 +48,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 1f98392a43b3..e8b135f3d80d 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -13,7 +13,6 @@
#include <linux/string.h>
#include <linux/module.h>
-#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/slab.h>
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 33034f81114d..4fc9df426c1a 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -23,7 +23,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
-#include <linux/tty.h>
+#include <linux/vt.h>
#include <linux/init.h>
#include <linux/linux_logo.h>
#include <linux/proc_fs.h>
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 3ccfff715a51..de93139ccbb5 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -26,7 +26,6 @@
* for more details.
*
*/
-#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index 605d1a132020..1b981b635675 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -21,7 +21,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 4d3a8871d3d1..bcf9cea54d8b 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -15,7 +15,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 5ef12a3dfa50..0d3643fc6293 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -25,7 +25,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 4e39035cf335..fb9e67228543 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -36,7 +36,6 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 01864767450d..4cc6b454265e 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -17,7 +17,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index abd920a663a0..91cf3b577d15 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -11,7 +11,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index fbe8a2c4b04c..a6ca02f2156a 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -33,7 +33,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/init.h>
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 8a0c2d3d3805..67f384f86758 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -33,7 +33,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
index cdbae173d69a..ff233b84dec4 100644
--- a/drivers/video/imacfb.c
+++ b/drivers/video/imacfb.c
@@ -15,9 +15,9 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/screen_info.h>
#include <linux/slab.h>
#include <linux/string.h>
-#include <linux/tty.h>
#include <asm/io.h>
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 5f393d985b11..5715b8ad0ddc 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -21,7 +21,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 3f39d84015f1..06af89d44a0d 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -113,7 +113,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
@@ -122,6 +121,7 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
+#include <linux/screen_info.h>
#include <asm/io.h>
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 3b78a57924f0..2a9322f9cfdc 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -24,7 +24,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 2fdbe9b2b04b..f0d614a80f1f 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -16,7 +16,6 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/string.h>
-#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/ioctl.h>
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index e6cbd9de944a..80a043807161 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -24,7 +24,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/nubus.h>
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index b95779b57c06..9c25c2f7966b 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -30,7 +30,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index f85421bf7cb5..38c8d38de4fd 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -29,7 +29,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index ff5454601e22..d1267904c280 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -12,7 +12,6 @@
*/
#include <linux/module.h>
-#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/sched.h>
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 773855a311e8..59a6f5fa5ae6 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -59,7 +59,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index 1c1c10c699c5..b45f577094ac 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -26,9 +26,11 @@
*/
#define MIN_LEVEL 0x158
#define MAX_LEVEL 0x534
+#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
static struct backlight_properties nvidia_bl_data;
+/* Call with fb_info->bl_mutex held */
static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
int level)
{
@@ -36,9 +38,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
int nlevel;
/* Get and convert the value */
- mutex_lock(&info->bl_mutex);
- nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
- mutex_unlock(&info->bl_mutex);
+ nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
if (nlevel < 0)
nlevel = 0;
@@ -50,7 +50,8 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
return nlevel;
}
-static int nvidia_bl_update_status(struct backlight_device *bd)
+/* Call with fb_info->bl_mutex held */
+static int __nvidia_bl_update_status(struct backlight_device *bd)
{
struct nvidia_par *par = class_get_devdata(&bd->class_dev);
u32 tmp_pcrt, tmp_pmc, fpcontrol;
@@ -84,6 +85,19 @@ static int nvidia_bl_update_status(struct backlight_device *bd)
return 0;
}
+static int nvidia_bl_update_status(struct backlight_device *bd)
+{
+ struct nvidia_par *par = class_get_devdata(&bd->class_dev);
+ struct fb_info *info = pci_get_drvdata(par->pci_dev);
+ int ret;
+
+ mutex_lock(&info->bl_mutex);
+ ret = __nvidia_bl_update_status(bd);
+ mutex_unlock(&info->bl_mutex);
+
+ return ret;
+}
+
static int nvidia_bl_get_brightness(struct backlight_device *bd)
{
return bd->props->brightness;
@@ -96,6 +110,16 @@ static struct backlight_properties nvidia_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
+void nvidia_bl_set_power(struct fb_info *info, int power)
+{
+ mutex_lock(&info->bl_mutex);
+ up(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __nvidia_bl_update_status(info->bl_dev);
+ down(&info->bl_dev->sem);
+ mutex_unlock(&info->bl_mutex);
+}
+
void nvidia_bl_init(struct nvidia_par *par)
{
struct fb_info *info = pci_get_drvdata(par->pci_dev);
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 6fba656cd56b..861271017655 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -68,9 +68,11 @@ extern u8 byte_rev[256];
#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
extern void nvidia_bl_init(struct nvidia_par *par);
extern void nvidia_bl_exit(struct nvidia_par *par);
+extern void nvidia_bl_set_power(struct fb_info *info, int power);
#else
static inline void nvidia_bl_init(struct nvidia_par *par) {}
static inline void nvidia_bl_exit(struct nvidia_par *par) {}
+static inline void nvidia_bl_set_power(struct fb_info *info, int power) {}
#endif
#endif /* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index b02d6033cc0c..9f2066f0745a 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -14,7 +14,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
@@ -933,16 +932,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
NVWriteSeq(par, 0x01, tmp);
NVWriteCrtc(par, 0x1a, vesa);
-#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
- mutex_lock(&info->bl_mutex);
- if (info->bl_dev) {
- down(&info->bl_dev->sem);
- info->bl_dev->props->power = blank;
- info->bl_dev->props->update_status(info->bl_dev);
- up(&info->bl_dev->sem);
- }
- mutex_unlock(&info->bl_mutex);
-#endif
+ nvidia_bl_set_power(info, blank);
NVTRACE_LEAVE();
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 71ce1fa45cf4..ce5f3031b99b 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -17,7 +17,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 450e802e0aa8..983be3ec2345 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -22,7 +22,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 49a203e1591c..a560a2223825 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -33,7 +33,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 0e0f977b05ee..1d81ef47efd3 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -57,7 +57,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index d92f352211ef..68ca3cc40770 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -29,7 +29,6 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 4a1e0e856920..940ba2be55e9 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -53,7 +53,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index fc91dbf896d2..48536c3e58a4 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -14,7 +14,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
index 5e2c64f622cb..cf41ff177644 100644
--- a/drivers/video/retz3fb.c
+++ b/drivers/video/retz3fb.c
@@ -25,7 +25,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 2788655e6e7d..33dddbae5420 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -34,7 +34,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
@@ -278,9 +277,11 @@ static const struct riva_regs reg_template = {
*/
#define MIN_LEVEL 0x158
#define MAX_LEVEL 0x534
+#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
static struct backlight_properties riva_bl_data;
+/* Call with fb_info->bl_mutex held */
static int riva_bl_get_level_brightness(struct riva_par *par,
int level)
{
@@ -288,9 +289,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
int nlevel;
/* Get and convert the value */
- mutex_lock(&info->bl_mutex);
- nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
- mutex_unlock(&info->bl_mutex);
+ nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
if (nlevel < 0)
nlevel = 0;
@@ -302,7 +301,8 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
return nlevel;
}
-static int riva_bl_update_status(struct backlight_device *bd)
+/* Call with fb_info->bl_mutex held */
+static int __riva_bl_update_status(struct backlight_device *bd)
{
struct riva_par *par = class_get_devdata(&bd->class_dev);
U032 tmp_pcrt, tmp_pmc;
@@ -327,6 +327,19 @@ static int riva_bl_update_status(struct backlight_device *bd)
return 0;
}
+static int riva_bl_update_status(struct backlight_device *bd)
+{
+ struct riva_par *par = class_get_devdata(&bd->class_dev);
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int ret;
+
+ mutex_lock(&info->bl_mutex);
+ ret = __riva_bl_update_status(bd);
+ mutex_unlock(&info->bl_mutex);
+
+ return ret;
+}
+
static int riva_bl_get_brightness(struct backlight_device *bd)
{
return bd->props->brightness;
@@ -339,6 +352,16 @@ static struct backlight_properties riva_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
+static void riva_bl_set_power(struct fb_info *info, int power)
+{
+ mutex_lock(&info->bl_mutex);
+ up(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __riva_bl_update_status(info->bl_dev);
+ down(&info->bl_dev->sem);
+ mutex_unlock(&info->bl_mutex);
+}
+
static void riva_bl_init(struct riva_par *par)
{
struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -419,6 +442,7 @@ static void riva_bl_exit(struct riva_par *par)
#else
static inline void riva_bl_init(struct riva_par *par) {}
static inline void riva_bl_exit(struct riva_par *par) {}
+static inline void riva_bl_set_power(struct fb_info *info, int power) {}
#endif /* CONFIG_FB_RIVA_BACKLIGHT */
/* ------------------------------------------------------------------------- *
@@ -1337,16 +1361,7 @@ static int rivafb_blank(int blank, struct fb_info *info)
SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa);
-#ifdef CONFIG_FB_RIVA_BACKLIGHT
- mutex_lock(&info->bl_mutex);
- if (info->bl_dev) {
- down(&info->bl_dev->sem);
- info->bl_dev->props->power = blank;
- info->bl_dev->props->update_status(info->bl_dev);
- up(&info->bl_dev->sem);
- }
- mutex_unlock(&info->bl_mutex);
-#endif
+ riva_bl_set_power(info, blank);
NVTRACE_LEAVE();
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index f461eb10cc79..ad3bdd6f1ac1 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -76,7 +76,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 4729af477fbf..461e094e7b45 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -46,7 +46,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index b848ca7db7f9..895ebda7d9e3 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -44,7 +44,13 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
#include <linux/tty.h>
+#else
+#include <linux/screen_info.h>
+#endif
+
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/selection.h>
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 67f429e93189..bb96cb65fdaa 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -47,7 +47,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
index e046e20f02b9..f80356dfa8e8 100644
--- a/drivers/video/sun3fb.c
+++ b/drivers/video/sun3fb.c
@@ -30,7 +30,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 239b1496874b..689ce0270b81 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -63,7 +63,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 6c2c78ab9827..94fde625a6c0 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -17,7 +17,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index d904da44e1aa..07389ba01eff 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
-#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 1d76c035050e..47f27924a7d7 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -44,7 +44,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 5718924b677f..2196448396ec 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -13,13 +13,13 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/screen_info.h>
#include <video/vga.h>
#include <asm/io.h>
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index d073ffb6e1f9..a9b99b01bd8e 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -15,7 +15,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 3c404c9bd36c..43d5a6d9c4a6 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -15,13 +15,13 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/screen_info.h>
#include <asm/io.h>
#include <video/vga.h>
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index 5ea2345dab99..64378959dd7b 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -39,7 +39,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/zorro.h>
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index af492cc48db2..d93eb626b2f0 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -218,7 +218,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev)
do {
temp = i2c_smbus_read_byte(&pdev->client);
} while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) &&
- (++retries > DS2482_WAIT_IDLE_TIMEOUT));
+ (++retries < DS2482_WAIT_IDLE_TIMEOUT));
}
if (retries > DS2482_WAIT_IDLE_TIMEOUT)
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
deleted file mode 100644
index 9a76d2ad69c5..000000000000
--- a/drivers/w1/w1_io.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * w1_io.h
- *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __W1_IO_H
-#define __W1_IO_H
-
-#include "w1.h"
-
-u8 w1_triplet(struct w1_master *dev, int bdir);
-void w1_write_8(struct w1_master *, u8);
-int w1_reset_bus(struct w1_master *);
-u8 w1_calc_crc8(u8 *, int);
-void w1_write_block(struct w1_master *, const u8 *, int);
-u8 w1_read_block(struct w1_master *, u8 *, int);
-void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
-int w1_reset_select_slave(struct w1_slave *sl);
-
-#endif /* __W1_IO_H */