summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@r063144.stusta.swh.mhn.de>2006-03-20 18:30:36 +0100
committerAdrian Bunk <bunk@r063144.stusta.swh.mhn.de>2006-03-20 18:30:36 +0100
commit0f76ee451484d02c7405d92e7bceb39b415abb01 (patch)
tree9722f84281f786ba48971dde057f5171a49969e4 /drivers
parent01d206a7c1167639f6ca6dac22140fbdca017558 (diff)
parent7705a8792b0fc82fd7d4dd923724606bbfd9fb20 (diff)
Merge with git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acpi/Kconfig10
-rw-r--r--drivers/acpi/processor_idle.c6
-rw-r--r--drivers/acpi/resources/rscalc.c6
-rw-r--r--drivers/atm/fore200e.c36
-rw-r--r--drivers/base/base.h4
-rw-r--r--drivers/base/bus.c3
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/power/resume.c3
-rw-r--r--drivers/base/power/shutdown.c2
-rw-r--r--drivers/base/power/suspend.c3
-rw-r--r--drivers/base/power/sysfs.c24
-rw-r--r--drivers/base/sys.c3
-rw-r--r--drivers/block/DAC960.c3
-rw-r--r--drivers/block/Kconfig8
-rw-r--r--drivers/block/cciss.c5
-rw-r--r--drivers/block/pktcdvd.c197
-rw-r--r--drivers/bluetooth/bt3c_cs.c17
-rw-r--r--drivers/cdrom/viocd.c2
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/agp/Kconfig55
-rw-r--r--drivers/char/agp/amd64-agp.c6
-rw-r--r--drivers/char/agp/sworks-agp.c4
-rw-r--r--drivers/char/drm/drmP.h10
-rw-r--r--drivers/char/drm/drm_pciids.h1
-rw-r--r--drivers/char/drm/drm_stub.c2
-rw-r--r--drivers/char/drm/drm_sysfs.c131
-rw-r--r--drivers/char/drm/i915_irq.c5
-rw-r--r--drivers/char/drm/r300_cmdbuf.c48
-rw-r--r--drivers/char/drm/r300_reg.h3
-rw-r--r--drivers/char/drm/radeon_drv.h3
-rw-r--r--drivers/char/esp.c22
-rw-r--r--drivers/char/hpet.c22
-rw-r--r--drivers/char/hvc_console.c8
-rw-r--r--drivers/char/hw_random.c2
-rw-r--r--drivers/char/mmtimer.c2
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c24
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c23
-rw-r--r--drivers/char/ser_a2232.c1
-rw-r--r--drivers/char/sx.c22
-rw-r--r--drivers/char/synclink_gt.c2
-rw-r--r--drivers/char/sysrq.c2
-rw-r--r--drivers/char/tipar.c15
-rw-r--r--drivers/char/tpm/tpm_infineon.c48
-rw-r--r--drivers/char/tty_io.c39
-rw-r--r--drivers/char/watchdog/pcwd.c450
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c12
-rw-r--r--drivers/char/watchdog/sbc_epx_c3.c15
-rw-r--r--drivers/cpufreq/cpufreq.c110
-rw-r--r--drivers/crypto/padlock-aes.c8
-rw-r--r--drivers/edac/Kconfig19
-rw-r--r--drivers/edac/edac_mc.c56
-rw-r--r--drivers/edac/i82875p_edac.c2
-rw-r--r--drivers/fc4/fc.c2
-rw-r--r--drivers/firmware/dcdbas.c8
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/f71805f.c908
-rw-r--r--drivers/hwmon/it87.c11
-rw-r--r--drivers/hwmon/lm77.c8
-rw-r--r--drivers/hwmon/vt8231.c8
-rw-r--r--drivers/hwmon/w83781d.c43
-rw-r--r--drivers/hwmon/w83792d.c31
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c2
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-isa.c12
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.c7
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/i2c-core.c15
-rw-r--r--drivers/ide/ide-disk.c6
-rw-r--r--drivers/ide/ide-taskfile.c3
-rw-r--r--drivers/ide/legacy/ide-cs.c1
-rw-r--r--drivers/ide/pci/sgiioc4.c5
-rw-r--r--drivers/ieee1394/sbp2.c126
-rw-r--r--drivers/ieee1394/sbp2.h64
-rw-r--r--drivers/ieee1394/video1394.c2
-rw-r--r--drivers/infiniband/core/mad.c10
-rw-r--r--drivers/infiniband/core/ucm.c13
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c38
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c28
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c6
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/ixp4xx-beeper.c1
-rw-r--r--drivers/input/mouse/logips2pp.c1
-rw-r--r--drivers/input/mouse/psmouse-base.c2
-rw-r--r--drivers/input/mouse/trackpoint.c20
-rw-r--r--drivers/input/mouse/trackpoint.h4
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c147
-rw-r--r--drivers/isdn/hisax/Kconfig2
-rw-r--r--drivers/isdn/hisax/config.c2
-rw-r--r--drivers/isdn/hisax/hfc_pci.c2
-rw-r--r--drivers/isdn/hisax/hfc_usb.c32
-rw-r--r--drivers/isdn/i4l/isdn_tty.c5
-rw-r--r--drivers/macintosh/Kconfig8
-rw-r--r--drivers/macintosh/Makefile5
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/macintosh/windfarm.h3
-rw-r--r--drivers/macintosh/windfarm_core.c129
-rw-r--r--drivers/macintosh/windfarm_cpufreq_clamp.c8
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c32
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c180
-rw-r--r--drivers/macintosh/windfarm_pid.c12
-rw-r--r--drivers/macintosh/windfarm_pid.h1
-rw-r--r--drivers/macintosh/windfarm_pm112.c700
-rw-r--r--drivers/macintosh/windfarm_pm81.c87
-rw-r--r--drivers/macintosh/windfarm_pm91.c95
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c69
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c419
-rw-r--r--drivers/macintosh/windfarm_smu_sensors.c43
-rw-r--r--drivers/md/dm-stripe.c8
-rw-r--r--drivers/md/dm.c8
-rw-r--r--drivers/md/raid1.c13
-rw-r--r--drivers/media/dvb/b2c2/Kconfig2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-dma.c35
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c11
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c6
-rw-r--r--drivers/media/dvb/b2c2/flexcop-pci.c6
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h4
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c44
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h17
-rw-r--r--drivers/media/dvb/bt8xx/dst.c2
-rw-r--r--drivers/media/dvb/dvb-core/demux.h2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig12
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c18
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c13
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h3
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c6
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h2
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c6
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig26
-rw-r--r--drivers/media/dvb/frontends/Makefile3
-rw-r--r--drivers/media/dvb/frontends/at76c651.c450
-rw-r--r--drivers/media/dvb/frontends/at76c651.h47
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c8
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h2
-rw-r--r--drivers/media/dvb/frontends/mt312.c116
-rw-r--r--drivers/media/dvb/frontends/mt312.h6
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c706
-rw-r--r--drivers/media/dvb/frontends/nxt2002.h23
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c58
-rw-r--r--drivers/media/dvb/frontends/stv0297.c4
-rw-r--r--drivers/media/dvb/frontends/tda80xx.c734
-rw-r--r--drivers/media/dvb/frontends/tda80xx.h51
-rw-r--r--drivers/media/dvb/ttpci/av7110.c23
-rw-r--r--drivers/media/dvb/ttpci/av7110.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c3
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c30
-rw-r--r--drivers/media/video/bttv-driver.c2
-rw-r--r--drivers/media/video/compat_ioctl32.c89
-rw-r--r--drivers/media/video/cpia.c2
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c54
-rw-r--r--drivers/media/video/cx88/Kconfig40
-rw-r--r--drivers/media/video/cx88/Makefile5
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c6
-rw-r--r--drivers/media/video/cx88/cx88-cards.c6
-rw-r--r--drivers/media/video/cx88/cx88-core.c10
-rw-r--r--drivers/media/video/cx88/cx88-input.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c17
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c8
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c6
-rw-r--r--drivers/media/video/mxb.c10
-rw-r--r--drivers/media/video/saa7115.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c68
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c14
-rw-r--r--drivers/media/video/saa7134/saa7134.h2
-rw-r--r--drivers/media/video/stradis.c15
-rw-r--r--drivers/media/video/tda8290.c8
-rw-r--r--drivers/media/video/tda9887.c9
-rw-r--r--drivers/media/video/tuner-core.c13
-rw-r--r--drivers/media/video/tvaudio.c9
-rw-r--r--drivers/media/video/tvp5150.c32
-rw-r--r--drivers/media/video/videocodec.h2
-rw-r--r--drivers/media/video/zr36050.c2
-rw-r--r--drivers/media/video/zr36060.c2
-rw-r--r--drivers/media/video/zr36120_i2c.c2
-rw-r--r--drivers/message/fusion/mptbase.c115
-rw-r--r--drivers/message/fusion/mptbase.h2
-rw-r--r--drivers/message/fusion/mptctl.c241
-rw-r--r--drivers/message/fusion/mptctl.h4
-rw-r--r--drivers/message/fusion/mptscsih.c2
-rw-r--r--drivers/message/i2o/i2o_scsi.c2
-rw-r--r--drivers/misc/ibmasm/ibmasm.h9
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/au1xmmc.c81
-rw-r--r--drivers/mmc/mmc.c28
-rw-r--r--drivers/mmc/mmc_block.c8
-rw-r--r--drivers/mmc/mmci.c18
-rw-r--r--drivers/mmc/pxamci.c9
-rw-r--r--drivers/mmc/wbsd.c8
-rw-r--r--drivers/mtd/chips/Kconfig2
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c15
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/redboot.c28
-rw-r--r--drivers/net/3c509.c13
-rw-r--r--drivers/net/8139cp.c37
-rw-r--r--drivers/net/8139too.c38
-rw-r--r--drivers/net/Kconfig15
-rw-r--r--drivers/net/appletalk/cops.h2
-rw-r--r--drivers/net/bonding/bond_main.c16
-rw-r--r--drivers/net/bonding/bond_sysfs.c6
-rw-r--r--drivers/net/chelsio/espi.c4
-rw-r--r--drivers/net/chelsio/sge.c6
-rw-r--r--drivers/net/de620.c2
-rw-r--r--drivers/net/dl2k.c25
-rw-r--r--drivers/net/e100.c7
-rw-r--r--drivers/net/e1000/e1000.h3
-rw-r--r--drivers/net/e1000/e1000_main.c129
-rw-r--r--drivers/net/gianfar.c24
-rw-r--r--drivers/net/gianfar.h8
-rw-r--r--drivers/net/gianfar_ethtool.c8
-rw-r--r--drivers/net/gianfar_mii.c17
-rw-r--r--drivers/net/hamradio/baycom_par.c1
-rw-r--r--drivers/net/ifb.c2
-rw-r--r--drivers/net/irda/irda-usb.c90
-rw-r--r--drivers/net/irda/irda-usb.h7
-rw-r--r--drivers/net/mv643xx_eth.c2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c1
-rw-r--r--drivers/net/ppp_generic.c3
-rw-r--r--drivers/net/r8169.c202
-rw-r--r--drivers/net/s2io.c1
-rw-r--r--drivers/net/sis190.c4
-rw-r--r--drivers/net/sis900.c4
-rw-r--r--drivers/net/sis900.h1
-rw-r--r--drivers/net/skge.c85
-rw-r--r--drivers/net/skge.h1
-rw-r--r--drivers/net/sky2.c295
-rw-r--r--drivers/net/sky2.h91
-rw-r--r--drivers/net/tg3.c140
-rw-r--r--drivers/net/tg3.h1
-rw-r--r--drivers/net/tlan.c2
-rw-r--r--drivers/net/tokenring/smctr.h2
-rw-r--r--drivers/net/tulip/de2104x.c26
-rw-r--r--drivers/net/tulip/uli526x.c2
-rw-r--r--drivers/net/tun.c5
-rw-r--r--drivers/net/via-velocity.c3
-rw-r--r--drivers/net/wan/dscc4.c2
-rw-r--r--drivers/net/wan/pci200syn.c2
-rw-r--r--drivers/net/wan/wanxl.c2
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/atmel.c98
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c5
-rw-r--r--drivers/net/wireless/ipw2200.c6
-rw-r--r--drivers/net/wireless/orinoco_cs.c1
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/wavelan_cs.c16
-rw-r--r--drivers/parisc/ccio-dma.c167
-rw-r--r--drivers/parisc/dino.c4
-rw-r--r--drivers/parisc/hppb.c3
-rw-r--r--drivers/parisc/iosapic.c8
-rw-r--r--drivers/parisc/lasi.c5
-rw-r--r--drivers/parisc/lba_pci.c6
-rw-r--r--drivers/parisc/pdc_stable.c356
-rw-r--r--drivers/parisc/sba_iommu.c128
-rw-r--r--drivers/parisc/superio.c41
-rw-r--r--drivers/parisc/wax.c2
-rw-r--r--drivers/parport/parport_gsc.c2
-rw-r--r--drivers/parport/parport_serial.c11
-rw-r--r--drivers/pcmcia/ds.c40
-rw-r--r--drivers/pnp/card.c12
-rw-r--r--drivers/s390/block/Kconfig14
-rw-r--r--drivers/s390/block/Makefile2
-rw-r--r--drivers/s390/block/dasd.c135
-rw-r--r--drivers/s390/block/dasd_3990_erp.c3
-rw-r--r--drivers/s390/block/dasd_eckd.h1
-rw-r--r--drivers/s390/block/dasd_eer.c1090
-rw-r--r--drivers/s390/block/dasd_genhd.c2
-rw-r--r--drivers/s390/block/dasd_int.h45
-rw-r--r--drivers/s390/block/dasd_proc.c3
-rw-r--r--drivers/s390/char/sclp.c13
-rw-r--r--drivers/s390/cio/chsc.c15
-rw-r--r--drivers/s390/cio/css.c3
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/device_pgid.c2
-rw-r--r--drivers/s390/cio/device_status.c1
-rw-r--r--drivers/s390/cio/qdio.c13
-rw-r--r--drivers/s390/net/lcs.c31
-rw-r--r--drivers/s390/net/lcs.h2
-rw-r--r--drivers/s390/net/qeth.h112
-rw-r--r--drivers/s390/net/qeth_eddp.c11
-rw-r--r--drivers/s390/net/qeth_main.c17
-rw-r--r--drivers/s390/net/smsgiucv.c2
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c76
-rw-r--r--drivers/s390/scsi/zfcp_def.h14
-rw-r--r--drivers/s390/scsi/zfcp_erp.c93
-rw-r--r--drivers/s390/scsi/zfcp_ext.h5
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c80
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c23
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c4
-rw-r--r--drivers/scsi/3w-9xxx.c7
-rw-r--r--drivers/scsi/aacraid/aachba.c217
-rw-r--r--drivers/scsi/aacraid/aacraid.h18
-rw-r--r--drivers/scsi/aacraid/commctrl.c22
-rw-r--r--drivers/scsi/aacraid/comminit.c12
-rw-r--r--drivers/scsi/aacraid/commsup.c52
-rw-r--r--drivers/scsi/aacraid/dpcsup.c2
-rw-r--r--drivers/scsi/aacraid/linit.c50
-rw-r--r--drivers/scsi/aha152x.c85
-rw-r--r--drivers/scsi/aha152x.h2
-rw-r--r--drivers/scsi/ahci.c14
-rw-r--r--drivers/scsi/esp.c4
-rw-r--r--drivers/scsi/gdth.c2
-rw-r--r--drivers/scsi/ipr.c49
-rw-r--r--drivers/scsi/ipr.h5
-rw-r--r--drivers/scsi/iscsi_tcp.c78
-rw-r--r--drivers/scsi/iscsi_tcp.h4
-rw-r--r--drivers/scsi/jazz_esp.c21
-rw-r--r--drivers/scsi/libata-core.c26
-rw-r--r--drivers/scsi/libata-scsi.c2
-rw-r--r--drivers/scsi/libata.h1
-rw-r--r--drivers/scsi/mac53c94.c4
-rw-r--r--drivers/scsi/megaraid.c2
-rw-r--r--drivers/scsi/megaraid.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c130
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h53
-rw-r--r--drivers/scsi/pcmcia/Kconfig1
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c276
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h44
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h27
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c108
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c43
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c963
-rw-r--r--drivers/scsi/sata_mv.c12
-rw-r--r--drivers/scsi/sata_qstor.c2
-rw-r--r--drivers/scsi/sata_sil.c62
-rw-r--r--drivers/scsi/sata_vsc.c30
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/scsi_error.c4
-rw-r--r--drivers/scsi/scsi_lib.c61
-rw-r--r--drivers/scsi/scsi_scan.c42
-rw-r--r--drivers/scsi/scsi_sysfs.c9
-rw-r--r--drivers/scsi/scsi_transport_fc.c5
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c262
-rw-r--r--drivers/scsi/sd.c20
-rw-r--r--drivers/scsi/sg.c4
-rw-r--r--drivers/scsi/sr_ioctl.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c4
-rw-r--r--drivers/serial/21285.c2
-rw-r--r--drivers/serial/68328serial.c4
-rw-r--r--drivers/serial/68360serial.c4
-rw-r--r--drivers/serial/8250.c9
-rw-r--r--drivers/serial/8250_au1x00.c1
-rw-r--r--drivers/serial/8250_pci.c29
-rw-r--r--drivers/serial/Kconfig5
-rw-r--r--drivers/serial/amba-pl010.c4
-rw-r--r--drivers/serial/au1x00_uart.c12
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c25
-rw-r--r--drivers/serial/dz.c3
-rw-r--r--drivers/serial/imx.c4
-rw-r--r--drivers/serial/ioc4_serial.c20
-rw-r--r--drivers/serial/ip22zilog.c12
-rw-r--r--drivers/serial/m32r_sio.c2
-rw-r--r--drivers/serial/m32r_sio.h2
-rw-r--r--drivers/serial/mcfserial.c16
-rw-r--r--drivers/serial/mux.c2
-rw-r--r--drivers/serial/pmac_zilog.c2
-rw-r--r--drivers/serial/s3c2410.c4
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_core.c34
-rw-r--r--drivers/serial/serial_lh7a40x.c6
-rw-r--r--drivers/serial/sh-sci.c20
-rw-r--r--drivers/serial/sn_console.c2
-rw-r--r--drivers/serial/sunsab.c2
-rw-r--r--drivers/serial/sunsu.c13
-rw-r--r--drivers/serial/sunzilog.c4
-rw-r--r--drivers/serial/v850e_uart.c2
-rw-r--r--drivers/sn/Kconfig4
-rw-r--r--drivers/sn/ioc3.c29
-rw-r--r--drivers/spi/Kconfig10
-rw-r--r--drivers/spi/spi.c5
-rw-r--r--drivers/spi/spi_butterfly.c36
-rw-r--r--drivers/tc/tc.c1
-rw-r--r--drivers/usb/core/driver.c6
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c6
-rw-r--r--drivers/usb/gadget/rndis.c11
-rw-r--r--drivers/usb/host/pci-quirks.c27
-rw-r--r--drivers/usb/host/sl811_cs.c4
-rw-r--r--drivers/usb/input/hid-core.c52
-rw-r--r--drivers/usb/misc/Kconfig2
-rw-r--r--drivers/usb/misc/ldusb.c57
-rw-r--r--drivers/usb/serial/ftdi_sio.c6
-rw-r--r--drivers/usb/serial/ftdi_sio.h10
-rw-r--r--drivers/usb/serial/pl2303.c5
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/serial/usb-serial.c10
-rw-r--r--drivers/usb/serial/visor.c3
-rw-r--r--drivers/usb/serial/visor.h3
-rw-r--r--drivers/usb/storage/unusual_devs.h59
-rw-r--r--drivers/video/Kconfig7
-rw-r--r--drivers/video/arcfb.c5
-rw-r--r--drivers/video/asiliantfb.c21
-rw-r--r--drivers/video/aty/aty128fb.c7
-rw-r--r--drivers/video/aty/radeon_monitor.c4
-rw-r--r--drivers/video/aty/radeon_pm.c19
-rw-r--r--drivers/video/au1100fb.c3
-rw-r--r--drivers/video/backlight/backlight.c3
-rw-r--r--drivers/video/backlight/lcd.c3
-rw-r--r--drivers/video/console/sticore.c45
-rw-r--r--drivers/video/console/vgacon.c67
-rw-r--r--drivers/video/fbmem.c2
-rw-r--r--drivers/video/gbefb.c5
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/intelfb/intelfbdrv.c50
-rw-r--r--drivers/video/kyro/STG4000VTG.c2
-rw-r--r--drivers/video/neofb.c21
-rw-r--r--drivers/video/nvidia/nvidia.c2
-rw-r--r--drivers/video/pmag-ba-fb.c1
-rw-r--r--drivers/video/pmagb-b-fb.c1
-rw-r--r--drivers/video/s1d13xxxfb.c3
-rw-r--r--drivers/video/s3c2410fb.c1
-rw-r--r--drivers/video/savage/savagefb_driver.c2
-rw-r--r--drivers/video/tdfxfb.c42
429 files changed, 9040 insertions, 7258 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 619dd964c51c..5c69b86db624 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -69,7 +69,7 @@ obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_INFINIBAND) += infiniband/
-obj-$(CONFIG_SGI_IOC4) += sn/
+obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0cce28c4025b..33e2ca847a26 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -247,7 +247,7 @@ config ACPI_CUSTOM_DSDT_FILE
Enter the full path name to the file wich includes the AmlCode declaration.
config ACPI_BLACKLIST_YEAR
- int "Disable ACPI for systems before Jan 1st this year" if X86
+ int "Disable ACPI for systems before Jan 1st this year" if X86_32
default 0
help
enter a 4-digit year, eg. 2001 to disable ACPI by default
@@ -285,9 +285,8 @@ config ACPI_SYSTEM
dump your ACPI DSDT table using /proc/acpi/dsdt.
config X86_PM_TIMER
- bool "Power Management Timer Support"
+ bool "Power Management Timer Support" if EMBEDDED
depends on X86
- depends on !X86_64
default y
help
The Power Management Timer is available on all ACPI-capable,
@@ -298,9 +297,8 @@ config X86_PM_TIMER
voltage scaling, unlike the commonly used Time Stamp Counter
(TSC) timing source.
- So, if you see messages like 'Losing too many ticks!' in the
- kernel logs, and/or you are using this on a notebook which
- does not yet have an HPET, you should say "Y" here.
+ You should nearly always say Y here because many modern
+ systems require this timer.
config ACPI_CONTAINER
tristate "ACPI0004,PNP0A05 and PNP0A06 Container Driver (EXPERIMENTAL)"
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index be2dae52f6fa..eb730a80952c 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -94,7 +94,9 @@ static int set_max_cstate(struct dmi_system_id *id)
return 0;
}
-static struct dmi_system_id __initdata processor_power_dmi_table[] = {
+/* Actually this shouldn't be __cpuinitdata, would be better to fix the
+ callers to only run once -AK */
+static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
{ set_max_cstate, "IBM ThinkPad R40e", {
DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1},
@@ -899,7 +901,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
case ACPI_STATE_C3:
acpi_processor_power_verify_c3(pr, cx);
#ifdef ARCH_APICTIMER_STOPS_ON_C3
- if (c->x86_vendor == X86_VENDOR_INTEL) {
+ if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) {
on_each_cpu(switch_APIC_timer_to_ipi,
&mask, 1, 1);
}
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 7d6481d9fbec..4038dbfa63a0 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -391,8 +391,7 @@ acpi_rs_get_list_length(u8 * aml_buffer,
* Ensure a 32-bit boundary for the structure
*/
extra_struct_bytes =
- ACPI_ROUND_UP_to_32_bITS(resource_length) -
- resource_length;
+ ACPI_ROUND_UP_to_32_bITS(resource_length);
break;
case ACPI_RESOURCE_NAME_END_TAG:
@@ -408,8 +407,7 @@ acpi_rs_get_list_length(u8 * aml_buffer,
* Add vendor data and ensure a 32-bit boundary for the structure
*/
extra_struct_bytes =
- ACPI_ROUND_UP_to_32_bITS(resource_length) -
- resource_length;
+ ACPI_ROUND_UP_to_32_bITS(resource_length);
break;
case ACPI_RESOURCE_NAME_ADDRESS32:
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 14f6a6201da3..05983a312d50 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -555,7 +555,7 @@ fore200e_pca_reset(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_pca_map(struct fore200e* fore200e)
{
DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);
@@ -589,7 +589,7 @@ fore200e_pca_unmap(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_pca_configure(struct fore200e* fore200e)
{
struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;
@@ -2125,7 +2125,7 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags)
}
-static int __init
+static int __devinit
fore200e_irq_request(struct fore200e* fore200e)
{
if (request_irq(fore200e->irq, fore200e_interrupt, SA_SHIRQ, fore200e->name, fore200e->atm_dev) < 0) {
@@ -2148,7 +2148,7 @@ fore200e_irq_request(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_get_esi(struct fore200e* fore200e)
{
struct prom_data* prom = fore200e_kmalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
@@ -2180,7 +2180,7 @@ fore200e_get_esi(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_alloc_rx_buf(struct fore200e* fore200e)
{
int scheme, magn, nbr, size, i;
@@ -2245,7 +2245,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_init_bs_queue(struct fore200e* fore200e)
{
int scheme, magn, i;
@@ -2308,7 +2308,7 @@ fore200e_init_bs_queue(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_init_rx_queue(struct fore200e* fore200e)
{
struct host_rxq* rxq = &fore200e->host_rxq;
@@ -2368,7 +2368,7 @@ fore200e_init_rx_queue(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_init_tx_queue(struct fore200e* fore200e)
{
struct host_txq* txq = &fore200e->host_txq;
@@ -2431,7 +2431,7 @@ fore200e_init_tx_queue(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_init_cmd_queue(struct fore200e* fore200e)
{
struct host_cmdq* cmdq = &fore200e->host_cmdq;
@@ -2487,7 +2487,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e,
}
-static int __init
+static int __devinit
fore200e_initialize(struct fore200e* fore200e)
{
struct cp_queues __iomem * cpq;
@@ -2539,7 +2539,7 @@ fore200e_initialize(struct fore200e* fore200e)
}
-static void __init
+static void __devinit
fore200e_monitor_putc(struct fore200e* fore200e, char c)
{
struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
@@ -2551,7 +2551,7 @@ fore200e_monitor_putc(struct fore200e* fore200e, char c)
}
-static int __init
+static int __devinit
fore200e_monitor_getc(struct fore200e* fore200e)
{
struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
@@ -2576,7 +2576,7 @@ fore200e_monitor_getc(struct fore200e* fore200e)
}
-static void __init
+static void __devinit
fore200e_monitor_puts(struct fore200e* fore200e, char* str)
{
while (*str) {
@@ -2591,7 +2591,7 @@ fore200e_monitor_puts(struct fore200e* fore200e, char* str)
}
-static int __init
+static int __devinit
fore200e_start_fw(struct fore200e* fore200e)
{
int ok;
@@ -2622,7 +2622,7 @@ fore200e_start_fw(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_load_fw(struct fore200e* fore200e)
{
u32* fw_data = (u32*) fore200e->bus->fw_data;
@@ -2648,7 +2648,7 @@ fore200e_load_fw(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_register(struct fore200e* fore200e)
{
struct atm_dev* atm_dev;
@@ -2675,7 +2675,7 @@ fore200e_register(struct fore200e* fore200e)
}
-static int __init
+static int __devinit
fore200e_init(struct fore200e* fore200e)
{
if (fore200e_register(fore200e) < 0)
@@ -2721,7 +2721,7 @@ fore200e_init(struct fore200e* fore200e)
return -EBUSY;
fore200e_supply(fore200e);
-
+
/* all done, board initialization is now complete */
fore200e->state = FORE200E_STATE_COMPLETE;
return 0;
diff --git a/drivers/base/base.h b/drivers/base/base.h
index e3b548d46cff..5735b38582d0 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -19,6 +19,10 @@ extern void bus_remove_driver(struct device_driver *);
extern void driver_detach(struct device_driver * drv);
extern int driver_probe_device(struct device_driver *, struct device *);
+extern void sysdev_shutdown(void);
+extern int sysdev_suspend(pm_message_t state);
+extern int sysdev_resume(void);
+
static inline struct class_device *to_class_dev(struct kobject *obj)
{
return container_of(obj, struct class_device, kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 29f6af554e71..c3141565d59d 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -133,6 +133,8 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
+#ifdef CONFIG_HOTPLUG
+
/* Manually detach a device from its associated driver. */
static int driver_helper(struct device *dev, void *data)
{
@@ -193,6 +195,7 @@ static ssize_t driver_bind(struct device_driver *drv,
}
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+#endif
static struct device * next_device(struct klist_iter * i)
{
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index d1a05224627e..105a0d61eb1f 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -303,7 +303,7 @@ static int block_size_init(void)
*/
#ifdef CONFIG_ARCH_MEMORY_PROBE
static ssize_t
-memory_probe_store(struct class *class, const char __user *buf, size_t count)
+memory_probe_store(struct class *class, const char *buf, size_t count)
{
u64 phys_addr;
int ret;
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 0a7aa07b9a2a..317edbf0feca 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -9,10 +9,9 @@
*/
#include <linux/device.h>
+#include "../base.h"
#include "power.h"
-extern int sysdev_resume(void);
-
/**
* resume_device - Restore state for one device.
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index c2475f3134ea..8826a5b6673e 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <asm/semaphore.h>
+#include "../base.h"
#include "power.h"
#define to_dev(node) container_of(node, struct device, kobj.entry)
@@ -28,7 +29,6 @@ extern struct subsystem devices_subsys;
* they only get one called once when interrupts are disabled.
*/
-extern int sysdev_shutdown(void);
/**
* device_shutdown - call ->shutdown() on each device to shutdown.
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 50501764d050..8660779fb288 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -9,10 +9,9 @@
*/
#include <linux/device.h>
+#include "../base.h"
#include "power.h"
-extern int sysdev_suspend(pm_message_t state);
-
/*
* The entries in the dpm_active list are in a depth first order, simply
* because children are guaranteed to be discovered after parents, and
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index f3a0c562bcb5..40d7242a07c1 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -27,22 +27,30 @@
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
- return sprintf(buf, "%u\n", dev->power.power_state.event);
+ if (dev->power.power_state.event)
+ return sprintf(buf, "2\n");
+ else
+ return sprintf(buf, "0\n");
}
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
pm_message_t state;
- char * rest;
- int error = 0;
+ int error = -EINVAL;
- state.event = simple_strtoul(buf, &rest, 10);
- if (*rest)
- return -EINVAL;
- if (state.event)
+ state.event = PM_EVENT_SUSPEND;
+ /* Older apps expected to write "3" here - confused with PCI D3 */
+ if ((n == 1) && !strcmp(buf, "3"))
error = dpm_runtime_suspend(dev, state);
- else
+
+ if ((n == 1) && !strcmp(buf, "2"))
+ error = dpm_runtime_suspend(dev, state);
+
+ if ((n == 1) && !strcmp(buf, "0")) {
dpm_runtime_resume(dev);
+ error = 0;
+ }
+
return error ? error : n;
}
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 66ed8f2fece5..6fc23ab127bd 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,8 +21,11 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pm.h>
+#include <linux/device.h>
#include <asm/semaphore.h>
+#include "base.h"
+
extern struct subsystem devices_subsys;
#define to_sysdev(k) container_of(k, struct sys_device, kobj)
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 6ede1f352c29..37b8cda3e8bc 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -41,6 +41,7 @@
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/random.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "DAC960.h"
@@ -3463,7 +3464,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
Command->SegmentCount, Command->DmaDirection);
if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
-
+ add_disk_randomness(Request->rq_disk);
end_that_request_last(Request, UpToDate);
if (Command->Completion) {
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 139cbba76180..8b1331677407 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -433,12 +433,12 @@ config CDROM_PKTCDVD_BUFFERS
This controls the maximum number of active concurrent packets. More
concurrent packets can increase write performance, but also require
more memory. Each concurrent packet will require approximately 64Kb
- of non-swappable kernel memory, memory which will be allocated at
- pktsetup time.
+ of non-swappable kernel memory, memory which will be allocated when
+ a disc is opened for writing.
config CDROM_PKTCDVD_WCACHE
- bool "Enable write caching"
- depends on CDROM_PKTCDVD
+ bool "Enable write caching (EXPERIMENTAL)"
+ depends on CDROM_PKTCDVD && EXPERIMENTAL
help
If enabled, write caching will be set for the CD-R/W device. For now
this option is dangerous unless the CD-RW media is known good, as we
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 12d7b9bdfa93..0d65394707db 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2183,6 +2183,7 @@ static void cciss_softirq_done(struct request *rq)
{
CommandList_struct *cmd = rq->completion_data;
ctlr_info_t *h = hba[cmd->ctlr];
+ unsigned long flags;
u64bit temp64;
int i, ddir;
@@ -2205,10 +2206,10 @@ static void cciss_softirq_done(struct request *rq)
printk("Done with %p\n", rq);
#endif /* CCISS_DEBUG */
- spin_lock_irq(&h->lock);
+ spin_lock_irqsave(&h->lock, flags);
end_that_request_last(rq, rq->errors);
cmd_free(h, cmd,1);
- spin_unlock_irq(&h->lock);
+ spin_unlock_irqrestore(&h->lock, flags);
}
/* checks the status of the job and calls complete buffers to mark all
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 93affeeef7bd..bc9b2bcd7dba 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -43,8 +43,6 @@
*
*************************************************************************/
-#define VERSION_CODE "v0.2.0a 2004-07-14 Jens Axboe (axboe@suse.de) and petero2@telia.com"
-
#include <linux/pktcdvd.h>
#include <linux/config.h>
#include <linux/module.h>
@@ -60,6 +58,7 @@
#include <linux/suspend.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi.h>
#include <asm/uaccess.h>
@@ -131,7 +130,7 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
/*
* Allocate a packet_data struct
*/
-static struct packet_data *pkt_alloc_packet_data(void)
+static struct packet_data *pkt_alloc_packet_data(int frames)
{
int i;
struct packet_data *pkt;
@@ -140,11 +139,12 @@ static struct packet_data *pkt_alloc_packet_data(void)
if (!pkt)
goto no_pkt;
- pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
+ pkt->frames = frames;
+ pkt->w_bio = pkt_bio_alloc(frames);
if (!pkt->w_bio)
goto no_bio;
- for (i = 0; i < PAGES_PER_PACKET; i++) {
+ for (i = 0; i < frames / FRAMES_PER_PAGE; i++) {
pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
if (!pkt->pages[i])
goto no_page;
@@ -152,7 +152,7 @@ static struct packet_data *pkt_alloc_packet_data(void)
spin_lock_init(&pkt->lock);
- for (i = 0; i < PACKET_MAX_SIZE; i++) {
+ for (i = 0; i < frames; i++) {
struct bio *bio = pkt_bio_alloc(1);
if (!bio)
goto no_rd_bio;
@@ -162,14 +162,14 @@ static struct packet_data *pkt_alloc_packet_data(void)
return pkt;
no_rd_bio:
- for (i = 0; i < PACKET_MAX_SIZE; i++) {
+ for (i = 0; i < frames; i++) {
struct bio *bio = pkt->r_bios[i];
if (bio)
bio_put(bio);
}
no_page:
- for (i = 0; i < PAGES_PER_PACKET; i++)
+ for (i = 0; i < frames / FRAMES_PER_PAGE; i++)
if (pkt->pages[i])
__free_page(pkt->pages[i]);
bio_put(pkt->w_bio);
@@ -186,12 +186,12 @@ static void pkt_free_packet_data(struct packet_data *pkt)
{
int i;
- for (i = 0; i < PACKET_MAX_SIZE; i++) {
+ for (i = 0; i < pkt->frames; i++) {
struct bio *bio = pkt->r_bios[i];
if (bio)
bio_put(bio);
}
- for (i = 0; i < PAGES_PER_PACKET; i++)
+ for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++)
__free_page(pkt->pages[i]);
bio_put(pkt->w_bio);
kfree(pkt);
@@ -206,17 +206,17 @@ static void pkt_shrink_pktlist(struct pktcdvd_device *pd)
list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) {
pkt_free_packet_data(pkt);
}
+ INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
}
static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
{
struct packet_data *pkt;
- INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
- INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
- spin_lock_init(&pd->cdrw.active_list_lock);
+ BUG_ON(!list_empty(&pd->cdrw.pkt_free_list));
+
while (nr_packets > 0) {
- pkt = pkt_alloc_packet_data();
+ pkt = pkt_alloc_packet_data(pd->settings.size >> 2);
if (!pkt) {
pkt_shrink_pktlist(pd);
return 0;
@@ -381,6 +381,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
+ rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->ref_count++;
rq->flags |= REQ_NOMERGE;
@@ -646,7 +647,7 @@ static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct pag
* b) The data can be used as cache to avoid read requests if we receive a
* new write request for the same zone.
*/
-static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, int *offsets)
+static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
{
int f, p, offs;
@@ -654,15 +655,15 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in
p = 0;
offs = 0;
for (f = 0; f < pkt->frames; f++) {
- if (pages[f] != pkt->pages[p]) {
- void *vfrom = kmap_atomic(pages[f], KM_USER0) + offsets[f];
+ if (bvec[f].bv_page != pkt->pages[p]) {
+ void *vfrom = kmap_atomic(bvec[f].bv_page, KM_USER0) + bvec[f].bv_offset;
void *vto = page_address(pkt->pages[p]) + offs;
memcpy(vto, vfrom, CD_FRAMESIZE);
kunmap_atomic(vfrom, KM_USER0);
- pages[f] = pkt->pages[p];
- offsets[f] = offs;
+ bvec[f].bv_page = pkt->pages[p];
+ bvec[f].bv_offset = offs;
} else {
- BUG_ON(offsets[f] != offs);
+ BUG_ON(bvec[f].bv_offset != offs);
}
offs += CD_FRAMESIZE;
if (offs >= PAGE_SIZE) {
@@ -951,7 +952,7 @@ try_next_bio:
pd->current_sector = zone + pd->settings.size;
pkt->sector = zone;
- pkt->frames = pd->settings.size >> 2;
+ BUG_ON(pkt->frames != pd->settings.size >> 2);
pkt->write_size = 0;
/*
@@ -992,18 +993,17 @@ try_next_bio:
static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
{
struct bio *bio;
- struct page *pages[PACKET_MAX_SIZE];
- int offsets[PACKET_MAX_SIZE];
int f;
int frames_write;
+ struct bio_vec *bvec = pkt->w_bio->bi_io_vec;
for (f = 0; f < pkt->frames; f++) {
- pages[f] = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
- offsets[f] = (f * CD_FRAMESIZE) % PAGE_SIZE;
+ bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
+ bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
}
/*
- * Fill-in pages[] and offsets[] with data from orig_bios.
+ * Fill-in bvec with data from orig_bios.
*/
frames_write = 0;
spin_lock(&pkt->lock);
@@ -1025,11 +1025,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
}
if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) {
- pages[f] = src_bvl->bv_page;
- offsets[f] = src_bvl->bv_offset + src_offs;
+ bvec[f].bv_page = src_bvl->bv_page;
+ bvec[f].bv_offset = src_bvl->bv_offset + src_offs;
} else {
pkt_copy_bio_data(bio, segment, src_offs,
- pages[f], offsets[f]);
+ bvec[f].bv_page, bvec[f].bv_offset);
}
src_offs += CD_FRAMESIZE;
frames_write++;
@@ -1043,7 +1043,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
BUG_ON(frames_write != pkt->write_size);
if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
- pkt_make_local_copy(pkt, pages, offsets);
+ pkt_make_local_copy(pkt, bvec);
pkt->cache_valid = 1;
} else {
pkt->cache_valid = 0;
@@ -1056,17 +1056,9 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt->w_bio->bi_bdev = pd->bdev;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;
- for (f = 0; f < pkt->frames; f++) {
- if ((f + 1 < pkt->frames) && (pages[f + 1] == pages[f]) &&
- (offsets[f + 1] = offsets[f] + CD_FRAMESIZE)) {
- if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE * 2, offsets[f]))
- BUG();
- f++;
- } else {
- if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE, offsets[f]))
- BUG();
- }
- }
+ for (f = 0; f < pkt->frames; f++)
+ if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
+ BUG();
VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt);
atomic_set(&pkt->io_wait, 1);
@@ -1505,40 +1497,42 @@ static int pkt_set_write_settings(struct pktcdvd_device *pd)
}
/*
- * 0 -- we can write to this track, 1 -- we can't
+ * 1 -- we can write to this track, 0 -- we can't
*/
-static int pkt_good_track(track_information *ti)
+static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
{
- /*
- * only good for CD-RW at the moment, not DVD-RW
- */
+ switch (pd->mmc3_profile) {
+ case 0x1a: /* DVD+RW */
+ case 0x12: /* DVD-RAM */
+ /* The track is always writable on DVD+RW/DVD-RAM */
+ return 1;
+ default:
+ break;
+ }
- /*
- * FIXME: only for FP
- */
- if (ti->fp == 0)
+ if (!ti->packet || !ti->fp)
return 0;
/*
* "good" settings as per Mt Fuji.
*/
- if (ti->rt == 0 && ti->blank == 0 && ti->packet == 1)
- return 0;
+ if (ti->rt == 0 && ti->blank == 0)
+ return 1;
- if (ti->rt == 0 && ti->blank == 1 && ti->packet == 1)
- return 0;
+ if (ti->rt == 0 && ti->blank == 1)
+ return 1;
- if (ti->rt == 1 && ti->blank == 0 && ti->packet == 1)
- return 0;
+ if (ti->rt == 1 && ti->blank == 0)
+ return 1;
printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
- return 1;
+ return 0;
}
/*
- * 0 -- we can write to this disc, 1 -- we can't
+ * 1 -- we can write to this disc, 0 -- we can't
*/
-static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
+static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
{
switch (pd->mmc3_profile) {
case 0x0a: /* CD-RW */
@@ -1547,10 +1541,10 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
case 0x1a: /* DVD+RW */
case 0x13: /* DVD-RW */
case 0x12: /* DVD-RAM */
- return 0;
- default:
- printk("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
return 1;
+ default:
+ VPRINTK("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
+ return 0;
}
/*
@@ -1559,25 +1553,25 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
*/
if (di->disc_type == 0xff) {
printk("pktcdvd: Unknown disc. No track?\n");
- return 1;
+ return 0;
}
if (di->disc_type != 0x20 && di->disc_type != 0) {
printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type);
- return 1;
+ return 0;
}
if (di->erasable == 0) {
printk("pktcdvd: Disc not erasable\n");
- return 1;
+ return 0;
}
if (di->border_status == PACKET_SESSION_RESERVED) {
printk("pktcdvd: Can't write to last track (reserved)\n");
- return 1;
+ return 0;
}
- return 0;
+ return 1;
}
static int pkt_probe_settings(struct pktcdvd_device *pd)
@@ -1602,23 +1596,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
return ret;
}
- if (pkt_good_disc(pd, &di))
- return -ENXIO;
+ if (!pkt_writable_disc(pd, &di))
+ return -EROFS;
- switch (pd->mmc3_profile) {
- case 0x1a: /* DVD+RW */
- printk("pktcdvd: inserted media is DVD+RW\n");
- break;
- case 0x13: /* DVD-RW */
- printk("pktcdvd: inserted media is DVD-RW\n");
- break;
- case 0x12: /* DVD-RAM */
- printk("pktcdvd: inserted media is DVD-RAM\n");
- break;
- default:
- printk("pktcdvd: inserted media is CD-R%s\n", di.erasable ? "W" : "");
- break;
- }
pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR;
track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
@@ -1627,9 +1607,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
return ret;
}
- if (pkt_good_track(&ti)) {
+ if (!pkt_writable_track(pd, &ti)) {
printk("pktcdvd: can't write to this track\n");
- return -ENXIO;
+ return -EROFS;
}
/*
@@ -1639,11 +1619,11 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
if (pd->settings.size == 0) {
printk("pktcdvd: detected zero packet size!\n");
- pd->settings.size = 128;
+ return -ENXIO;
}
if (pd->settings.size > PACKET_MAX_SECTORS) {
printk("pktcdvd: packet size is too big\n");
- return -ENXIO;
+ return -EROFS;
}
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -1685,7 +1665,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
break;
default:
printk("pktcdvd: unknown data mode\n");
- return 1;
+ return -EROFS;
}
return 0;
}
@@ -1895,8 +1875,8 @@ static int pkt_open_write(struct pktcdvd_device *pd)
unsigned int write_speed, media_write_speed, read_speed;
if ((ret = pkt_probe_settings(pd))) {
- DPRINTK("pktcdvd: %s failed probe\n", pd->name);
- return -EIO;
+ VPRINTK("pktcdvd: %s failed probe\n", pd->name);
+ return ret;
}
if ((ret = pkt_set_write_settings(pd))) {
@@ -1987,8 +1967,14 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
if ((ret = pkt_set_segment_merging(pd, q)))
goto out_unclaim;
- if (write)
+ if (write) {
+ if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
+ printk("pktcdvd: not enough memory for buffers\n");
+ ret = -ENOMEM;
+ goto out_unclaim;
+ }
printk("pktcdvd: %lukB available on disc\n", lba << 1);
+ }
return 0;
@@ -2014,6 +2000,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
bd_release(pd->bdev);
blkdev_put(pd->bdev);
+
+ pkt_shrink_pktlist(pd);
}
static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
@@ -2046,10 +2034,9 @@ static int pkt_open(struct inode *inode, struct file *file)
goto out_dec;
}
} else {
- if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) {
- ret = -EIO;
+ ret = pkt_open_dev(pd, file->f_mode & FMODE_WRITE);
+ if (ret)
goto out_dec;
- }
/*
* needed here as well, since ext2 (among others) may change
* the blocksize at mount time
@@ -2379,12 +2366,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
/* This is safe, since we have a reference from open(). */
__module_get(THIS_MODULE);
- if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
- printk("pktcdvd: not enough memory for buffers\n");
- ret = -ENOMEM;
- goto out_mem;
- }
-
pd->bdev = bdev;
set_blocksize(bdev, CD_FRAMESIZE);
@@ -2395,7 +2376,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
if (IS_ERR(pd->cdrw.thread)) {
printk("pktcdvd: can't start kernel thread\n");
ret = -ENOMEM;
- goto out_thread;
+ goto out_mem;
}
proc = create_proc_entry(pd->name, 0, pkt_proc);
@@ -2406,8 +2387,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
return 0;
-out_thread:
- pkt_shrink_pktlist(pd);
out_mem:
blkdev_put(bdev);
/* This is safe: open() is still holding a reference. */
@@ -2437,11 +2416,12 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
* The door gets locked when the device is opened, so we
* have to unlock it or else the eject command fails.
*/
- pkt_lock_door(pd, 0);
+ if (pd->refcnt == 1)
+ pkt_lock_door(pd, 0);
return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
default:
- printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
+ VPRINTK("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
return -ENOTTY;
}
@@ -2503,6 +2483,10 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
goto out_mem;
pd->disk = disk;
+ INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
+ INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
+ spin_lock_init(&pd->cdrw.active_list_lock);
+
spin_lock_init(&pd->lock);
spin_lock_init(&pd->iosched.lock);
sprintf(pd->name, "pktcdvd%d", idx);
@@ -2567,8 +2551,6 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
blkdev_put(pd->bdev);
- pkt_shrink_pktlist(pd);
-
remove_proc_entry(pd->name, pkt_proc);
DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
@@ -2678,7 +2660,6 @@ static int __init pkt_init(void)
pkt_proc = proc_mkdir("pktcdvd", proc_root_driver);
- DPRINTK("pktcdvd: %s\n", VERSION_CODE);
return 0;
out:
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index e522d19ad886..7e21b1ff27c4 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -474,18 +474,6 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
/* ======================== Card services HCI interaction ======================== */
-static struct device *bt3c_device(void)
-{
- static struct device dev = {
- .bus_id = "pcmcia",
- };
- kobject_set_name(&dev.kobj, "bt3c");
- kobject_init(&dev.kobj);
-
- return &dev;
-}
-
-
static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count)
{
char *ptr = (char *) firmware;
@@ -574,6 +562,7 @@ static int bt3c_open(bt3c_info_t *info)
{
const struct firmware *firmware;
struct hci_dev *hdev;
+ client_handle_t handle;
int err;
spin_lock_init(&(info->lock));
@@ -605,8 +594,10 @@ static int bt3c_open(bt3c_info_t *info)
hdev->owner = THIS_MODULE;
+ handle = info->link.handle;
+
/* Load firmware */
- err = request_firmware(&firmware, "BT3CPCC.bin", bt3c_device());
+ err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
if (err < 0) {
BT_ERR("Firmware request failed");
goto error;
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 193446e6a08a..e27617259552 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -42,8 +42,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <asm/bug.h>
-
#include <asm/vio.h>
#include <asm/scatterlist.h>
#include <asm/iseries/hv_types.h>
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4c67727d75b1..05ba410682a3 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -222,7 +222,7 @@ config SYNCLINKMP
config SYNCLINK_GT
tristate "SyncLink GT/AC support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && PCI
help
Support for SyncLink GT and SyncLink AC families of
synchronous and asynchronous serial adapters
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 486ed8a11b59..a4d425d2dce2 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -15,22 +15,23 @@ config AGP
due to kernel allocation issues), you could use PCI accesses
and have up to a couple gigs of texture space.
- Note that this is the only means to have XFree4/GLX use
+ Note that this is the only means to have X/GLX use
write-combining with MTRR support on the AGP bus. Without it, OpenGL
direct rendering will be a lot slower but still faster than PIO.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
To compile this driver as a module, choose M here: the
module will be called agpgart.
+ You should say Y here if you want to use GLX or DRI.
+
+ If unsure, say N.
+
config AGP_ALI
tristate "ALI chipset support"
depends on AGP && X86_32
---help---
This option gives you AGP support for the GLX component of
- XFree86 4.x on the following ALi chipsets. The supported chipsets
+ X on the following ALi chipsets. The supported chipsets
include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
For the ALi-chipset question, ALi suggests you refer to
<http://www.ali.com.tw/eng/support/index.shtml>.
@@ -40,28 +41,19 @@ config AGP_ALI
timing issues, this chipset cannot do AGP 2x with the G200.
This is a hardware limitation. AGP 1x seems to be fine, though.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
config AGP_ATI
tristate "ATI chipset support"
depends on AGP && X86_32
---help---
- This option gives you AGP support for the GLX component of
- XFree86 4.x on the ATI RadeonIGP family of chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ This option gives you AGP support for the GLX component of
+ X on the ATI RadeonIGP family of chipsets.
config AGP_AMD
tristate "AMD Irongate, 761, and 762 chipset support"
depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ X on AMD Irongate, 761, and 762 chipsets.
config AGP_AMD64
tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
@@ -69,45 +61,38 @@ config AGP_AMD64
default y if GART_IOMMU
help
This option gives you AGP support for the GLX component of
- XFree86 4.x using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
+ X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
You still need an external AGP bridge like the AMD 8151, VIA
K8T400M, SiS755. It may also support other AGP bridges when loaded
with agp_try_unsupported=1.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y
config AGP_INTEL
tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
depends on AGP && X86
help
- This option gives you AGP support for the GLX component of XFree86 4.x
+ This option gives you AGP support for the GLX component of X
on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
- E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G,
- 852GM, 855GM, 865G and I915 integrated graphics chipsets.
+ E7205 and E7505 chipsets and full support for the 810, 815, 830M,
+ 845G, 852GM, 855GM, 865G and I915 integrated graphics chipsets.
+
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI, or if you have any Intel integrated graphics
- chipsets. If unsure, say Y.
config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on the following NVIDIA chipsets. The supported chipsets
- include nForce and nForce2
+ X on NVIDIA chipsets including nForce and nForce2
config AGP_SIS
tristate "SiS chipset support"
depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on Silicon Integrated Systems [SiS] chipsets.
+ X on Silicon Integrated Systems [SiS] chipsets.
Note that 5591/5592 AGP chipsets are NOT supported.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
config AGP_SWORKS
tristate "Serverworks LE/HE chipset support"
@@ -121,10 +106,7 @@ config AGP_VIA
depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on VIA MVP3/Apollo Pro chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ X on VIA MVP3/Apollo Pro chipsets.
config AGP_I460
tristate "Intel 460GX chipset support"
@@ -159,9 +141,6 @@ config AGP_EFFICEON
This option gives you AGP support for the Transmeta Efficeon
series processors with integrated northbridges.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y.
-
config AGP_SGI_TIOCA
tristate "SGI TIO chipset AGP support"
depends on AGP && (IA64_SGI_SN2 || IA64_GENERIC)
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 9964c508c111..1251b2515bbe 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -516,8 +516,10 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
- if ( (apbase & 0x7fff) >> (32 - 25) )
- return -ENODEV;
+ if ( (apbase & 0x7fff) >> (32 - 25) ) {
+ printk(KERN_INFO PFX "aperture base > 4G\n");
+ return -ENODEV;
+ }
apbase = (apbase & 0x7fff) << 25;
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 268f78d926d3..efef9999f1cf 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -468,9 +468,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
switch (pdev->device) {
case 0x0006:
- /* ServerWorks CNB20HE
- Fail silently.*/
- printk (KERN_ERR PFX "Detected ServerWorks CNB20HE chipset: No AGP present.\n");
+ printk (KERN_ERR PFX "ServerWorks CNB20HE is unsupported due to lack of documentation.\n");
return -ENODEV;
case PCI_DEVICE_ID_SERVERWORKS_HE:
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 71b8b32b075f..107df9fdba4e 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -980,7 +980,7 @@ extern int drm_put_head(drm_head_t * head);
extern unsigned int drm_debug;
extern unsigned int drm_cards_limit;
extern drm_head_t **drm_heads;
-extern struct drm_sysfs_class *drm_class;
+extern struct class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
/* Proc support (drm_proc.h) */
@@ -1011,11 +1011,9 @@ extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
/* sysfs support (drm_sysfs.c) */
-struct drm_sysfs_class;
-extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
- char *name);
-extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
-extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
+extern struct class *drm_sysfs_create(struct module *owner, char *name);
+extern void drm_sysfs_destroy(struct class *cs);
+extern struct class_device *drm_sysfs_device_add(struct class *cs,
drm_head_t *head);
extern void drm_sysfs_device_remove(struct class_device *class_dev);
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 8fd6357a48da..2c17e88a8847 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -85,7 +85,6 @@
{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
{0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 7a9263ff3007..68073e14fdec 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -50,7 +50,7 @@ module_param_named(cards_limit, drm_cards_limit, int, 0444);
module_param_named(debug, drm_debug, int, 0600);
drm_head_t **drm_heads;
-struct drm_sysfs_class *drm_class;
+struct class *drm_class;
struct proc_dir_entry *drm_proc_root;
static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 68e43ddc16ae..0b9f98a7eb10 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -1,3 +1,4 @@
+
/*
* drm_sysfs.c - Modifications to drm_sysfs_class.c to support
* extra sysfs attribute from DRM. Normal drm_sysfs_class
@@ -19,36 +20,6 @@
#include "drm_core.h"
#include "drmP.h"
-struct drm_sysfs_class {
- struct class_device_attribute attr;
- struct class class;
-};
-#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
-
-struct simple_dev {
- dev_t dev;
- struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static void release_simple_dev(struct class_device *class_dev)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- kfree(s_dev);
-}
-
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- return print_dev_t(buf, s_dev->dev);
-}
-
-static void drm_sysfs_class_release(struct class *class)
-{
- struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
- kfree(cs);
-}
-
/* Display the version of drm_core. This doesn't work right in current design */
static ssize_t version_show(struct class *dev, char *buf)
{
@@ -69,38 +40,16 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
* Note, the pointer created here is to be destroyed when finished by making a
* call to drm_sysfs_destroy().
*/
-struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
+struct class *drm_sysfs_create(struct module *owner, char *name)
{
- struct drm_sysfs_class *cs;
- int retval;
-
- cs = kmalloc(sizeof(*cs), GFP_KERNEL);
- if (!cs) {
- retval = -ENOMEM;
- goto error;
- }
- memset(cs, 0x00, sizeof(*cs));
-
- cs->class.name = name;
- cs->class.class_release = drm_sysfs_class_release;
- cs->class.release = release_simple_dev;
-
- cs->attr.attr.name = "dev";
- cs->attr.attr.mode = S_IRUGO;
- cs->attr.attr.owner = owner;
- cs->attr.show = show_dev;
- cs->attr.store = NULL;
-
- retval = class_register(&cs->class);
- if (retval)
- goto error;
- class_create_file(&cs->class, &class_attr_version);
-
- return cs;
-
- error:
- kfree(cs);
- return ERR_PTR(retval);
+ struct class *class;
+
+ class = class_create(owner, name);
+ if (!class)
+ return class;
+
+ class_create_file(class, &class_attr_version);
+ return class;
}
/**
@@ -110,12 +59,13 @@ struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
* Note, the pointer to be destroyed must have been created with a call to
* drm_sysfs_create().
*/
-void drm_sysfs_destroy(struct drm_sysfs_class *cs)
+void drm_sysfs_destroy(struct class *class)
{
- if ((cs == NULL) || (IS_ERR(cs)))
+ if ((class == NULL) || (IS_ERR(class)))
return;
- class_unregister(&cs->class);
+ class_remove_file(class, &class_attr_version);
+ class_destroy(class);
}
static ssize_t show_dri(struct class_device *class_device, char *buf)
@@ -132,7 +82,7 @@ static struct class_device_attribute class_device_attrs[] = {
/**
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
+ * @cs: pointer to the struct class that this device should be registered to.
* @dev: the dev_t for the device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
@@ -141,46 +91,26 @@ static struct class_device_attribute class_device_attrs[] = {
* class. A "dev" file will be created, showing the dev_t for the device. The
* pointer to the struct class_device will be returned from the call. Any further
* sysfs files that might be required can be created using this pointer.
- * Note: the struct drm_sysfs_class passed to this function must have previously been
+ * Note: the struct class passed to this function must have previously been
* created with a call to drm_sysfs_create().
*/
-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
- drm_head_t *head)
+struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
{
- struct simple_dev *s_dev = NULL;
- int i, retval;
-
- if ((cs == NULL) || (IS_ERR(cs))) {
- retval = -ENODEV;
- goto error;
- }
-
- s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
- if (!s_dev) {
- retval = -ENOMEM;
- goto error;
- }
- memset(s_dev, 0x00, sizeof(*s_dev));
-
- s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
- s_dev->class_dev.dev = &(head->dev->pdev)->dev;
- s_dev->class_dev.class = &cs->class;
+ struct class_device *class_dev;
+ int i;
- snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
- retval = class_device_register(&s_dev->class_dev);
- if (retval)
- goto error;
+ class_dev = class_device_create(cs, NULL,
+ MKDEV(DRM_MAJOR, head->minor),
+ &(head->dev->pdev)->dev,
+ "card%d", head->minor);
+ if (!class_dev)
+ return NULL;
- class_device_create_file(&s_dev->class_dev, &cs->attr);
- class_set_devdata(&s_dev->class_dev, head);
+ class_set_devdata(class_dev, head);
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
- return &s_dev->class_dev;
-
-error:
- kfree(s_dev);
- return ERR_PTR(retval);
+ class_device_create_file(class_dev, &class_device_attrs[i]);
+ return class_dev;
}
/**
@@ -192,10 +122,9 @@ error:
*/
void drm_sysfs_device_remove(struct class_device *class_dev)
{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
int i;
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
- class_device_unregister(&s_dev->class_dev);
+ class_device_remove_file(class_dev, &class_device_attrs[i]);
+ class_device_unregister(class_dev);
}
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index a1381c61aa63..d3879ac9970f 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -202,10 +202,15 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
void i915_driver_irq_uninstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ u16 temp;
+
if (!dev_priv)
return;
I915_WRITE16(I915REG_HWSTAM, 0xffff);
I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+
+ temp = I915_READ16(I915REG_INT_IDENTITY_R);
+ I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
}
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index 291dbf4c8186..c08fa5076f05 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -161,6 +161,7 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
ADD_RANGE(R300_GB_ENABLE, 1);
ADD_RANGE(R300_GB_MSPOS0, 5);
+ ADD_RANGE(R300_TX_CNTL, 1);
ADD_RANGE(R300_TX_ENABLE, 1);
ADD_RANGE(0x4200, 4);
ADD_RANGE(0x4214, 1);
@@ -489,6 +490,50 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
return 0;
}
+static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+ u32 *cmd = (u32 *) cmdbuf->buf;
+ int count, ret;
+ RING_LOCALS;
+
+ count=(cmd[0]>>16) & 0x3fff;
+
+ if (cmd[0] & 0x8000) {
+ u32 offset;
+
+ if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+ | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+ offset = cmd[2] << 10;
+ ret = r300_check_offset(dev_priv, offset);
+ if (ret) {
+ DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+ (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+ offset = cmd[3] << 10;
+ ret = r300_check_offset(dev_priv, offset);
+ if (ret) {
+ DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
+ return DRM_ERR(EINVAL);
+ }
+
+ }
+ }
+
+ BEGIN_RING(count+2);
+ OUT_RING(cmd[0]);
+ OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+ ADVANCE_RING();
+
+ cmdbuf->buf += (count+2)*4;
+ cmdbuf->bufsz -= (count+2)*4;
+
+ return 0;
+}
static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t *cmdbuf)
@@ -527,6 +572,9 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+ case RADEON_CNTL_BITBLT_MULTI:
+ return r300_emit_bitblt_multi(dev_priv, cmdbuf);
+
case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index a0ed20e25221..d1e19954406b 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -451,6 +451,9 @@ I am fairly certain that they are correct unless stated otherwise in comments.
/* END */
/* gap */
+/* Zero to flush caches. */
+#define R300_TX_CNTL 0x4100
+
/* The upper enable bits are guessed, based on fglrx reported limits. */
#define R300_TX_ENABLE 0x4104
# define R300_TX_ENABLE_0 (1 << 0)
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 498b19b1d641..1f7d2ab8c4fc 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -90,9 +90,10 @@
* 1.19- Add support for gart table in FB memory and PCIE r300
* 1.20- Add support for r300 texrect
* 1.21- Add support for card type getparam
+ * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 21
+#define DRIVER_MINOR 22
#define DRIVER_PATCHLEVEL 0
/*
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 57539d8f9f7c..09dc4b01232c 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -150,17 +150,6 @@ static void rs_wait_until_sent(struct tty_struct *, int);
/* Standard COM flags (except for COM4, because of the 8514 problem) */
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-
static inline int serial_paranoia_check(struct esp_struct *info,
char *name, const char *routine)
{
@@ -1267,7 +1256,7 @@ static int rs_write(struct tty_struct * tty,
if (serial_paranoia_check(info, tty->name, "rs_write"))
return 0;
- if (!tty || !info->xmit_buf || !tmp_buf)
+ if (!tty || !info->xmit_buf)
return 0;
while (1) {
@@ -2291,11 +2280,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
tty->driver_data = info;
info->tty = tty;
- if (!tmp_buf) {
- tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL);
- if (!tmp_buf)
- return -ENOMEM;
- }
+ spin_unlock_irqrestore(&info->lock, flags);
/*
* Start up serial port
@@ -2602,9 +2587,6 @@ static void __exit espserial_exit(void)
free_pages((unsigned long)dma_buffer,
get_order(DMA_BUFFER_SZ));
- if (tmp_buf)
- free_page((unsigned long)tmp_buf);
-
while (free_pio_buf) {
pio_buf = free_pio_buf->next;
kfree(free_pio_buf);
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 66a2fee06eb9..ef140ebde117 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -956,22 +956,18 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
}
} else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
struct acpi_resource_extended_irq *irqp;
- int i;
+ int i, irq;
irqp = &res->data.extended_irq;
- if (irqp->interrupt_count > 0) {
- hdp->hd_nirqs = irqp->interrupt_count;
-
- for (i = 0; i < hdp->hd_nirqs; i++) {
- int rc =
- acpi_register_gsi(irqp->interrupts[i],
- irqp->triggering,
- irqp->polarity);
- if (rc < 0)
- return AE_ERROR;
- hdp->hd_irq[i] = rc;
- }
+ for (i = 0; i < irqp->interrupt_count; i++) {
+ irq = acpi_register_gsi(irqp->interrupts[i],
+ irqp->triggering, irqp->polarity);
+ if (irq < 0)
+ return AE_ERROR;
+
+ hdp->hd_irq[hdp->hd_nirqs] = irq;
+ hdp->hd_nirqs++;
}
}
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 1994a92d4733..f65b2e14a485 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -335,6 +335,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
} /* else count == 0 */
tty->driver_data = hp;
+ tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */
+
hp->tty = tty;
/* Save for request_irq outside of spin_lock. */
irq = hp->irq;
@@ -633,9 +635,6 @@ static int hvc_poll(struct hvc_struct *hp)
tty_insert_flip_char(tty, buf[i], 0);
}
- if (count)
- tty_schedule_flip(tty);
-
/*
* Account for the total amount read in one loop, and if above
* 64 bytes, we do a quick schedule loop to let the tty grok
@@ -656,6 +655,9 @@ static int hvc_poll(struct hvc_struct *hp)
bail:
spin_unlock_irqrestore(&hp->lock, flags);
+ if (read_total)
+ tty_flip_buffer_push(tty);
+
return poll_mask;
}
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index b3bc2e37e616..29dc87e59020 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -131,7 +131,9 @@ enum {
rng_hw_none,
rng_hw_intel,
rng_hw_amd,
+#ifdef __i386__
rng_hw_via,
+#endif
rng_hw_geode,
};
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index c92378121b4c..1b05fa688996 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -675,7 +675,7 @@ static int __init mmtimer_init(void)
cnodeid_t node, maxn = -1;
if (!ia64_platform_is("sn2"))
- return -1;
+ return 0;
/*
* Sanity check the cycles/sec variable
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 649677b5dc36..5fdf18515433 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -13,11 +13,12 @@
*
* (C) 2000,2001,2002,2003,2004 Omnikey AG
*
- * (C) 2005 Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
* - Adhere to Kernel CodingStyle
* - Port to 2.6.13 "new" style PCMCIA
* - Check for copy_{from,to}_user return values
* - Use nonseekable_open()
+ * - add class interface for udev device creation
*
* All rights reserved. Licensed under dual BSD/GPL license.
*/
@@ -56,7 +57,7 @@ module_param(pc_debug, int, 0600);
#else
#define DEBUGP(n, rdr, x, args...)
#endif
-static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte";
+static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
#define T_1SEC (HZ)
#define T_10MSEC msecs_to_jiffies(10)
@@ -156,6 +157,7 @@ struct cm4000_dev {
/*queue*/ 4*sizeof(wait_queue_head_t))
static dev_link_t *dev_table[CM4000_MAX_DEV];
+static struct class *cmm_class;
/* This table doesn't use spaces after the comma between fields and thus
* violates CodingStyle. However, I don't really think wrapping it around will
@@ -1937,6 +1939,9 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
cm4000_config(link, i);
+ class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
+ "cmm%d", i);
+
return 0;
}
@@ -1962,6 +1967,8 @@ static void cm4000_detach(struct pcmcia_device *p_dev)
dev_table[devno] = NULL;
kfree(dev);
+ class_device_destroy(cmm_class, MKDEV(major, devno));
+
return;
}
@@ -1995,8 +2002,18 @@ static struct pcmcia_driver cm4000_driver = {
static int __init cmm_init(void)
{
+ int rc;
+
printk(KERN_INFO "%s\n", version);
- pcmcia_register_driver(&cm4000_driver);
+
+ cmm_class = class_create(THIS_MODULE, "cardman_4000");
+ if (!cmm_class)
+ return -1;
+
+ rc = pcmcia_register_driver(&cm4000_driver);
+ if (rc < 0)
+ return rc;
+
major = register_chrdev(0, DEVICE_NAME, &cm4000_fops);
if (major < 0) {
printk(KERN_WARNING MODULE_NAME
@@ -2012,6 +2029,7 @@ static void __exit cmm_exit(void)
printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&cm4000_driver);
unregister_chrdev(major, DEVICE_NAME);
+ class_destroy(cmm_class);
};
module_init(cmm_init);
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 46eb371bf17e..466e33bab029 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -3,12 +3,13 @@
*
* (c) 2000-2004 Omnikey AG (http://www.omnikey.com/)
*
- * (C) 2005 Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
* - add support for poll()
* - driver cleanup
* - add waitqueues
* - adhere to linux kernel coding style and policies
* - support 2.6.13 "new style" pcmcia interface
+ * - add class interface for udev device creation
*
* The device basically is a USB CCID compliant device that has been
* attached to an I/O-Mapped FIFO.
@@ -53,7 +54,7 @@ module_param(pc_debug, int, 0600);
#endif
static char *version =
-"OMNIKEY CardMan 4040 v1.1.0gm4 - All bugs added by Harald Welte";
+"OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte";
#define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ)
#define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ)
@@ -67,6 +68,7 @@ static char *version =
static void reader_release(dev_link_t *link);
static int major;
+static struct class *cmx_class;
#define BS_READABLE 0x01
#define BS_WRITABLE 0x02
@@ -696,6 +698,9 @@ static int reader_attach(struct pcmcia_device *p_dev)
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
reader_config(link, i);
+ class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
+ "cmx%d", i);
+
return 0;
}
@@ -721,6 +726,8 @@ static void reader_detach(struct pcmcia_device *p_dev)
dev_table[devno] = NULL;
kfree(dev);
+ class_device_destroy(cmx_class, MKDEV(major, devno));
+
return;
}
@@ -755,8 +762,17 @@ static struct pcmcia_driver reader_driver = {
static int __init cm4040_init(void)
{
+ int rc;
+
printk(KERN_INFO "%s\n", version);
- pcmcia_register_driver(&reader_driver);
+ cmx_class = class_create(THIS_MODULE, "cardman_4040");
+ if (!cmx_class)
+ return -1;
+
+ rc = pcmcia_register_driver(&reader_driver);
+ if (rc < 0)
+ return rc;
+
major = register_chrdev(0, DEVICE_NAME, &reader_fops);
if (major < 0) {
printk(KERN_WARNING MODULE_NAME
@@ -771,6 +787,7 @@ static void __exit cm4040_exit(void)
printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&reader_driver);
unregister_chrdev(major, DEVICE_NAME);
+ class_destroy(cmx_class);
}
module_init(cm4040_init);
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 80a5b840e22f..fee68cc895f8 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -103,6 +103,7 @@
#include <linux/serial.h>
#include <linux/generic_serial.h>
+#include <linux/tty_flip.h>
#include "ser_a2232.h"
#include "ser_a2232fw.h"
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index c2490e270f1f..a6b4f02bdceb 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1095,17 +1095,17 @@ static inline void sx_receive_chars (struct sx_port *port)
sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
+ /* Don't copy past the end of the hardware receive buffer */
+ if (rx_op + c > 0x100) c = 0x100 - rx_op;
+
+ sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
+
/* Don't copy more bytes than there is room for in the buffer */
c = tty_prepare_flip_string(tty, &rp, c);
sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
- /* Don't copy past the end of the hardware receive buffer */
- if (rx_op + c > 0x100) c = 0x100 - rx_op;
-
- sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
/* If for one reason or another, we can't copy more data, we're done! */
if (c == 0) break;
@@ -2173,15 +2173,17 @@ static int probe_si (struct sx_board *board)
if ( IS_SI1_BOARD(board)) {
/* This should be an SI1 board, which has this
location writable... */
- if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
func_exit ();
return 0;
+ }
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
- if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) {
func_exit ();
return 0;
+ }
}
/* Now we're pretty much convinced that there is an SI board here,
@@ -2192,15 +2194,17 @@ static int probe_si (struct sx_board *board)
if ( IS_SI1_BOARD(board)) {
/* This should be an SI1 board, which has this
location writable... */
- if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
func_exit();
return 0;
+ }
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
- if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) {
func_exit ();
return 0;
+ }
}
printheader ();
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index a85a60a93deb..b046390cd256 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -306,7 +306,7 @@ struct slgt_info {
int tx_active;
unsigned char signals; /* serial signal states */
- unsigned int init_error; /* initialization error */
+ int init_error; /* initialization error */
unsigned char *tx_buf;
int tx_count;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5765f672e853..d58f82318853 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -243,7 +243,7 @@ static struct sysrq_key_op sysrq_term_op = {
static void moom_callback(void *ignored)
{
- out_of_memory(GFP_KERNEL, 0);
+ out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0);
}
static DECLARE_WORK(moom_work, moom_callback, NULL);
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 41a94bc79f67..eb2eb3e12d6a 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -250,12 +250,17 @@ tipar_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode) - TIPAR_MINOR;
- if (minor > tp_count - 1)
+ if (tp_count == 0 || minor > tp_count - 1)
return -ENXIO;
if (test_and_set_bit(minor, &opened))
return -EBUSY;
+ if (!table[minor].dev) {
+ printk(KERN_ERR "%s: NULL device for minor %u\n",
+ __FUNCTION__, minor);
+ return -ENXIO;
+ }
parport_claim_or_block(table[minor].dev);
init_ti_parallel(minor);
parport_release(table[minor].dev);
@@ -510,16 +515,20 @@ tipar_init_module(void)
err = PTR_ERR(tipar_class);
goto out_chrdev;
}
- if (parport_register_driver(&tipar_driver)) {
+ if (parport_register_driver(&tipar_driver) || tp_count == 0) {
printk(KERN_ERR "tipar: unable to register with parport\n");
err = -EIO;
- goto out;
+ goto out_class;
}
err = 0;
goto out;
+out_class:
+ class_destroy(tipar_class);
+
out_chrdev:
+ devfs_remove("ticables/par");
unregister_chrdev(TIPAR_MAJOR, "tipar");
out:
return err;
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index ec7590951af5..24095f6ee6da 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -33,6 +33,7 @@
static int TPM_INF_DATA;
static int TPM_INF_ADDR;
static int TPM_INF_BASE;
+static int TPM_INF_ADDR_LEN;
static int TPM_INF_PORT_LEN;
/* TPM header definitions */
@@ -195,6 +196,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
int i;
int ret;
u32 size = 0;
+ number_of_wtx = 0;
recv_begin:
/* start receiving header */
@@ -378,24 +380,35 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
!(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
TPM_INF_ADDR = pnp_port_start(dev, 0);
+ TPM_INF_ADDR_LEN = pnp_port_len(dev, 0);
TPM_INF_DATA = (TPM_INF_ADDR + 1);
TPM_INF_BASE = pnp_port_start(dev, 1);
TPM_INF_PORT_LEN = pnp_port_len(dev, 1);
- if (!TPM_INF_PORT_LEN)
- return -EINVAL;
+ if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) {
+ rc = -EINVAL;
+ goto err_last;
+ }
dev_info(&dev->dev, "Found %s with ID %s\n",
dev->name, dev_id->id);
- if (!((TPM_INF_BASE >> 8) & 0xff))
- return -EINVAL;
+ if (!((TPM_INF_BASE >> 8) & 0xff)) {
+ rc = -EINVAL;
+ goto err_last;
+ }
/* publish my base address and request region */
tpm_inf.base = TPM_INF_BASE;
if (request_region
(tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_last;
+ }
+ if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
+ "tpm_infineon0") == NULL) {
+ rc = -EINVAL;
+ goto err_last;
}
} else {
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_last;
}
/* query chip for its vendor, its version number a.s.o. */
@@ -443,8 +456,8 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
dev_err(&dev->dev,
"Could not set IO-ports to 0x%lx\n",
tpm_inf.base);
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
- return -EIO;
+ rc = -EIO;
+ goto err_release_region;
}
/* activate register */
@@ -471,14 +484,21 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
rc = tpm_register_hardware(&dev->dev, &tpm_inf);
if (rc < 0) {
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_release_region;
}
return 0;
} else {
- dev_info(&dev->dev, "No Infineon TPM found!\n");
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_release_region;
}
+
+err_release_region:
+ release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+
+err_last:
+ return rc;
}
static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
@@ -518,5 +538,5 @@ module_exit(cleanup_inf);
MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.6");
+MODULE_VERSION("1.7");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 076e07c1da38..53d3d066554e 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -268,6 +268,8 @@ static struct tty_buffer *tty_buffer_alloc(size_t size)
p->size = size;
p->next = NULL;
p->active = 0;
+ p->commit = 0;
+ p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
/* printk("Flip create %p\n", p); */
@@ -298,8 +300,10 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
*tbh = t->next;
t->next = NULL;
t->used = 0;
+ t->commit = 0;
+ t->read = 0;
/* DEBUG ONLY */
- memset(t->data, '*', size);
+/* memset(t->data, '*', size); */
/* printk("Flip recycle %p\n", t); */
return t;
}
@@ -335,6 +339,7 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
if (b != NULL) {
b->next = n;
b->active = 0;
+ b->commit = b->used;
} else
tty->buf.head = n;
tty->buf.tail = n;
@@ -1836,7 +1841,6 @@ static void release_dev(struct file * filp)
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
- up(&tty_sem);
do_sleep = 0;
if (tty_closing) {
@@ -1864,6 +1868,7 @@ static void release_dev(struct file * filp)
printk(KERN_WARNING "release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
+ up(&tty_sem);
schedule();
}
@@ -1872,8 +1877,6 @@ static void release_dev(struct file * filp)
* both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing.
*/
-
- down(&tty_sem);
if (pty_master) {
if (--o_tty->count < 0) {
printk(KERN_WARNING "release_dev: bad pty slave count "
@@ -1887,7 +1890,6 @@ static void release_dev(struct file * filp)
tty->count, tty_name(tty, buf));
tty->count = 0;
}
- up(&tty_sem);
/*
* We've decremented tty->count, so we need to remove this file
@@ -1932,6 +1934,8 @@ static void release_dev(struct file * filp)
read_unlock(&tasklist_lock);
}
+ up(&tty_sem);
+
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing))
return;
@@ -2752,6 +2756,9 @@ static void flush_to_ldisc(void *private_)
unsigned long flags;
struct tty_ldisc *disc;
struct tty_buffer *tbuf;
+ int count;
+ char *char_buf;
+ unsigned char *flag_buf;
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
@@ -2765,16 +2772,20 @@ static void flush_to_ldisc(void *private_)
goto out;
}
spin_lock_irqsave(&tty->buf.lock, flags);
- while((tbuf = tty->buf.head) != NULL && !tbuf->active) {
+ while((tbuf = tty->buf.head) != NULL) {
+ while ((count = tbuf->commit - tbuf->read) != 0) {
+ char_buf = tbuf->char_buf_ptr + tbuf->read;
+ flag_buf = tbuf->flag_buf_ptr + tbuf->read;
+ tbuf->read += count;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ disc->receive_buf(tty, char_buf, flag_buf, count);
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ }
+ if (tbuf->active)
+ break;
tty->buf.head = tbuf->next;
if (tty->buf.head == NULL)
tty->buf.tail = NULL;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
- disc->receive_buf(tty, tbuf->char_buf_ptr,
- tbuf->flag_buf_ptr,
- tbuf->used);
- spin_lock_irqsave(&tty->buf.lock, flags);
tty_buffer_free(tty, tbuf);
}
spin_unlock_irqrestore(&tty->buf.lock, flags);
@@ -2871,8 +2882,10 @@ void tty_flip_buffer_push(struct tty_struct *tty)
{
unsigned long flags;
spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
+ if (tty->buf.tail != NULL) {
tty->buf.tail->active = 0;
+ tty->buf.tail->commit = tty->buf.tail->used;
+ }
spin_unlock_irqrestore(&tty->buf.lock, flags);
if (tty->low_latency)
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 37c9e13ad3ac..8d6b249ad66b 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -49,29 +49,37 @@
* More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/config.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/reboot.h>
+#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/delay.h> /* For mdelay function */
+#include <linux/timer.h> /* For timer related operations */
+#include <linux/jiffies.h> /* For jiffies stuff */
+#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h> /* For the watchdog specific items */
+#include <linux/notifier.h> /* For notifier support */
+#include <linux/reboot.h> /* For reboot_notifier stuff */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/fs.h> /* For file operations */
+#include <linux/ioport.h> /* For io-port access */
+#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
#include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/slab.h> /* For kmalloc */
-#define WD_VER "1.16 (06/12/2004)"
-#define PFX "pcwd: "
+#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
+#include <asm/io.h> /* For inb/outb/... */
+
+/* Module and version information */
+#define WATCHDOG_VERSION "1.16"
+#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
+#define WATCHDOG_NAME "pcwd"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
+#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")"
/*
* It should be noted that PCWD_REVISION_B was removed because A and B
@@ -85,36 +93,38 @@
/*
* These are the defines that describe the control status bits for the
- * PC Watchdog card, revision A.
- */
+ * PCI-PC Watchdog card.
+*/
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
#define WD_WDRST 0x01 /* Previously reset state */
#define WD_T110 0x02 /* Temperature overheat sense */
#define WD_HRTBT 0x04 /* Heartbeat sense */
#define WD_RLY2 0x08 /* External relay triggered */
#define WD_SRLY2 0x80 /* Software external relay triggered */
-
-/*
- * These are the defines that describe the control status bits for the
- * PC Watchdog card, revision C.
- */
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
+/* Port 2 : Control Status #2 */
+#define WD_WDIS 0x10 /* Watchdog Disabled */
+#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */
+#define WD_SSEL 0x40 /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */
+#define WD_WCMD 0x80 /* Watchdog Command Mode */
/* max. time we give an ISA watchdog card to process a command */
/* 500ms for each 4 bit response (according to spec.) */
#define ISA_COMMAND_TIMEOUT 1000
/* Watchdog's internal commands */
-#define CMD_ISA_IDLE 0x00
-#define CMD_ISA_VERSION_INTEGER 0x01
-#define CMD_ISA_VERSION_TENTH 0x02
-#define CMD_ISA_VERSION_HUNDRETH 0x03
-#define CMD_ISA_VERSION_MINOR 0x04
-#define CMD_ISA_SWITCH_SETTINGS 0x05
-#define CMD_ISA_DELAY_TIME_2SECS 0x0A
-#define CMD_ISA_DELAY_TIME_4SECS 0x0B
-#define CMD_ISA_DELAY_TIME_8SECS 0x0C
+#define CMD_ISA_IDLE 0x00
+#define CMD_ISA_VERSION_INTEGER 0x01
+#define CMD_ISA_VERSION_TENTH 0x02
+#define CMD_ISA_VERSION_HUNDRETH 0x03
+#define CMD_ISA_VERSION_MINOR 0x04
+#define CMD_ISA_SWITCH_SETTINGS 0x05
+#define CMD_ISA_DELAY_TIME_2SECS 0x0A
+#define CMD_ISA_DELAY_TIME_4SECS 0x0B
+#define CMD_ISA_DELAY_TIME_8SECS 0x0C
/*
* We are using an kernel timer to do the pinging of the watchdog
@@ -130,15 +140,17 @@ static int cards_found;
/* internal variables */
static atomic_t open_allowed = ATOMIC_INIT(1);
static char expect_close;
-static struct timer_list timer;
-static unsigned long next_heartbeat;
static int temp_panic;
-static int revision; /* The card's revision */
-static int supports_temp; /* Wether or not the card has a temperature device */
-static int command_mode; /* Wether or not the card is in command mode */
-static int initial_status; /* The card's boot status */
-static int current_readport; /* The cards I/O address */
-static spinlock_t io_lock;
+static struct { /* this is private data for each ISA-PC watchdog card */
+ int revision; /* The card's revision */
+ int supports_temp; /* Wether or not the card has a temperature device */
+ int command_mode; /* Wether or not the card is in command mode */
+ int boot_status; /* The card's boot status */
+ int io_addr; /* The cards I/O address */
+ spinlock_t io_lock; /* the lock for io operations */
+ struct timer_list timer; /* The timer that pings the watchdog */
+ unsigned long next_heartbeat; /* the next_heartbeat for the timer */
+} pcwd_private;
/* module parameters */
#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */
@@ -161,14 +173,14 @@ static int send_isa_command(int cmd)
int port0, last_port0; /* Double read for stabilising */
/* The WCMD bit must be 1 and the command is only 4 bits in size */
- control_status = (cmd & 0x0F) | 0x80;
- outb_p(control_status, current_readport + 2);
+ control_status = (cmd & 0x0F) | WD_WCMD;
+ outb_p(control_status, pcwd_private.io_addr + 2);
udelay(ISA_COMMAND_TIMEOUT);
- port0 = inb_p(current_readport);
+ port0 = inb_p(pcwd_private.io_addr);
for (i = 0; i < 25; ++i) {
last_port0 = port0;
- port0 = inb_p(current_readport);
+ port0 = inb_p(pcwd_private.io_addr);
if (port0 == last_port0)
break; /* Data is stable */
@@ -184,7 +196,7 @@ static int set_command_mode(void)
int i, found=0, count=0;
/* Set the card into command mode */
- spin_lock(&io_lock);
+ spin_lock(&pcwd_private.io_lock);
while ((!found) && (count < 3)) {
i = send_isa_command(CMD_ISA_IDLE);
@@ -192,15 +204,15 @@ static int set_command_mode(void)
found = 1;
else if (i == 0xF3) {
/* Card does not like what we've done to it */
- outb_p(0x00, current_readport + 2);
+ outb_p(0x00, pcwd_private.io_addr + 2);
udelay(1200); /* Spec says wait 1ms */
- outb_p(0x00, current_readport + 2);
+ outb_p(0x00, pcwd_private.io_addr + 2);
udelay(ISA_COMMAND_TIMEOUT);
}
count++;
}
- spin_unlock(&io_lock);
- command_mode = found;
+ spin_unlock(&pcwd_private.io_lock);
+ pcwd_private.command_mode = found;
return(found);
}
@@ -208,12 +220,95 @@ static int set_command_mode(void)
static void unset_command_mode(void)
{
/* Set the card into normal mode */
- spin_lock(&io_lock);
- outb_p(0x00, current_readport + 2);
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0x00, pcwd_private.io_addr + 2);
udelay(ISA_COMMAND_TIMEOUT);
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
+
+ pcwd_private.command_mode = 0;
+}
+
+static inline void pcwd_check_temperature_support(void)
+{
+ if (inb(pcwd_private.io_addr) != 0xF0)
+ pcwd_private.supports_temp = 1;
+}
+
+static inline char *get_firmware(void)
+{
+ int one, ten, hund, minor;
+ char *ret;
+
+ ret = kmalloc(6, GFP_KERNEL);
+ if(ret == NULL)
+ return NULL;
+
+ if (set_command_mode()) {
+ one = send_isa_command(CMD_ISA_VERSION_INTEGER);
+ ten = send_isa_command(CMD_ISA_VERSION_TENTH);
+ hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
+ minor = send_isa_command(CMD_ISA_VERSION_MINOR);
+ sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+ }
+ else
+ sprintf(ret, "ERROR");
+
+ unset_command_mode();
+ return(ret);
+}
+
+static inline int pcwd_get_option_switches(void)
+{
+ int option_switches=0;
+
+ if (set_command_mode()) {
+ /* Get switch settings */
+ option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
+ }
+
+ unset_command_mode();
+ return(option_switches);
+}
+
+static void pcwd_show_card_info(void)
+{
+ char *firmware;
+ int option_switches;
+
+ /* Get some extra info from the hardware (in command/debug/diag mode) */
+ if (pcwd_private.revision == PCWD_REVISION_A)
+ printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
+ else if (pcwd_private.revision == PCWD_REVISION_C) {
+ firmware = get_firmware();
+ printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
+ pcwd_private.io_addr, firmware);
+ kfree(firmware);
+ option_switches = pcwd_get_option_switches();
+ printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+ option_switches,
+ ((option_switches & 0x10) ? "ON" : "OFF"),
+ ((option_switches & 0x08) ? "ON" : "OFF"));
+
+ /* Reprogram internal heartbeat to 2 seconds */
+ if (set_command_mode()) {
+ send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
+ unset_command_mode();
+ }
+ }
+
+ if (pcwd_private.supports_temp)
+ printk(KERN_INFO PFX "Temperature Option Detected\n");
+
+ if (pcwd_private.boot_status & WDIOF_CARDRESET)
+ printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
+
+ if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
+ printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
+ printk(KERN_EMERG PFX "CPU Overheat\n");
+ }
- command_mode = 0;
+ if (pcwd_private.boot_status == 0)
+ printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
}
static void pcwd_timer_ping(unsigned long data)
@@ -222,25 +317,25 @@ static void pcwd_timer_ping(unsigned long data)
/* If we got a heartbeat pulse within the WDT_INTERVAL
* we agree to ping the WDT */
- if(time_before(jiffies, next_heartbeat)) {
+ if(time_before(jiffies, pcwd_private.next_heartbeat)) {
/* Ping the watchdog */
- spin_lock(&io_lock);
- if (revision == PCWD_REVISION_A) {
+ spin_lock(&pcwd_private.io_lock);
+ if (pcwd_private.revision == PCWD_REVISION_A) {
/* Rev A cards are reset by setting the WD_WDRST bit in register 1 */
- wdrst_stat = inb_p(current_readport);
+ wdrst_stat = inb_p(pcwd_private.io_addr);
wdrst_stat &= 0x0F;
wdrst_stat |= WD_WDRST;
- outb_p(wdrst_stat, current_readport + 1);
+ outb_p(wdrst_stat, pcwd_private.io_addr + 1);
} else {
/* Re-trigger watchdog by writing to port 0 */
- outb_p(0x00, current_readport);
+ outb_p(0x00, pcwd_private.io_addr);
}
/* Re-set the timer interval */
- mod_timer(&timer, jiffies + WDT_INTERVAL);
+ mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
} else {
printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
}
@@ -250,19 +345,19 @@ static int pcwd_start(void)
{
int stat_reg;
- next_heartbeat = jiffies + (heartbeat * HZ);
+ pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
/* Start the timer */
- mod_timer(&timer, jiffies + WDT_INTERVAL);
+ mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
/* Enable the port */
- if (revision == PCWD_REVISION_C) {
- spin_lock(&io_lock);
- outb_p(0x00, current_readport + 3);
+ if (pcwd_private.revision == PCWD_REVISION_C) {
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0x00, pcwd_private.io_addr + 3);
udelay(ISA_COMMAND_TIMEOUT);
- stat_reg = inb_p(current_readport + 2);
- spin_unlock(&io_lock);
- if (stat_reg & 0x10) {
+ stat_reg = inb_p(pcwd_private.io_addr + 2);
+ spin_unlock(&pcwd_private.io_lock);
+ if (stat_reg & WD_WDIS) {
printk(KERN_INFO PFX "Could not start watchdog\n");
return -EIO;
}
@@ -275,18 +370,18 @@ static int pcwd_stop(void)
int stat_reg;
/* Stop the timer */
- del_timer(&timer);
+ del_timer(&pcwd_private.timer);
/* Disable the board */
- if (revision == PCWD_REVISION_C) {
- spin_lock(&io_lock);
- outb_p(0xA5, current_readport + 3);
+ if (pcwd_private.revision == PCWD_REVISION_C) {
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0xA5, pcwd_private.io_addr + 3);
udelay(ISA_COMMAND_TIMEOUT);
- outb_p(0xA5, current_readport + 3);
+ outb_p(0xA5, pcwd_private.io_addr + 3);
udelay(ISA_COMMAND_TIMEOUT);
- stat_reg = inb_p(current_readport + 2);
- spin_unlock(&io_lock);
- if ((stat_reg & 0x10) == 0) {
+ stat_reg = inb_p(pcwd_private.io_addr + 2);
+ spin_unlock(&pcwd_private.io_lock);
+ if ((stat_reg & WD_WDIS) == 0) {
printk(KERN_INFO PFX "Could not stop watchdog\n");
return -EIO;
}
@@ -297,7 +392,7 @@ static int pcwd_stop(void)
static int pcwd_keepalive(void)
{
/* user land ping */
- next_heartbeat = jiffies + (heartbeat * HZ);
+ pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
return 0;
}
@@ -315,23 +410,23 @@ static int pcwd_get_status(int *status)
int card_status;
*status=0;
- spin_lock(&io_lock);
- if (revision == PCWD_REVISION_A)
+ spin_lock(&pcwd_private.io_lock);
+ if (pcwd_private.revision == PCWD_REVISION_A)
/* Rev A cards return status information from
* the base register, which is used for the
* temperature in other cards. */
- card_status = inb(current_readport);
+ card_status = inb(pcwd_private.io_addr);
else {
/* Rev C cards return card status in the base
* address + 1 register. And use different bits
* to indicate a card initiated reset, and an
* over-temperature condition. And the reboot
* status can be reset. */
- card_status = inb(current_readport + 1);
+ card_status = inb(pcwd_private.io_addr + 1);
}
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
- if (revision == PCWD_REVISION_A) {
+ if (pcwd_private.revision == PCWD_REVISION_A) {
if (card_status & WD_WDRST)
*status |= WDIOF_CARDRESET;
@@ -360,10 +455,10 @@ static int pcwd_get_status(int *status)
static int pcwd_clear_status(void)
{
- if (revision == PCWD_REVISION_C) {
- spin_lock(&io_lock);
- outb_p(0x00, current_readport + 1); /* clear reset status */
- spin_unlock(&io_lock);
+ if (pcwd_private.revision == PCWD_REVISION_C) {
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+ spin_unlock(&pcwd_private.io_lock);
}
return 0;
}
@@ -371,20 +466,20 @@ static int pcwd_clear_status(void)
static int pcwd_get_temperature(int *temperature)
{
/* check that port 0 gives temperature info and no command results */
- if (command_mode)
+ if (pcwd_private.command_mode)
return -1;
*temperature = 0;
- if (!supports_temp)
+ if (!pcwd_private.supports_temp)
return -ENODEV;
/*
* Convert celsius to fahrenheit, since this was
* the decided 'standard' for this return value.
*/
- spin_lock(&io_lock);
- *temperature = ((inb(current_readport)) * 9 / 5) + 32;
- spin_unlock(&io_lock);
+ spin_lock(&pcwd_private.io_lock);
+ *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
+ spin_unlock(&pcwd_private.io_lock);
return 0;
}
@@ -425,7 +520,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return put_user(status, argp);
case WDIOC_GETBOOTSTATUS:
- return put_user(initial_status, argp);
+ return put_user(pcwd_private.boot_status, argp);
case WDIOC_GETTEMP:
if (pcwd_get_temperature(&temperature))
@@ -434,7 +529,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return put_user(temperature, argp);
case WDIOC_SETOPTIONS:
- if (revision == PCWD_REVISION_C)
+ if (pcwd_private.revision == PCWD_REVISION_C)
{
if(copy_from_user(&rv, argp, sizeof(int)))
return -EFAULT;
@@ -550,7 +645,7 @@ static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count,
static int pcwd_temp_open(struct inode *inode, struct file *file)
{
- if (!supports_temp)
+ if (!pcwd_private.supports_temp)
return -ENODEV;
return nonseekable_open(inode, file);
@@ -616,68 +711,24 @@ static struct notifier_block pcwd_notifier = {
* Init & exit routines
*/
-static inline void get_support(void)
-{
- if (inb(current_readport) != 0xF0)
- supports_temp = 1;
-}
-
static inline int get_revision(void)
{
int r = PCWD_REVISION_C;
- spin_lock(&io_lock);
+ spin_lock(&pcwd_private.io_lock);
/* REV A cards use only 2 io ports; test
* presumes a floating bus reads as 0xff. */
- if ((inb(current_readport + 2) == 0xFF) ||
- (inb(current_readport + 3) == 0xFF))
+ if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
+ (inb(pcwd_private.io_addr + 3) == 0xFF))
r=PCWD_REVISION_A;
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
return r;
}
-static inline char *get_firmware(void)
-{
- int one, ten, hund, minor;
- char *ret;
-
- ret = kmalloc(6, GFP_KERNEL);
- if(ret == NULL)
- return NULL;
-
- if (set_command_mode()) {
- one = send_isa_command(CMD_ISA_VERSION_INTEGER);
- ten = send_isa_command(CMD_ISA_VERSION_TENTH);
- hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
- minor = send_isa_command(CMD_ISA_VERSION_MINOR);
- sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
- }
- else
- sprintf(ret, "ERROR");
-
- unset_command_mode();
- return(ret);
-}
-
-static inline int get_option_switches(void)
-{
- int rv=0;
-
- if (set_command_mode()) {
- /* Get switch settings */
- rv = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
- }
-
- unset_command_mode();
- return(rv);
-}
-
static int __devinit pcwatchdog_init(int base_addr)
{
int ret;
- char *firmware;
- int option_switches;
cards_found++;
if (cards_found == 1)
@@ -692,104 +743,66 @@ static int __devinit pcwatchdog_init(int base_addr)
printk(KERN_ERR PFX "No I/O-Address for card detected\n");
return -ENODEV;
}
- current_readport = base_addr;
+ pcwd_private.io_addr = base_addr;
/* Check card's revision */
- revision = get_revision();
+ pcwd_private.revision = get_revision();
- if (!request_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
+ if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
- current_readport);
- current_readport = 0x0000;
+ pcwd_private.io_addr);
+ pcwd_private.io_addr = 0x0000;
return -EIO;
}
/* Initial variables */
- supports_temp = 0;
+ pcwd_private.supports_temp = 0;
temp_panic = 0;
- initial_status = 0x0000;
+ pcwd_private.boot_status = 0x0000;
/* get the boot_status */
- pcwd_get_status(&initial_status);
+ pcwd_get_status(&pcwd_private.boot_status);
/* clear the "card caused reboot" flag */
pcwd_clear_status();
- init_timer(&timer);
- timer.function = pcwd_timer_ping;
- timer.data = 0;
+ init_timer(&pcwd_private.timer);
+ pcwd_private.timer.function = pcwd_timer_ping;
+ pcwd_private.timer.data = 0;
/* Disable the board */
pcwd_stop();
/* Check whether or not the card supports the temperature device */
- get_support();
-
- /* Get some extra info from the hardware (in command/debug/diag mode) */
- if (revision == PCWD_REVISION_A)
- printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", current_readport);
- else if (revision == PCWD_REVISION_C) {
- firmware = get_firmware();
- printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
- current_readport, firmware);
- kfree(firmware);
- option_switches = get_option_switches();
- printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
- option_switches,
- ((option_switches & 0x10) ? "ON" : "OFF"),
- ((option_switches & 0x08) ? "ON" : "OFF"));
-
- /* Reprogram internal heartbeat to 2 seconds */
- if (set_command_mode()) {
- send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
- unset_command_mode();
- }
- } else {
- /* Should NEVER happen, unless get_revision() fails. */
- printk(KERN_INFO PFX "Unable to get revision\n");
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
- return -1;
- }
+ pcwd_check_temperature_support();
- if (supports_temp)
- printk(KERN_INFO PFX "Temperature Option Detected\n");
-
- if (initial_status & WDIOF_CARDRESET)
- printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
-
- if (initial_status & WDIOF_OVERHEAT) {
- printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
- printk(KERN_EMERG PFX "CPU Overheat\n");
- }
-
- if (initial_status == 0)
- printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+ /* Show info about the card itself */
+ pcwd_show_card_info();
/* Check that the heartbeat value is within it's range ; if not reset to the default */
- if (pcwd_set_heartbeat(heartbeat)) {
- pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
- printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
- WATCHDOG_HEARTBEAT);
+ if (pcwd_set_heartbeat(heartbeat)) {
+ pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
+ printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
+ WATCHDOG_HEARTBEAT);
}
ret = register_reboot_notifier(&pcwd_notifier);
if (ret) {
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
ret);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
return ret;
}
- if (supports_temp) {
+ if (pcwd_private.supports_temp) {
ret = misc_register(&temp_miscdev);
if (ret) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
TEMP_MINOR, ret);
unregister_reboot_notifier(&pcwd_notifier);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
return ret;
}
}
@@ -798,11 +811,11 @@ static int __devinit pcwatchdog_init(int base_addr)
if (ret) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
- if (supports_temp)
+ if (pcwd_private.supports_temp)
misc_deregister(&temp_miscdev);
unregister_reboot_notifier(&pcwd_notifier);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
return ret;
}
@@ -820,11 +833,12 @@ static void __devexit pcwatchdog_exit(void)
/* Deregister */
misc_deregister(&pcwd_miscdev);
- if (supports_temp)
+ if (pcwd_private.supports_temp)
misc_deregister(&temp_miscdev);
unregister_reboot_notifier(&pcwd_notifier);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
+ cards_found--;
}
/*
@@ -887,7 +901,7 @@ static int __init pcwd_init_module(void)
{
int i, found = 0;
- spin_lock_init(&io_lock);
+ spin_lock_init(&pcwd_private.io_lock);
for (i = 0; pcwd_ioports[i] != 0; i++) {
if (pcwd_checkcard(pcwd_ioports[i])) {
@@ -906,7 +920,7 @@ static int __init pcwd_init_module(void)
static void __exit pcwd_cleanup_module(void)
{
- if (current_readport)
+ if (pcwd_private.io_addr)
pcwatchdog_exit();
return;
}
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index b474ea52d6e8..522a9370db94 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -93,23 +93,25 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
{
int ret = -ENOIOCTLCMD;
int time;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
switch (cmd) {
case WDIOC_GETSUPPORT:
- ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+ ret = copy_to_user(argp, &ident,
sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETSTATUS:
- ret = put_user(0, (int __user *)arg);
+ ret = put_user(0, p);
break;
case WDIOC_GETBOOTSTATUS:
- ret = put_user(boot_status, (int __user *)arg);
+ ret = put_user(boot_status, p);
break;
case WDIOC_SETTIMEOUT:
- ret = get_user(time, (int __user *)arg);
+ ret = get_user(time, p);
if (ret)
break;
@@ -123,7 +125,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
/*fall through*/
case WDIOC_GETTIMEOUT:
- ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg);
+ ret = put_user(pre_margin / OSCR_FREQ, p);
break;
case WDIOC_KEEPALIVE:
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
index 7a4dfb95d087..837b1ec3ffe3 100644
--- a/drivers/char/watchdog/sbc_epx_c3.c
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -92,7 +92,7 @@ static int epx_c3_release(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t epx_c3_write(struct file *file, const char *data,
+static ssize_t epx_c3_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
/* Refresh the timer. */
@@ -105,6 +105,7 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int options, retval = -EINVAL;
+ int __user *argp = (void __user *)arg;
static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
@@ -114,20 +115,19 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case WDIOC_GETSUPPORT:
- if (copy_to_user((struct watchdog_info *)arg,
- &ident, sizeof(ident)))
+ if (copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
- return put_user(0,(int *)arg);
+ return put_user(0, argp);
case WDIOC_KEEPALIVE:
epx_c3_pet();
return 0;
case WDIOC_GETTIMEOUT:
- return put_user(WATCHDOG_TIMEOUT,(int *)arg);
- case WDIOC_SETOPTIONS: {
- if (get_user(options, (int *)arg))
+ return put_user(WATCHDOG_TIMEOUT, argp);
+ case WDIOC_SETOPTIONS:
+ if (get_user(options, argp))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
@@ -141,7 +141,6 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
}
return retval;
- }
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7a511479ae29..9582de1c9cad 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -35,8 +35,8 @@
* level driver of CPUFreq support, and its spinlock. This lock
* also protects the cpufreq_cpu_data array.
*/
-static struct cpufreq_driver *cpufreq_driver;
-static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+static struct cpufreq_driver *cpufreq_driver;
+static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
static DEFINE_SPINLOCK(cpufreq_driver_lock);
/* internal prototypes */
@@ -50,15 +50,15 @@ static void handle_update(void *data);
* changes to devices when the CPU clock speed changes.
* The mutex locks both lists.
*/
-static struct notifier_block *cpufreq_policy_notifier_list;
-static struct notifier_block *cpufreq_transition_notifier_list;
-static DECLARE_RWSEM (cpufreq_notifier_rwsem);
+static struct notifier_block *cpufreq_policy_notifier_list;
+static struct notifier_block *cpufreq_transition_notifier_list;
+static DECLARE_RWSEM (cpufreq_notifier_rwsem);
static LIST_HEAD(cpufreq_governor_list);
-static DEFINE_MUTEX (cpufreq_governor_mutex);
+static DEFINE_MUTEX (cpufreq_governor_mutex);
-struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{
struct cpufreq_policy *data;
unsigned long flags;
@@ -85,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
if (!kobject_get(&data->kobj))
goto err_out_put_module;
-
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
return data;
- err_out_put_module:
+err_out_put_module:
module_put(cpufreq_driver->owner);
- err_out_unlock:
+err_out_unlock:
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- err_out:
+err_out:
return NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
+
void cpufreq_cpu_put(struct cpufreq_policy *data)
{
kobject_put(&data->kobj);
@@ -229,44 +228,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) {
/**
- * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies
+ * on frequency transition.
*
- * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
- * twice on all CPU frequency changes that have external effects.
+ * This function calls the transition notifiers and the "adjust_jiffies"
+ * function. It is called twice on all CPU frequency changes that have
+ * external effects.
*/
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
{
+ struct cpufreq_policy *policy;
+
BUG_ON(irqs_disabled());
freqs->flags = cpufreq_driver->flags;
- dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new);
+ dprintk("notification %u of frequency transition to %u kHz\n",
+ state, freqs->new);
down_read(&cpufreq_notifier_rwsem);
+
+ policy = cpufreq_cpu_data[freqs->cpu];
switch (state) {
+
case CPUFREQ_PRECHANGE:
- /* detect if the driver reported a value as "old frequency" which
- * is not equal to what the cpufreq core thinks is "old frequency".
+ /* detect if the driver reported a value as "old frequency"
+ * which is not equal to what the cpufreq core thinks is
+ * "old frequency".
*/
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
- if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
- (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) &&
- (likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
- (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
- {
- dprintk(KERN_WARNING "Warning: CPU frequency is %u, "
- "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
- freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
+ if ((policy) && (policy->cpu == freqs->cpu) &&
+ (policy->cur) && (policy->cur != freqs->old)) {
+ dprintk(KERN_WARNING "Warning: CPU frequency is"
+ " %u, cpufreq assumed %u kHz.\n",
+ freqs->old, policy->cur);
+ freqs->old = policy->cur;
}
}
- notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
+ notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
+
case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
- notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
- if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
- (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)))
- cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
+ notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_POSTCHANGE, freqs);
+ if (likely(policy) && likely(policy->cpu == freqs->cpu))
+ policy->cur = freqs->new;
break;
}
up_read(&cpufreq_notifier_rwsem);
@@ -308,7 +316,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
return 0;
}
}
- out:
+out:
mutex_unlock(&cpufreq_governor_mutex);
}
return -EINVAL;
@@ -415,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
return -EINVAL;
ret = cpufreq_set_policy(&new_policy);
-
return ret ? ret : count;
}
@@ -446,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
goto out;
i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
}
- out:
+out:
i += sprintf(&buf[i], "\n");
return i;
}
@@ -789,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
kfree(data);
cpufreq_debug_enable_ratelimit();
-
return 0;
}
@@ -870,8 +876,7 @@ unsigned int cpufreq_get(unsigned int cpu)
ret = cpufreq_driver->get(cpu);
- if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS))
- {
+ if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
/* verify no discrepancy between actual and saved value exists */
if (unlikely(ret != policy->cur)) {
cpufreq_out_of_sync(cpu, policy->cur, ret);
@@ -881,7 +886,7 @@ unsigned int cpufreq_get(unsigned int cpu)
mutex_unlock(&policy->lock);
- out:
+out:
cpufreq_cpu_put(policy);
return (ret);
@@ -962,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
cpu_policy->cur = cur_freq;
}
- out:
+out:
cpufreq_cpu_put(cpu_policy);
return 0;
}
@@ -1169,7 +1174,6 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy);
-
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
@@ -1208,7 +1212,6 @@ int cpufreq_governor(unsigned int cpu, unsigned int event)
mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy);
-
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_governor);
@@ -1232,7 +1235,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
list_add(&governor->governor_list, &cpufreq_governor_list);
mutex_unlock(&cpufreq_governor_mutex);
-
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_register_governor);
@@ -1277,7 +1279,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
mutex_unlock(&cpu_policy->lock);
cpufreq_cpu_put(cpu_policy);
-
return 0;
}
EXPORT_SYMBOL(cpufreq_get_policy);
@@ -1291,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
policy->min, policy->max);
- memcpy(&policy->cpuinfo,
- &data->cpuinfo,
- sizeof(struct cpufreq_cpuinfo));
+ memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(policy);
@@ -1324,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
up_read(&cpufreq_notifier_rwsem);
- data->min = policy->min;
- data->max = policy->max;
+ data->min = policy->min;
+ data->max = policy->max;
dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max);
@@ -1362,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
}
- error_out:
+error_out:
cpufreq_debug_enable_ratelimit();
return ret;
}
@@ -1421,9 +1420,7 @@ int cpufreq_update_policy(unsigned int cpu)
mutex_lock(&data->lock);
dprintk("updating policy for CPU %u\n", cpu);
- memcpy(&policy,
- data,
- sizeof(struct cpufreq_policy));
+ memcpy(&policy, data, sizeof(struct cpufreq_policy));
policy.min = data->user_policy.min;
policy.max = data->user_policy.max;
policy.policy = data->user_policy.policy;
@@ -1433,8 +1430,13 @@ int cpufreq_update_policy(unsigned int cpu)
-> ask driver for current freq and notify governors about a change */
if (cpufreq_driver->get) {
policy.cur = cpufreq_driver->get(cpu);
- if (data->cur != policy.cur)
- cpufreq_out_of_sync(cpu, data->cur, policy.cur);
+ if (!data->cur) {
+ dprintk("Driver did not initialize current freq");
+ data->cur = policy.cur;
+ } else {
+ if (data->cur != policy.cur)
+ cpufreq_out_of_sync(cpu, data->cur, policy.cur);
+ }
}
ret = __cpufreq_set_policy(data, &policy);
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 64819aa7cac4..0c08c58252be 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -348,10 +348,10 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t
break;
case 32:
- E_KEY[4] = le32_to_cpu(in_key[4]);
- E_KEY[5] = le32_to_cpu(in_key[5]);
- E_KEY[6] = le32_to_cpu(in_key[6]);
- t = E_KEY[7] = le32_to_cpu(in_key[7]);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ E_KEY[5] = le32_to_cpu(key[5]);
+ E_KEY[6] = le32_to_cpu(key[6]);
+ t = E_KEY[7] = le32_to_cpu(key[7]);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index d94331c1e5b0..52f3eb45d2b9 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -6,18 +6,29 @@
# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
#
-menu 'EDAC - error detection and reporting (RAS)'
+menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)'
config EDAC
- tristate "EDAC core system error reporting"
- depends on X86
- default y
+ tristate "EDAC core system error reporting (EXPERIMENTAL)"
+ depends on X86 && EXPERIMENTAL
help
EDAC is designed to report errors in the core system.
These are low-level errors that are reported in the CPU or
supporting chipset: memory errors, cache errors, PCI errors,
thermal throttling, etc.. If unsure, select 'Y'.
+ If this code is reporting problems on your system, please
+ see the EDAC project web pages for more information at:
+
+ <http://bluesmoke.sourceforge.net/>
+
+ and:
+
+ <http://buttersideup.com/edacwiki>
+
+ There is also a mailing list for the EDAC project, which can
+ be found via the sourceforge page.
+
comment "Reporting subsystems"
depends on EDAC
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index b10ee4698b1d..9c205274c1cb 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -38,6 +38,12 @@
#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __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 */
int edac_debug_level = 1;
@@ -47,7 +53,7 @@ EXPORT_SYMBOL(edac_debug_level);
/* EDAC Controls, setable by module parameter, and sysfs */
static int log_ue = 1;
static int log_ce = 1;
-static int panic_on_ue = 1;
+static int panic_on_ue;
static int poll_msec = 1000;
static int check_pci_parity = 0; /* default YES check PCI parity */
@@ -77,6 +83,8 @@ static int pci_whitelist_count ;
/* START sysfs data and methods */
+#ifndef DISABLE_EDAC_SYSFS
+
static const char *mem_types[] = {
[MEM_EMPTY] = "Empty",
[MEM_RESERVED] = "Reserved",
@@ -132,11 +140,13 @@ static struct kobject edac_pci_kobj;
* /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)
{
@@ -207,7 +217,9 @@ struct memctrl_dev_attribute attr_##_name = { \
};
/* 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);
@@ -222,7 +234,6 @@ static struct memctrl_dev_attribute *memctrl_attr[] = {
&attr_log_ue,
&attr_log_ce,
&attr_poll_msec,
- &attr_mc_version,
NULL,
};
@@ -238,6 +249,7 @@ 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
@@ -248,6 +260,11 @@ 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;
@@ -280,6 +297,7 @@ static int edac_sysfs_memctrl_setup(void)
return err;
}
+#endif /* DISABLE_EDAC_SYSFS */
/*
* MC teardown:
@@ -287,6 +305,7 @@ 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 */
@@ -297,8 +316,11 @@ static void edac_sysfs_memctrl_teardown(void)
/* Unregister the 'edac' object */
sysdev_class_unregister(&edac_class);
+#endif /* DISABLE_EDAC_SYSFS */
}
+#ifndef DISABLE_EDAC_SYSFS
+
/*
* /sys/devices/system/edac/pci;
* data structures and methods
@@ -309,6 +331,8 @@ struct list_control {
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)
{
@@ -430,6 +454,7 @@ static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
return count;
}
+#endif
static ssize_t edac_pci_int_show(void *ptr, char *buffer)
{
int *value = ptr;
@@ -498,6 +523,7 @@ 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
@@ -520,6 +546,7 @@ EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
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);
@@ -531,8 +558,6 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
&edac_pci_attr_check_pci_parity,
&edac_pci_attr_panic_on_pci_parity,
&edac_pci_attr_pci_parity_count,
- &edac_pci_attr_pci_parity_whitelist,
- &edac_pci_attr_pci_parity_blacklist,
NULL,
};
@@ -548,11 +573,18 @@ 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;
@@ -576,16 +608,20 @@ 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("MC: " __FILE__ ": %s()\n", __func__);
kobject_unregister(&edac_pci_kobj);
kobject_put(&edac_pci_kobj);
+#endif
}
+#ifndef DISABLE_EDAC_SYSFS
+
/* EDAC sysfs CSROW data structures and methods */
/* Set of more detailed csrow<id> attribute show/store functions */
@@ -1039,6 +1075,8 @@ static struct kobj_type ktype_mci = {
.default_attrs = (struct attribute **) mci_attr,
};
+#endif /* DISABLE_EDAC_SYSFS */
+
#define EDAC_DEVICE_SYMLINK "device"
/*
@@ -1050,6 +1088,11 @@ 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;
@@ -1118,12 +1161,14 @@ fail:
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("MC: " __FILE__ ": %s()\n", __func__);
@@ -1140,6 +1185,7 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
kobject_unregister(&mci->edac_mci_kobj);
kobject_put(&mci->edac_mci_kobj);
+#endif /* DISABLE_EDAC_SYSFS */
}
/* END OF sysfs data and methods */
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index 009c08fe5d69..1991f94af753 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -159,7 +159,7 @@ enum i82875p_chips {
struct i82875p_pvt {
struct pci_dev *ovrfl_pdev;
- void *ovrfl_window;
+ void __iomem *ovrfl_window;
};
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 5c8943509cc1..66d03f242d3c 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -1053,7 +1053,7 @@ static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
int i;
fcmd = &_fcmd;
- memset(fcmd, 0, sizeof(fcmd));
+ memset(fcmd, 0, sizeof(fcp_cmnd));
FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
fch = &fcmd->fch;
FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 8ed6ddbb9c5d..4652512f7d1a 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -39,7 +39,7 @@
#include "dcdbas.h"
#define DRIVER_NAME "dcdbas"
-#define DRIVER_VERSION "5.6.0-1"
+#define DRIVER_VERSION "5.6.0-2"
#define DRIVER_DESCRIPTION "Dell Systems Management Base Driver"
static struct platform_device *dcdbas_pdev;
@@ -581,9 +581,13 @@ static int __init dcdbas_init(void)
*/
static void __exit dcdbas_exit(void)
{
- platform_device_unregister(dcdbas_pdev);
+ /*
+ * make sure functions that use dcdbas_pdev are called
+ * before platform_device_unregister
+ */
unregister_reboot_notifier(&dcdbas_reboot_nb);
smi_data_buf_free();
+ platform_device_unregister(dcdbas_pdev);
}
module_init(dcdbas_init);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c58295914365..7230d4e08196 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -113,6 +113,16 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module
will be called ds1621.
+config SENSORS_F71805F
+ tristate "Fintek F71805F/FG"
+ depends on HWMON && EXPERIMENTAL
+ help
+ If you say yes here you get support for hardware monitoring
+ features of the Fintek F71805F/FG chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called f71805f.
+
config SENSORS_FSCHER
tristate "FSC Hermes"
depends on HWMON && I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 06d4a1d14105..fbdb8d911a72 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
+obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
new file mode 100644
index 000000000000..e029e0a94ecc
--- /dev/null
+++ b/drivers/hwmon/f71805f.c
@@ -0,0 +1,908 @@
+/*
+ * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
+ * hardware monitoring features
+ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ *
+ * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
+ * complete hardware monitoring features: voltage, fan and temperature
+ * sensors, and manual and automatic fan speed control.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+static struct platform_device *pdev;
+
+#define DRVNAME "f71805f"
+
+/*
+ * Super-I/O constants and functions
+ */
+
+#define F71805F_LD_HWM 0x04
+
+#define SIO_REG_LDSEL 0x07 /* Logical device select */
+#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
+#define SIO_REG_DEVREV 0x22 /* Device revision */
+#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
+#define SIO_REG_ENABLE 0x30 /* Logical device enable */
+#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
+
+#define SIO_FINTEK_ID 0x1934
+#define SIO_F71805F_ID 0x0406
+
+static inline int
+superio_inb(int base, int reg)
+{
+ outb(reg, base);
+ return inb(base + 1);
+}
+
+static int
+superio_inw(int base, int reg)
+{
+ int val;
+ outb(reg++, base);
+ val = inb(base + 1) << 8;
+ outb(reg, base);
+ val |= inb(base + 1);
+ return val;
+}
+
+static inline void
+superio_select(int base, int ld)
+{
+ outb(SIO_REG_LDSEL, base);
+ outb(ld, base + 1);
+}
+
+static inline void
+superio_enter(int base)
+{
+ outb(0x87, base);
+ outb(0x87, base);
+}
+
+static inline void
+superio_exit(int base)
+{
+ outb(0xaa, base);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH 2
+#define ADDR_REG_OFFSET 0
+#define DATA_REG_OFFSET 1
+
+static struct resource f71805f_resource __initdata = {
+ .flags = IORESOURCE_IO,
+};
+
+/*
+ * Registers
+ */
+
+/* in nr from 0 to 8 (8-bit values) */
+#define F71805F_REG_IN(nr) (0x10 + (nr))
+#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
+#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
+/* fan nr from 0 to 2 (12-bit values, two registers) */
+#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
+#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
+#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
+/* temp nr from 0 to 2 (8-bit values) */
+#define F71805F_REG_TEMP(nr) (0x1B + (nr))
+#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
+#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
+#define F71805F_REG_TEMP_MODE 0x01
+
+#define F71805F_REG_START 0x00
+/* status nr from 0 to 2 */
+#define F71805F_REG_STATUS(nr) (0x36 + (nr))
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct f71805f_data {
+ unsigned short addr;
+ const char *name;
+ struct semaphore lock;
+ struct class_device *class_dev;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ unsigned long last_limits; /* In jiffies */
+
+ /* Register values */
+ u8 in[9];
+ u8 in_high[9];
+ u8 in_low[9];
+ u16 fan[3];
+ u16 fan_low[3];
+ u8 fan_enabled; /* Read once at init time */
+ u8 temp[3];
+ u8 temp_high[3];
+ u8 temp_hyst[3];
+ u8 temp_mode;
+ u8 alarms[3];
+};
+
+static inline long in_from_reg(u8 reg)
+{
+ return (reg * 8);
+}
+
+/* The 2 least significant bits are not used */
+static inline u8 in_to_reg(long val)
+{
+ if (val <= 0)
+ return 0;
+ if (val >= 2016)
+ return 0xfc;
+ return (((val + 16) / 32) << 2);
+}
+
+/* in0 is downscaled by a factor 2 internally */
+static inline long in0_from_reg(u8 reg)
+{
+ return (reg * 16);
+}
+
+static inline u8 in0_to_reg(long val)
+{
+ if (val <= 0)
+ return 0;
+ if (val >= 4032)
+ return 0xfc;
+ return (((val + 32) / 64) << 2);
+}
+
+/* The 4 most significant bits are not used */
+static inline long fan_from_reg(u16 reg)
+{
+ reg &= 0xfff;
+ if (!reg || reg == 0xfff)
+ return 0;
+ return (1500000 / reg);
+}
+
+static inline u16 fan_to_reg(long rpm)
+{
+ /* If the low limit is set below what the chip can measure,
+ store the largest possible 12-bit value in the registers,
+ so that no alarm will ever trigger. */
+ if (rpm < 367)
+ return 0xfff;
+ return (1500000 / rpm);
+}
+
+static inline long temp_from_reg(u8 reg)
+{
+ return (reg * 1000);
+}
+
+static inline u8 temp_to_reg(long val)
+{
+ if (val < 0)
+ val = 0;
+ else if (val > 1000 * 0xff)
+ val = 0xff;
+ return ((val + 500) / 1000);
+}
+
+/*
+ * Device I/O access
+ */
+
+static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
+{
+ u8 val;
+
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ val = inb(data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+
+ return val;
+}
+
+static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
+{
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ outb(val, data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+}
+
+/* It is important to read the MSB first, because doing so latches the
+ value of the LSB, so we are sure both bytes belong to the same value. */
+static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
+{
+ u16 val;
+
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ val = inb(data->addr + DATA_REG_OFFSET) << 8;
+ outb(++reg, data->addr + ADDR_REG_OFFSET);
+ val |= inb(data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+
+ return val;
+}
+
+static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
+{
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ outb(val >> 8, data->addr + DATA_REG_OFFSET);
+ outb(++reg, data->addr + ADDR_REG_OFFSET);
+ outb(val & 0xff, data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+}
+
+static struct f71805f_data *f71805f_update_device(struct device *dev)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ int nr;
+
+ down(&data->update_lock);
+
+ /* Limit registers cache is refreshed after 60 seconds */
+ if (time_after(jiffies, data->last_updated + 60 * HZ)
+ || !data->valid) {
+ for (nr = 0; nr < 9; nr++) {
+ data->in_high[nr] = f71805f_read8(data,
+ F71805F_REG_IN_HIGH(nr));
+ data->in_low[nr] = f71805f_read8(data,
+ F71805F_REG_IN_LOW(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ if (data->fan_enabled & (1 << nr))
+ data->fan_low[nr] = f71805f_read16(data,
+ F71805F_REG_FAN_LOW(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ data->temp_high[nr] = f71805f_read8(data,
+ F71805F_REG_TEMP_HIGH(nr));
+ data->temp_hyst[nr] = f71805f_read8(data,
+ F71805F_REG_TEMP_HYST(nr));
+ }
+ data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
+
+ data->last_limits = jiffies;
+ }
+
+ /* Measurement registers cache is refreshed after 1 second */
+ if (time_after(jiffies, data->last_updated + HZ)
+ || !data->valid) {
+ for (nr = 0; nr < 9; nr++) {
+ data->in[nr] = f71805f_read8(data,
+ F71805F_REG_IN(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ if (data->fan_enabled & (1 << nr))
+ data->fan[nr] = f71805f_read16(data,
+ F71805F_REG_FAN(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ data->temp[nr] = f71805f_read8(data,
+ F71805F_REG_TEMP(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ data->alarms[nr] = f71805f_read8(data,
+ F71805F_REG_STATUS(nr));
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+/*
+ * Sysfs interface
+ */
+
+static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
+}
+
+static ssize_t show_in0_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
+}
+
+static ssize_t show_in0_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
+}
+
+static ssize_t set_in0_max(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_high[0] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t set_in0_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_low[0] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
+static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
+static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_high[nr] = in_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_low[nr] = in_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_in(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, offset)
+
+sysfs_in(1);
+sysfs_in(2);
+sysfs_in(3);
+sysfs_in(4);
+sysfs_in(5);
+sysfs_in(6);
+sysfs_in(7);
+sysfs_in(8);
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->fan_low[nr] = fan_to_reg(val);
+ f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_fan(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, offset - 1)
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
+}
+
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
+}
+
+static ssize_t show_temp_type(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ /* 3 is diode, 4 is thermistor */
+ return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_high[nr] = temp_to_reg(val);
+ f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_hyst[nr] = temp_to_reg(val);
+ f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_temp(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
+ show_temp_hyst, set_temp_hyst, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \
+ show_temp_type, NULL, offset - 1)
+
+sysfs_temp(1);
+sysfs_temp(2);
+sysfs_temp(3);
+
+static ssize_t show_alarms_in(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->alarms[0] |
+ ((data->alarms[1] & 0x01) << 8));
+}
+
+static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
+}
+
+static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
+}
+
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
+static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
+static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", data->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+/*
+ * Device registration and initialization
+ */
+
+static void __devinit f71805f_init_device(struct f71805f_data *data)
+{
+ u8 reg;
+ int i;
+
+ reg = f71805f_read8(data, F71805F_REG_START);
+ if ((reg & 0x41) != 0x01) {
+ printk(KERN_DEBUG DRVNAME ": Starting monitoring "
+ "operations\n");
+ f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
+ }
+
+ /* Fan monitoring can be disabled. If it is, we won't be polling
+ the register values, and won't create the related sysfs files. */
+ for (i = 0; i < 3; i++) {
+ reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
+ if (!(reg & 0x80))
+ data->fan_enabled |= (1 << i);
+ }
+}
+
+static int __devinit f71805f_probe(struct platform_device *pdev)
+{
+ struct f71805f_data *data;
+ struct resource *res;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Out of memory\n");
+ goto exit;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ data->addr = res->start;
+ init_MUTEX(&data->lock);
+ data->name = "f71805f";
+ init_MUTEX(&data->update_lock);
+
+ platform_set_drvdata(pdev, data);
+
+ data->class_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+ goto exit_free;
+ }
+
+ /* Initialize the F71805F chip */
+ f71805f_init_device(data);
+
+ /* Register sysfs interface files */
+ device_create_file(&pdev->dev, &dev_attr_in0_input);
+ device_create_file(&pdev->dev, &dev_attr_in0_max);
+ device_create_file(&pdev->dev, &dev_attr_in0_min);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr);
+ if (data->fan_enabled & (1 << 0)) {
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan1_min.dev_attr);
+ }
+ if (data->fan_enabled & (1 << 1)) {
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan2_min.dev_attr);
+ }
+ if (data->fan_enabled & (1 << 2)) {
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan3_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan3_min.dev_attr);
+ }
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_max_hyst.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp2_max_hyst.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp3_max_hyst.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr);
+ device_create_file(&pdev->dev, &dev_attr_alarms_in);
+ device_create_file(&pdev->dev, &dev_attr_alarms_fan);
+ device_create_file(&pdev->dev, &dev_attr_alarms_temp);
+ device_create_file(&pdev->dev, &dev_attr_name);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int __devexit f71805f_remove(struct platform_device *pdev)
+{
+ struct f71805f_data *data = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ hwmon_device_unregister(data->class_dev);
+ kfree(data);
+
+ return 0;
+}
+
+static struct platform_driver f71805f_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = f71805f_probe,
+ .remove = __devexit_p(f71805f_remove),
+};
+
+static int __init f71805f_device_add(unsigned short address)
+{
+ int err;
+
+ pdev = platform_device_alloc(DRVNAME, address);
+ if (!pdev) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+ goto exit;
+ }
+
+ f71805f_resource.start = address;
+ f71805f_resource.end = address + REGION_LENGTH - 1;
+ f71805f_resource.name = pdev->name;
+ err = platform_device_add_resources(pdev, &f71805f_resource, 1);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device resource addition failed "
+ "(%d)\n", err);
+ goto exit_device_put;
+ }
+
+ err = platform_device_add(pdev);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+ err);
+ goto exit_device_put;
+ }
+
+ return 0;
+
+exit_device_put:
+ platform_device_put(pdev);
+exit:
+ return err;
+}
+
+static int __init f71805f_find(int sioaddr, unsigned short *address)
+{
+ int err = -ENODEV;
+ u16 devid;
+
+ superio_enter(sioaddr);
+
+ devid = superio_inw(sioaddr, SIO_REG_MANID);
+ if (devid != SIO_FINTEK_ID)
+ goto exit;
+
+ devid = superio_inw(sioaddr, SIO_REG_DEVID);
+ if (devid != SIO_F71805F_ID) {
+ printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
+ "skipping\n");
+ goto exit;
+ }
+
+ superio_select(sioaddr, F71805F_LD_HWM);
+ if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+ printk(KERN_WARNING DRVNAME ": Device not activated, "
+ "skipping\n");
+ goto exit;
+ }
+
+ *address = superio_inw(sioaddr, SIO_REG_ADDR);
+ if (*address == 0) {
+ printk(KERN_WARNING DRVNAME ": Base address not set, "
+ "skipping\n");
+ goto exit;
+ }
+
+ err = 0;
+ printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
+ *address, superio_inb(sioaddr, SIO_REG_DEVREV));
+
+exit:
+ superio_exit(sioaddr);
+ return err;
+}
+
+static int __init f71805f_init(void)
+{
+ int err;
+ unsigned short address;
+
+ if (f71805f_find(0x2e, &address)
+ && f71805f_find(0x4e, &address))
+ return -ENODEV;
+
+ err = platform_driver_register(&f71805f_driver);
+ if (err)
+ goto exit;
+
+ /* Sets global pdev as a side effect */
+ err = f71805f_device_add(address);
+ if (err)
+ goto exit_driver;
+
+ return 0;
+
+exit_driver:
+ platform_driver_unregister(&f71805f_driver);
+exit:
+ return err;
+}
+
+static void __exit f71805f_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&f71805f_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("F71805F hardware monitoring driver");
+
+module_init(f71805f_init);
+module_exit(f71805f_exit);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 0da7c9c508c3..d7a9401600bb 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -45,8 +45,7 @@
/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
- 0x2e, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
static unsigned short isa_address;
/* Insmod parameters */
@@ -830,6 +829,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(new_client)))
goto ERROR2;
+ if (!is_isa)
+ dev_info(&new_client->dev, "The I2C interface to IT87xxF "
+ "hardware monitoring chips is deprecated. Please "
+ "report if you still rely on it.\n");
+
/* Check PWM configuration */
enable_pwm_interface = it87_check_pwm(new_client);
@@ -1182,7 +1186,8 @@ static int __init sm_it87_init(void)
static void __exit sm_it87_exit(void)
{
- i2c_isa_del_driver(&it87_isa_driver);
+ if (isa_address)
+ i2c_isa_del_driver(&it87_isa_driver);
i2c_del_driver(&it87_driver);
}
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index a2f420d01fb7..df9e02aaa70a 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = {
/* In the temperature registers, the low 3 bits are not part of the
temperature values; they are the status bits. */
-static inline u16 LM77_TEMP_TO_REG(int temp)
+static inline s16 LM77_TEMP_TO_REG(int temp)
{
int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
- return (u16)((ntemp / 500) * 8);
+ return (ntemp / 500) * 8;
}
-static inline int LM77_TEMP_FROM_REG(u16 reg)
+static inline int LM77_TEMP_FROM_REG(s16 reg)
{
- return ((int)reg / 8) * 500;
+ return (reg / 8) * 500;
}
/* sysfs stuff */
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 3eb08f004c0f..271e9cb9532c 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -437,12 +437,12 @@ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
show_temp, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_max, set_temp_max, offset - 1); \
-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp_min, set_temp_min, offset - 1)
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
-static DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
define_temperature_sysfs(2);
define_temperature_sysfs(3);
@@ -451,7 +451,7 @@ define_temperature_sysfs(5);
define_temperature_sysfs(6);
#define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \
- &sensor_dev_attr_temp##id##_min.dev_attr, \
+ &sensor_dev_attr_temp##id##_max_hyst.dev_attr, \
&sensor_dev_attr_temp##id##_max.dev_attr }
#define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \
&sensor_dev_attr_in##id##_min.dev_attr, \
@@ -464,7 +464,7 @@ struct str_device_attr_table {
};
static struct str_device_attr_table cfg_info_temp[] = {
- { &dev_attr_temp1_input, &dev_attr_temp1_min, &dev_attr_temp1_max },
+ { &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max },
CFG_INFO_TEMP(2),
CFG_INFO_TEMP(3),
CFG_INFO_TEMP(4),
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 557114872f3c..64c1f8af5bb2 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -95,11 +95,16 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
(0x39)))
#define W83781D_REG_CONFIG 0x40
+
+/* Interrupt status (W83781D, AS99127F) */
#define W83781D_REG_ALARM1 0x41
#define W83781D_REG_ALARM2 0x42
-#define W83781D_REG_ALARM3 0x450 /* not on W83781D */
-#define W83781D_REG_IRQ 0x4C
+/* Real-time status (W83782D, W83783S, W83627HF) */
+#define W83782D_REG_ALARM1 0x459
+#define W83782D_REG_ALARM2 0x45A
+#define W83782D_REG_ALARM3 0x45B
+
#define W83781D_REG_BEEP_CONFIG 0x4D
#define W83781D_REG_BEEP_INTS1 0x56
#define W83781D_REG_BEEP_INTS2 0x57
@@ -1513,15 +1518,6 @@ w83781d_init_client(struct i2c_client *client)
W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
}
}
-
- if (type != w83781d) {
- /* enable comparator mode for temp2 and temp3 so
- alarm indication will work correctly */
- i = w83781d_read_value(client, W83781D_REG_IRQ);
- if (!(i & 0x40))
- w83781d_write_value(client, W83781D_REG_IRQ,
- i | 0x40);
- }
}
/* Start monitoring */
@@ -1612,14 +1608,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
data->fan_div[1] |= (i >> 4) & 0x04;
data->fan_div[2] |= (i >> 5) & 0x04;
}
- data->alarms =
- w83781d_read_value(client,
- W83781D_REG_ALARM1) +
- (w83781d_read_value(client, W83781D_REG_ALARM2) << 8);
if ((data->type == w83782d) || (data->type == w83627hf)) {
- data->alarms |=
- w83781d_read_value(client,
- W83781D_REG_ALARM3) << 16;
+ data->alarms = w83781d_read_value(client,
+ W83782D_REG_ALARM1)
+ | (w83781d_read_value(client,
+ W83782D_REG_ALARM2) << 8)
+ | (w83781d_read_value(client,
+ W83782D_REG_ALARM3) << 16);
+ } else if (data->type == w83783s) {
+ data->alarms = w83781d_read_value(client,
+ W83782D_REG_ALARM1)
+ | (w83781d_read_value(client,
+ W83782D_REG_ALARM2) << 8);
+ } else {
+ /* No real-time status registers, fall back to
+ interrupt status registers */
+ data->alarms = w83781d_read_value(client,
+ W83781D_REG_ALARM1)
+ | (w83781d_read_value(client,
+ W83781D_REG_ALARM2) << 8);
}
i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
data->beep_enable = i >> 7;
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index b176bf0c4c7b..a2f6bb676235 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -303,10 +303,6 @@ struct w83792d_data {
static int w83792d_attach_adapter(struct i2c_adapter *adapter);
static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
static int w83792d_detach_client(struct i2c_client *client);
-
-static int w83792d_read_value(struct i2c_client *client, u8 register);
-static int w83792d_write_value(struct i2c_client *client, u8 register,
- u8 value);
static struct w83792d_data *w83792d_update_device(struct device *dev);
#ifdef DEBUG
@@ -329,6 +325,20 @@ static inline long in_count_from_reg(int nr, struct w83792d_data *data)
return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
}
+/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+ but the driver only accesses registers in bank 0, so we don't have
+ to switch banks and lock access between switches. */
+static inline int w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static inline int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
/* following are the sysfs callback functions */
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client *client)
return 0;
}
-/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
- but the driver only accesses registers in bank 0, so we don't have
- to switch banks and lock access between switches. */
-static int w83792d_read_value(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
-{
- return i2c_smbus_write_byte_data(client, reg, value);
-}
-
static void
w83792d_init_client(struct i2c_client *client)
{
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 938848ae162d..3df3f09995c2 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus);
#ifdef MODULE
MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
-MODULE_PARM(bit_scan, "i");
+module_param(bit_scan, int, 0);
MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 08d5b8fed2dc..ff92735c7c85 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -124,6 +124,7 @@ config I2C_I801
ICH6
ICH7
ESB2
+ ICH8
This driver can also be built as a module. If so, the module
will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1c752ddc10e2..8e0f3158215f 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -32,6 +32,7 @@
ICH6 266A
ICH7 27DA
ESB2 269B
+ ICH8 283E
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
For SMBus support, they are similar to the PIIX4 and are part
of Intel's '810' and other chipsets.
@@ -527,6 +528,7 @@ static struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 9f2ffef4d812..4344ae6b1fcb 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -72,16 +72,6 @@ static ssize_t show_adapter_name(struct device *dev,
}
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-static int i2c_isa_device_probe(struct device *dev)
-{
- return -ENODEV;
-}
-
-static int i2c_isa_device_remove(struct device *dev)
-{
- return 0;
-}
-
/* We implement an interface which resembles i2c_{add,del}_driver,
but for i2c-isa drivers. We don't have to remember and handle lists
@@ -93,8 +83,6 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
/* Add the driver to the list of i2c drivers in the driver core */
driver->driver.bus = &i2c_bus_type;
- driver->driver.probe = i2c_isa_device_probe;
- driver->driver.remove = i2c_isa_device_remove;
res = driver_register(&driver->driver);
if (res)
return res;
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 3e5eba9fcacb..c63025a4c861 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapter = {
static int __init i2c_parport_init(void)
{
- int type_count;
-
- type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
- if (type < 0 || type >= type_count) {
+ if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
type = 0;
}
-
+
if (base == 0) {
printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
base = DEFAULT_BASE;
@@ -152,7 +149,7 @@ static int __init i2c_parport_init(void)
release_region(base, 3);
return -ENODEV;
}
-
+
return 0;
}
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 2854d858fc9b..7e2e8cd1c14a 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,14 +241,11 @@ static struct parport_driver i2c_parport_driver = {
static int __init i2c_parport_init(void)
{
- int type_count;
-
- type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
- if (type < 0 || type >= type_count) {
+ if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
type = 0;
}
-
+
return parport_register_driver(&i2c_parport_driver);
}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 86e2234faf80..7579f4b256a8 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *r
decode_ISR(isr);
}
- if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32))
+ if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog))
i2c->isrlog[i2c->irqlogidx++] = isr;
show_state(i2c);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0ce58b506046..1a2c9ab5d9e3 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -946,6 +946,20 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
}
}
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
+ u8 length, u8 *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+ data.block[0] = length;
+ memcpy(data.block + 1, values, length);
+ return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+
/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
@@ -1150,6 +1164,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
EXPORT_SYMBOL(i2c_smbus_write_word_data);
EXPORT_SYMBOL(i2c_smbus_write_block_data);
EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 6c60a9d2afd8..09086b8b6486 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -190,7 +190,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
if (lba48) {
task_ioreg_t tasklets[10];
- pr_debug("%s: LBA=0x%012llx\n", drive->name, block);
+ pr_debug("%s: LBA=0x%012llx\n", drive->name,
+ (unsigned long long)block);
tasklets[0] = 0;
tasklets[1] = 0;
@@ -317,7 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
- block, rq->nr_sectors, (unsigned long)rq->buffer);
+ (unsigned long long)block, rq->nr_sectors,
+ (unsigned long)rq->buffer);
if (hwif->rw_disk)
hwif->rw_disk(drive, rq);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 9834dce4e20f..0606bd2f6020 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -34,6 +34,7 @@
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -314,6 +315,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
if (rq->bio) /* fs request */
rq->errors = 0;
+ touch_softlockup_watchdog();
+
switch (drive->hwif->data_phase) {
case TASKFILE_MULTI_IN:
case TASKFILE_MULTI_OUT:
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 4c2af9020905..6213bd3caee5 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -445,6 +445,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
+ PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 2b286e865163..43b96e298363 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -13,11 +13,6 @@
* License along with this program; if not, write the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 18d7eda38851..eca92eb475a1 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -137,15 +137,15 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"
/*
* SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on
* if your sbp2 device is not properly handling the SCSI inquiry command.
- * This hack makes the inquiry look more like a typical MS Windows
- * inquiry.
+ * This hack makes the inquiry look more like a typical MS Windows inquiry
+ * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8.
*
* If force_inquiry_hack=1 is required for your device to work,
* please submit the logged sbp2_firmware_revision value of this device to
* the linux1394-devel mailing list.
*/
static int force_inquiry_hack;
-module_param(force_inquiry_hack, int, 0444);
+module_param(force_inquiry_hack, int, 0644);
MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
/*
@@ -264,18 +264,17 @@ static struct hpsb_protocol_driver sbp2_driver = {
},
};
-
-/* List of device firmware's that require a forced 36 byte inquiry. */
+/*
+ * List of device firmwares that require the inquiry hack.
+ * Yields a few false positives but did not break other devices so far.
+ */
static u32 sbp2_broken_inquiry_list[] = {
- 0x00002800, /* Stefan Richter <richtest@bauwesen.tu-cottbus.de> */
+ 0x00002800, /* Stefan Richter <stefanr@s5r6.in-berlin.de> */
/* DViCO Momobay CX-1 */
0x00000200 /* Andreas Plesch <plesch@fas.harvard.edu> */
/* QPS Fire DVDBurner */
};
-#define NUM_BROKEN_INQUIRY_DEVS \
- (sizeof(sbp2_broken_inquiry_list)/sizeof(*sbp2_broken_inquiry_list))
-
/**************************************
* General utility functions
**************************************/
@@ -643,9 +642,15 @@ static int sbp2_remove(struct device *dev)
if (!scsi_id)
return 0;
- /* Trigger shutdown functions in scsi's highlevel. */
- if (scsi_id->scsi_host)
+ if (scsi_id->scsi_host) {
+ /* Get rid of enqueued commands if there is no chance to
+ * send them. */
+ if (!sbp2util_node_is_available(scsi_id))
+ sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
+ /* scsi_remove_device() will trigger shutdown functions of SCSI
+ * highlevel drivers which would deadlock if blocked. */
scsi_unblock_requests(scsi_id->scsi_host);
+ }
sdev = scsi_id->sdev;
if (sdev) {
scsi_id->sdev = NULL;
@@ -742,11 +747,6 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
hi->host = ud->ne->host;
INIT_LIST_HEAD(&hi->scsi_ids);
- /* Register our sbp2 status address space... */
- hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops,
- SBP2_STATUS_FIFO_ADDRESS,
- SBP2_STATUS_FIFO_ADDRESS +
- SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1));
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
/* Handle data movement if physical dma is not
* enabled/supportedon host controller */
@@ -759,6 +759,18 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
+ /* Register the status FIFO address range. We could use the same FIFO
+ * for targets at different nodes. However we need different FIFOs per
+ * target in order to support multi-unit devices. */
+ scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
+ &sbp2_highlevel, ud->ne->host, &sbp2_ops,
+ sizeof(struct sbp2_status_block), sizeof(quadlet_t),
+ ~0ULL, ~0ULL);
+ if (!scsi_id->status_fifo_addr) {
+ SBP2_ERR("failed to allocate status FIFO address range");
+ goto failed_alloc;
+ }
+
/* Register our host with the SCSI stack. */
scsi_host = scsi_host_alloc(&scsi_driver_template,
sizeof(unsigned long));
@@ -997,6 +1009,10 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
SBP2_DMA_FREE("single query logins data");
}
+ if (scsi_id->status_fifo_addr)
+ hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
+ scsi_id->status_fifo_addr);
+
scsi_id->ud->device.driver_data = NULL;
SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
@@ -1075,11 +1091,10 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
- scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
- SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
- scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
- SBP2_STATUS_FIFO_ADDRESS_HI);
- SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");
+ scsi_id->query_logins_orb->status_fifo_hi =
+ ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+ scsi_id->query_logins_orb->status_fifo_lo =
+ ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
@@ -1184,11 +1199,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
- scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
- SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
- scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
- SBP2_STATUS_FIFO_ADDRESS_HI);
- SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
+ scsi_id->login_orb->status_fifo_hi =
+ ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+ scsi_id->login_orb->status_fifo_lo =
+ ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
/*
* Byte swap ORB if necessary
@@ -1301,10 +1315,10 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
scsi_id->logout_orb->reserved5 = 0x0;
- scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
- SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
- scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
- SBP2_STATUS_FIFO_ADDRESS_HI);
+ scsi_id->logout_orb->status_fifo_hi =
+ ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+ scsi_id->logout_orb->status_fifo_lo =
+ ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
/*
* Byte swap ORB if necessary
@@ -1366,10 +1380,10 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
scsi_id->reconnect_orb->reserved5 = 0x0;
- scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
- SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
- scsi_id->reconnect_orb->status_FIFO_hi =
- (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
+ scsi_id->reconnect_orb->status_fifo_hi =
+ ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+ scsi_id->reconnect_orb->status_fifo_lo =
+ ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
/*
* Byte swap ORB if necessary
@@ -1560,7 +1574,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
/* Check for a blacklisted set of devices that require us to force
* a 36 byte host inquiry. This can be overriden as a module param
* (to force all hosts). */
- for (i = 0; i < NUM_BROKEN_INQUIRY_DEVS; i++) {
+ for (i = 0; i < ARRAY_SIZE(sbp2_broken_inquiry_list); i++) {
if ((firmware_revision & 0xffff00) ==
sbp2_broken_inquiry_list[i]) {
SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
@@ -2007,18 +2021,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
}
/*
- * The scsi stack sends down a request_bufflen which does not match the
- * length field in the scsi cdb. This causes some sbp2 devices to
- * reject this inquiry command. Fix the request_bufflen.
- */
- if (*cmd == INQUIRY) {
- if (force_inquiry_hack || scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK)
- request_bufflen = cmd[4] = 0x24;
- else
- request_bufflen = cmd[4];
- }
-
- /*
* Now actually fill in the comamnd orb and sbp2 s/g list
*/
sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg,
@@ -2082,9 +2084,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
SBP2_DEBUG("sbp2_check_sbp2_response");
- switch (SCpnt->cmnd[0]) {
-
- case INQUIRY:
+ if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
/*
* Make sure data length is ok. Minimum length is 36 bytes
*/
@@ -2097,13 +2097,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
*/
scsi_buf[2] |= 2;
scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-
- break;
-
- default:
- break;
}
- return;
}
/*
@@ -2114,7 +2108,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
{
struct sbp2scsi_host_info *hi;
struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
- u32 id;
struct scsi_cmnd *SCpnt = NULL;
u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
struct sbp2_command_info *command;
@@ -2137,12 +2130,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
}
/*
- * Find our scsi_id structure by looking at the status fifo address written to by
- * the sbp2 device.
+ * Find our scsi_id structure by looking at the status fifo address
+ * written to by the sbp2 device.
*/
- id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS));
list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) {
- if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) {
+ if (scsi_id_tmp->ne->nodeid == nodeid &&
+ scsi_id_tmp->status_fifo_addr == addr) {
scsi_id = scsi_id_tmp;
break;
}
@@ -2483,7 +2476,16 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
{
- ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
+ struct scsi_id_instance_data *scsi_id =
+ (struct scsi_id_instance_data *)sdev->host->hostdata[0];
+
+ scsi_id->sdev = sdev;
+
+ if (force_inquiry_hack ||
+ scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) {
+ sdev->inquiry_len = 36;
+ sdev->skip_ms_page_8 = 1;
+ }
return 0;
}
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 900ea1d25e71..e2d357a9ea3a 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -33,15 +33,17 @@
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
#define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31)
-#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31)
-#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */
+#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31)
+#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */
#define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16)
-#define ORB_SET_DATA_SIZE(value) (value & 0xffff)
-#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16)
-#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19)
-#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20)
-#define ORB_SET_SPEED(value) ((value & 0x7) << 24)
-#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27)
+#define ORB_SET_STATUS_FIFO_HI(value, id) (value >> 32 | ORB_SET_NODE_ID(id))
+#define ORB_SET_STATUS_FIFO_LO(value) (value & 0xffffffff)
+#define ORB_SET_DATA_SIZE(value) (value & 0xffff)
+#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16)
+#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19)
+#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20)
+#define ORB_SET_SPEED(value) ((value & 0x7) << 24)
+#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27)
struct sbp2_command_orb {
volatile u32 next_ORB_hi;
@@ -76,8 +78,8 @@ struct sbp2_login_orb {
u32 login_response_lo;
u32 lun_misc;
u32 passwd_resp_lengths;
- u32 status_FIFO_hi;
- u32 status_FIFO_lo;
+ u32 status_fifo_hi;
+ u32 status_fifo_lo;
};
#define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff)
@@ -102,8 +104,8 @@ struct sbp2_query_logins_orb {
u32 query_response_lo;
u32 lun_misc;
u32 reserved_resp_length;
- u32 status_FIFO_hi;
- u32 status_FIFO_lo;
+ u32 status_fifo_hi;
+ u32 status_fifo_lo;
};
#define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff)
@@ -123,8 +125,8 @@ struct sbp2_reconnect_orb {
u32 reserved4;
u32 login_ID_misc;
u32 reserved5;
- u32 status_FIFO_hi;
- u32 status_FIFO_lo;
+ u32 status_fifo_hi;
+ u32 status_fifo_lo;
};
struct sbp2_logout_orb {
@@ -134,8 +136,8 @@ struct sbp2_logout_orb {
u32 reserved4;
u32 login_ID_misc;
u32 reserved5;
- u32 status_FIFO_hi;
- u32 status_FIFO_lo;
+ u32 status_fifo_hi;
+ u32 status_fifo_lo;
};
#define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff)
@@ -195,30 +197,6 @@ struct sbp2_status_block {
* Miscellaneous SBP2 related config rom defines
*/
-/* The status fifo address definition below is used as a base for each
- * node, which a chunk seperately assigned to each unit directory in the
- * node. For example, 0xfffe00000000ULL is used for the first sbp2 device
- * detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node
- * 0, and so on.
- *
- * Note: We could use a single status fifo address for all sbp2 devices,
- * and figure out which sbp2 device the status belongs to by looking at
- * the source node id of the status write... but, using separate addresses
- * for each sbp2 unit directory allows for better code and the ability to
- * support multiple luns within a single 1394 node.
- *
- * Also note that we choose the address range below as it is a region
- * specified for write posting, where the ohci controller will
- * automatically send an ack_complete when the status is written by the
- * sbp2 device... saving a split transaction. =)
- */
-#define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL
-#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe
-#define SBP2_STATUS_FIFO_ADDRESS_LO 0x0
-
-#define SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(entry) ((entry) << 5)
-#define SBP2_STATUS_FIFO_OFFSET_TO_ENTRY(offset) ((offset) >> 5)
-
#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1
#define SBP2_CSR_OFFSET_KEY 0x54
#define SBP2_UNIT_SPEC_ID_KEY 0x12
@@ -258,7 +236,6 @@ struct sbp2_status_block {
*/
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
-#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#define SBP2_MAX_CMDS 8 /* This should be safe */
@@ -338,6 +315,11 @@ struct scsi_id_instance_data {
u32 sbp2_firmware_revision;
/*
+ * Address for the device to write status blocks to
+ */
+ u64 status_fifo_addr;
+
+ /*
* Variable used for logins, reconnects, logouts, query logins
*/
atomic_t sbp2_login_complete;
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 39fb88309e8e..216dbbf1dc8e 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -744,7 +744,7 @@ static int __video1394_ioctl(struct file *file,
if (i == ISO_CHANNELS) {
PRINT(KERN_ERR, ohci->host->id,
"No free channel found");
- return EAGAIN;
+ return -EAGAIN;
}
if (!(ohci->ISO_channel_usage & mask)) {
v.channel = i;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index d393b504bf26..c82f47a66e48 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -665,7 +665,15 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_wc mad_wc;
struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
- if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
+ /*
+ * Directed route handling starts if the initial LID routed part of
+ * a request or the ending LID routed part of a response is empty.
+ * If we are at the start of the LID routed part, don't update the
+ * hop_ptr or hop_cnt. See section 14.2.2, Vol 1 IB spec.
+ */
+ if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) ==
+ IB_LID_PERMISSIVE &&
+ !smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
ret = -EINVAL;
printk(KERN_ERR PFX "Invalid directed route\n");
goto out;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index e95c4293a496..f6a05965a4e8 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1319,15 +1319,6 @@ static struct class ucm_class = {
.release = ib_ucm_release_class_dev
};
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct ib_ucm_device *dev;
-
- dev = container_of(class_dev, struct ib_ucm_device, class_dev);
- return print_dev_t(buf, dev->dev.dev);
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
{
struct ib_ucm_device *dev;
@@ -1364,15 +1355,13 @@ static void ib_ucm_add_one(struct ib_device *device)
ucm_dev->class_dev.class = &ucm_class;
ucm_dev->class_dev.dev = device->dma_device;
+ ucm_dev->class_dev.devt = ucm_dev->dev.dev;
snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
ucm_dev->devnum);
if (class_device_register(&ucm_dev->class_dev))
goto err_cdev;
if (class_device_create_file(&ucm_dev->class_dev,
- &class_device_attr_dev))
- goto err_class;
- if (class_device_create_file(&ucm_dev->class_dev,
&class_device_attr_ibdev))
goto err_class;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index f9b9b93dc501..2825615ce81c 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1029,25 +1029,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
MTHCA_GET(size, outbox, QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET);
dev_lim->uar_scratch_entry_sz = size;
- mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
- dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
- mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
- dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
- mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
- dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
- mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
- dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz);
- mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
- dev_lim->reserved_mrws, dev_lim->reserved_mtts);
- mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
- dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
- mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
- dev_lim->max_pds, dev_lim->reserved_mgms);
- mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
- dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
-
- mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
-
if (mthca_is_memfree(dev)) {
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
dev_lim->max_srq_sz = 1 << field;
@@ -1093,6 +1074,25 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE;
}
+ mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
+ dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
+ mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
+ dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
+ mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
+ dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
+ mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
+ dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz);
+ mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
+ dev_lim->reserved_mrws, dev_lim->reserved_mtts);
+ mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
+ dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
+ mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
+ dev_lim->max_pds, dev_lim->reserved_mgms);
+ mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
+ dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
+
+ mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
+
out:
mthca_free_mailbox(dev, mailbox);
return err;
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 2a165fd06e57..e481037288d6 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -53,8 +53,8 @@
#define DRV_NAME "ib_mthca"
#define PFX DRV_NAME ": "
-#define DRV_VERSION "0.06"
-#define DRV_RELDATE "June 23, 2005"
+#define DRV_VERSION "0.07"
+#define DRV_RELDATE "February 13, 2006"
enum {
MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index e0a5412b7e68..2f85a9a831b1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -78,6 +78,7 @@ enum {
IPOIB_FLAG_SUBINTERFACE = 4,
IPOIB_MCAST_RUN = 5,
IPOIB_STOP_REAPER = 6,
+ IPOIB_MCAST_STARTED = 7,
IPOIB_MAX_BACKOFF_SECONDS = 16,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ccaa0c387076..a2408d7ec598 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -533,8 +533,10 @@ void ipoib_mcast_join_task(void *dev_ptr)
}
if (!priv->broadcast) {
- priv->broadcast = ipoib_mcast_alloc(dev, 1);
- if (!priv->broadcast) {
+ struct ipoib_mcast *broadcast;
+
+ broadcast = ipoib_mcast_alloc(dev, 1);
+ if (!broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
@@ -544,10 +546,11 @@ void ipoib_mcast_join_task(void *dev_ptr)
return;
}
- memcpy(priv->broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
+ spin_lock_irq(&priv->lock);
+ memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
sizeof (union ib_gid));
+ priv->broadcast = broadcast;
- spin_lock_irq(&priv->lock);
__ipoib_mcast_add(dev, priv->broadcast);
spin_unlock_irq(&priv->lock);
}
@@ -601,6 +604,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
queue_work(ipoib_workqueue, &priv->mcast_task);
mutex_unlock(&mcast_mutex);
+ spin_lock_irq(&priv->lock);
+ set_bit(IPOIB_MCAST_STARTED, &priv->flags);
+ spin_unlock_irq(&priv->lock);
+
return 0;
}
@@ -611,6 +618,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
+ spin_lock_irq(&priv->lock);
+ clear_bit(IPOIB_MCAST_STARTED, &priv->flags);
+ spin_unlock_irq(&priv->lock);
+
mutex_lock(&mcast_mutex);
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
cancel_delayed_work(&priv->mcast_task);
@@ -693,6 +704,14 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
*/
spin_lock(&priv->lock);
+ if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) ||
+ !priv->broadcast ||
+ !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
+ ++priv->stats.tx_dropped;
+ dev_kfree_skb_any(skb);
+ goto unlock;
+ }
+
mcast = __ipoib_mcast_find(dev, mgid);
if (!mcast) {
/* Let's create a new send only group now */
@@ -754,6 +773,7 @@ out:
ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
}
+unlock:
spin_unlock(&priv->lock);
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 2d2d4ac3525a..960dae5c87d1 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1155,6 +1155,12 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
spin_lock_irq(target->scsi_host->host_lock);
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED) {
+ scmnd->result = DID_BAD_TARGET << 16;
+ goto out;
+ }
+
if (scmnd->host_scribble == (void *) -1L)
goto out;
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 6e0afbb22383..2708167ba175 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
-obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 184c4129470d..415c49178985 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -7,7 +7,6 @@
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
-obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index d448bb5e4869..3a6ae85cd69c 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -19,6 +19,7 @@
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <asm/hardware.h>
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index c88520d3d13c..40333d61093c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -232,6 +232,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
+ { 99, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 19b1b0121726..ad6217467676 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -58,7 +58,7 @@ static unsigned int psmouse_resetafter = 5;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
-static unsigned int psmouse_resync_time = 5;
+static unsigned int psmouse_resync_time;
module_param_named(resync_time, psmouse_resync_time, uint, 0644);
MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never).");
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index b4898d8a68e2..6d9ec9ab1b90 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -68,15 +68,19 @@ struct trackpoint_attr_data {
size_t field_offset;
unsigned char command;
unsigned char mask;
+ unsigned char inverted;
};
static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
{
struct trackpoint_data *tp = psmouse->private;
struct trackpoint_attr_data *attr = data;
- unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+ unsigned char value = *(unsigned char *)((char *)tp + attr->field_offset);
+
+ if (attr->inverted)
+ value = !value;
- return sprintf(buf, "%u\n", *field);
+ return sprintf(buf, "%u\n", value);
}
static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
@@ -120,6 +124,9 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
if (*rest || value > 1)
return -EINVAL;
+ if (attr->inverted)
+ value = !value;
+
if (*field != value) {
*field = value;
trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
@@ -129,11 +136,12 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
}
-#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \
+#define TRACKPOINT_BIT_ATTR(_name, _command, _mask, _inv) \
static struct trackpoint_attr_data trackpoint_attr_##_name = { \
.field_offset = offsetof(struct trackpoint_data, _name), \
.command = _command, \
.mask = _mask, \
+ .inverted = _inv, \
}; \
PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
&trackpoint_attr_##_name, \
@@ -150,9 +158,9 @@ TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
-TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
-TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
-TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0);
+TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, 0);
+TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, 1);
static struct attribute *trackpoint_attrs[] = {
&psmouse_attr_sensitivity.dattr.attr,
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index 9857d8b6ad66..050298b1a09d 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -78,7 +78,7 @@
#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */
#define TP_MASK_MB 0x01
-#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */
+#define TP_TOGGLE_EXT_DEV 0x23 /* Disable external device */
#define TP_MASK_EXT_DEV 0x02
#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */
#define TP_MASK_DRIFT 0x80
@@ -125,7 +125,7 @@
#define TP_DEF_MB 0x00
#define TP_DEF_PTSON 0x00
#define TP_DEF_SKIPBACK 0x00
-#define TP_DEF_EXT_DEV 0x01
+#define TP_DEF_EXT_DEV 0x00 /* 0 means enabled */
#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 678a8599f9ff..4155197867a3 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
-obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
obj-$(CONFIG_HP_SDC) += hp_sdc.o
obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index b45a45ca7cc9..8c12a974b411 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -48,10 +48,13 @@
#define TS_POLL_PERIOD msecs_to_jiffies(10)
+/* this driver doesn't aim at the peak continuous sample rate */
+#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
+
struct ts_event {
/* For portability, we can't read 12 bit values using SPI (which
* would make the controller deliver them as native byteorder u16
- * with msbs zeroed). Instead, we read them as two 8-byte values,
+ * with msbs zeroed). Instead, we read them as two 8-bit values,
* which need byteswapping then range adjustment.
*/
__be16 x;
@@ -60,7 +63,7 @@ struct ts_event {
};
struct ads7846 {
- struct input_dev input;
+ struct input_dev *input;
char phys[32];
struct spi_device *spi;
@@ -68,6 +71,7 @@ struct ads7846 {
u16 vref_delay_usecs;
u16 x_plate_ohms;
+ u8 read_x, read_y, read_z1, read_z2;
struct ts_event tc;
struct spi_transfer xfer[8];
@@ -117,10 +121,10 @@ struct ads7846 {
#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
| ADS_12_BIT | ADS_DFR)
-static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON;
-static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON;
-static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON;
-static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
+#define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON)
+#define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
+#define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
+#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */
/* single-ended samples need to first power up reference voltage;
* we leave both ADC and VREF powered
@@ -128,8 +132,8 @@ static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
| ADS_12_BIT | ADS_SER)
-static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON;
-static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
+#define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON)
+#define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN)
/*--------------------------------------------------------------------------*/
@@ -138,7 +142,9 @@ static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
*/
struct ser_req {
+ u8 ref_on;
u8 command;
+ u8 ref_off;
u16 scratch;
__be16 sample;
struct spi_message msg;
@@ -152,7 +158,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL);
int status;
int sample;
- int i;
+ int i;
if (!req)
return -ENOMEM;
@@ -160,7 +166,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
INIT_LIST_HEAD(&req->msg.transfers);
/* activate reference, so it has time to settle; */
- req->xfer[0].tx_buf = &ref_on;
+ req->ref_on = REF_ON;
+ req->xfer[0].tx_buf = &req->ref_on;
req->xfer[0].len = 1;
req->xfer[1].rx_buf = &req->scratch;
req->xfer[1].len = 2;
@@ -182,7 +189,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
/* REVISIT: take a few more samples, and compare ... */
/* turn off reference */
- req->xfer[4].tx_buf = &ref_off;
+ req->ref_off = REF_OFF;
+ req->xfer[4].tx_buf = &req->ref_off;
req->xfer[4].len = 1;
req->xfer[5].rx_buf = &req->scratch;
req->xfer[5].len = 2;
@@ -236,11 +244,12 @@ SHOW(vbatt)
static void ads7846_rx(void *ads)
{
- struct ads7846 *ts = ads;
- unsigned Rt;
- unsigned sync = 0;
- u16 x, y, z1, z2;
- unsigned long flags;
+ struct ads7846 *ts = ads;
+ struct input_dev *input_dev = ts->input;
+ unsigned Rt;
+ unsigned sync = 0;
+ u16 x, y, z1, z2;
+ unsigned long flags;
/* adjust: 12 bit samples (left aligned), built from
* two 8 bit values writen msb-first.
@@ -276,21 +285,21 @@ static void ads7846_rx(void *ads)
* won't notice that, even if nPENIRQ never fires ...
*/
if (!ts->pendown && Rt != 0) {
- input_report_key(&ts->input, BTN_TOUCH, 1);
+ input_report_key(input_dev, BTN_TOUCH, 1);
sync = 1;
} else if (ts->pendown && Rt == 0) {
- input_report_key(&ts->input, BTN_TOUCH, 0);
+ input_report_key(input_dev, BTN_TOUCH, 0);
sync = 1;
}
if (Rt) {
- input_report_abs(&ts->input, ABS_X, x);
- input_report_abs(&ts->input, ABS_Y, y);
- input_report_abs(&ts->input, ABS_PRESSURE, Rt);
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_report_abs(input_dev, ABS_PRESSURE, Rt);
sync = 1;
}
if (sync)
- input_sync(&ts->input);
+ input_sync(input_dev);
#ifdef VERBOSE
if (Rt || ts->pendown)
@@ -396,9 +405,10 @@ static int ads7846_resume(struct spi_device *spi)
static int __devinit ads7846_probe(struct spi_device *spi)
{
struct ads7846 *ts;
+ struct input_dev *input_dev;
struct ads7846_platform_data *pdata = spi->dev.platform_data;
struct spi_transfer *x;
- int i;
+ int err;
if (!spi->irq) {
dev_dbg(&spi->dev, "no IRQ?\n");
@@ -411,9 +421,9 @@ static int __devinit ads7846_probe(struct spi_device *spi)
}
/* don't exceed max specified sample rate */
- if (spi->max_speed_hz > (125000 * 16)) {
+ if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
- (spi->max_speed_hz/16)/1000);
+ (spi->max_speed_hz/SAMPLE_BITS)/1000);
return -EINVAL;
}
@@ -423,13 +433,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
* to discard the four garbage LSBs.
*/
- if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL)))
- return -ENOMEM;
+ ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ts || !input_dev) {
+ err = -ENOMEM;
+ goto err_free_mem;
+ }
dev_set_drvdata(&spi->dev, ts);
+ spi->dev.power.power_state = PMSG_ON;
ts->spi = spi;
- spi->dev.power.power_state = PMSG_ON;
+ ts->input = input_dev;
init_timer(&ts->timer);
ts->timer.data = (unsigned long) ts;
@@ -439,70 +454,80 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
- init_input_dev(&ts->input);
+ snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
- ts->input.dev = &spi->dev;
- ts->input.name = "ADS784x Touchscreen";
- snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id);
- ts->input.phys = ts->phys;
+ input_dev->name = "ADS784x Touchscreen";
+ input_dev->phys = ts->phys;
+ input_dev->cdev.dev = &spi->dev;
- ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&ts->input, ABS_X,
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X,
pdata->x_min ? : 0,
pdata->x_max ? : MAX_12BIT,
0, 0);
- input_set_abs_params(&ts->input, ABS_Y,
+ input_set_abs_params(input_dev, ABS_Y,
pdata->y_min ? : 0,
pdata->y_max ? : MAX_12BIT,
0, 0);
- input_set_abs_params(&ts->input, ABS_PRESSURE,
+ input_set_abs_params(input_dev, ABS_PRESSURE,
pdata->pressure_min, pdata->pressure_max, 0, 0);
- input_register_device(&ts->input);
-
/* set up the transfers to read touchscreen state; this assumes we
* use formula #2 for pressure, not #3.
*/
+ INIT_LIST_HEAD(&ts->msg.transfers);
x = ts->xfer;
/* y- still on; turn on only y+ (and ADC) */
- x->tx_buf = &read_y;
+ ts->read_y = READ_Y;
+ x->tx_buf = &ts->read_y;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.y;
x->len = 2;
- x++;
+ spi_message_add_tail(x, &ts->msg);
/* turn y+ off, x- on; we'll use formula #2 */
if (ts->model == 7846) {
- x->tx_buf = &read_z1;
+ x++;
+ ts->read_z1 = READ_Z1;
+ x->tx_buf = &ts->read_z1;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.z1;
x->len = 2;
- x++;
+ spi_message_add_tail(x, &ts->msg);
- x->tx_buf = &read_z2;
+ x++;
+ ts->read_z2 = READ_Z2;
+ x->tx_buf = &ts->read_z2;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.z2;
x->len = 2;
- x++;
+ spi_message_add_tail(x, &ts->msg);
}
/* turn y- off, x+ on, then leave in lowpower */
- x->tx_buf = &read_x;
+ x++;
+ ts->read_x = READ_X;
+ x->tx_buf = &ts->read_x;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.x;
x->len = 2;
- x++;
-
- CS_CHANGE(x[-1]);
+ CS_CHANGE(*x);
+ spi_message_add_tail(x, &ts->msg);
- for (i = 0; i < x - ts->xfer; i++)
- spi_message_add_tail(&ts->xfer[i], &ts->msg);
ts->msg.complete = ads7846_rx;
ts->msg.context = ts;
@@ -510,9 +535,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
spi->dev.bus_id, ts)) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
- input_unregister_device(&ts->input);
- kfree(ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto err_free_mem;
}
dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
@@ -534,7 +558,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
device_create_file(&spi->dev, &dev_attr_vbatt);
device_create_file(&spi->dev, &dev_attr_vaux);
+ err = input_register_device(input_dev);
+ if (err)
+ goto err_free_irq;
+
return 0;
+
+ err_free_irq:
+ free_irq(spi->irq, ts);
+ err_free_mem:
+ input_free_device(input_dev);
+ kfree(ts);
+ return err;
}
static int __devexit ads7846_remove(struct spi_device *spi)
@@ -554,7 +589,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
device_remove_file(&spi->dev, &dev_attr_vbatt);
device_remove_file(&spi->dev, &dev_attr_vaux);
- input_unregister_device(&ts->input);
+ input_unregister_device(ts->input);
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 0ef560144be3..6dfc94122dd9 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -351,7 +351,7 @@ config HISAX_ENTERNOW_PCI
config HISAX_AMD7930
bool "Am7930 (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SPARC
+ depends on EXPERIMENTAL && SPARC && BROKEN
help
This enables HiSax support for the AMD7930 chips on some SPARCs.
This code is not finished yet.
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 8159bcecd0c2..df9d65201819 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1929,6 +1929,8 @@ static struct pci_device_id hisax_pci_tbl[] __initdata = {
{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B700, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B701, PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, PCI_ANY_ID, PCI_ANY_ID},
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 4866fc32d8d9..91d25acb5ede 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -51,6 +51,8 @@ static const PCI_ENTRY id_list[] =
{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B700, "Primux II S0", "B700"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B701, "Primux II S0 NT", "B701"},
{PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"},
{PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
{PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index ca5b4a3b683e..262c44127419 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1,7 +1,7 @@
/*
* hfc_usb.c
*
- * $Id: hfc_usb.c,v 4.36 2005/04/08 09:55:13 martinb1 Exp $
+ * $Id: hfc_usb.c,v 2.3.2.13 2006/02/17 17:17:22 mbachem Exp $
*
* modular HiSax ISDN driver for Colognechip HFC-S USB chip
*
@@ -45,7 +45,7 @@
#include "hfc_usb.h"
static const char *hfcusb_revision =
- "$Revision: 4.36 $ $Date: 2005/04/08 09:55:13 $ ";
+ "$Revision: 2.3.2.13 $ $Date: 2006/02/17 17:17:22 $ ";
/* Hisax debug support
* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG
@@ -219,7 +219,7 @@ symbolic(struct hfcusb_symbolic_list list[], const int num)
for (i = 0; list[i].name != NULL; i++)
if (list[i].num == num)
return (list[i].name);
- return "<unkown ERROR>";
+ return "<unknown ERROR>";
}
@@ -235,9 +235,9 @@ ctrl_start_transfer(hfcusb_data * hfc)
hfc->ctrl_urb->transfer_buffer = NULL;
hfc->ctrl_urb->transfer_buffer_length = 0;
hfc->ctrl_write.wIndex =
- hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
+ cpu_to_le16(hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg);
hfc->ctrl_write.wValue =
- hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
+ cpu_to_le16(hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val);
usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */
}
@@ -1282,7 +1282,7 @@ usb_init(hfcusb_data * hfc)
/* init the background machinery for control requests */
hfc->ctrl_read.bRequestType = 0xc0;
hfc->ctrl_read.bRequest = 1;
- hfc->ctrl_read.wLength = 1;
+ hfc->ctrl_read.wLength = cpu_to_le16(1);
hfc->ctrl_write.bRequestType = 0x40;
hfc->ctrl_write.bRequest = 0;
hfc->ctrl_write.wLength = 0;
@@ -1373,9 +1373,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
vend_idx = 0xffff;
for (i = 0; hfcusb_idtab[i].idVendor; i++) {
- if (dev->descriptor.idVendor == hfcusb_idtab[i].idVendor
- && dev->descriptor.idProduct ==
- hfcusb_idtab[i].idProduct) {
+ if ((le16_to_cpu(dev->descriptor.idVendor) == hfcusb_idtab[i].idVendor)
+ && (le16_to_cpu(dev->descriptor.idProduct) == hfcusb_idtab[i].idProduct)) {
vend_idx = i;
continue;
}
@@ -1516,8 +1515,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_transfer_mode
= USB_INT;
packet_size =
- ep->desc.
- wMaxPacketSize;
+ le16_to_cpu(ep->desc.wMaxPacketSize);
break;
case USB_ENDPOINT_XFER_BULK:
if (ep_addr & 0x80)
@@ -1545,8 +1543,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_transfer_mode
= USB_BULK;
packet_size =
- ep->desc.
- wMaxPacketSize;
+ le16_to_cpu(ep->desc.wMaxPacketSize);
break;
case USB_ENDPOINT_XFER_ISOC:
if (ep_addr & 0x80)
@@ -1574,8 +1571,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_transfer_mode
= USB_ISOC;
iso_packet_size =
- ep->desc.
- wMaxPacketSize;
+ le16_to_cpu(ep->desc.wMaxPacketSize);
break;
default:
context->
@@ -1588,10 +1584,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
fifonum = cidx;
context->fifos[cidx].hfc =
context;
- context->fifos[cidx].
- usb_packet_maxlen =
- ep->desc.
- wMaxPacketSize;
+ context->fifos[cidx].usb_packet_maxlen =
+ le16_to_cpu(ep->desc.wMaxPacketSize);
context->fifos[cidx].
intervall =
ep->desc.bInterval;
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index f190a99604f0..aeaa1db74bd8 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1682,6 +1682,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
#endif
+ module_put(info->owner);
return;
}
info->flags |= ISDN_ASYNC_CLOSING;
@@ -2359,8 +2360,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
/* use queue instead of direct, if online and */
/* data is in queue or buffer is full */
- if ((info->online && tty_buffer_request_room(tty, l) < l) ||
- (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
+ if (info->online && ((tty_buffer_request_room(tty, l) < l) ||
+ !skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
skb = alloc_skb(l, GFP_ATOMIC);
if (!skb) {
spin_unlock_irqrestore(&info->readlock, flags);
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 7d4a0ac28c06..12ad462737ba 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -187,6 +187,14 @@ config WINDFARM_PM91
This driver provides thermal control for the PowerMac9,1
which is the recent (SMU based) single CPU desktop G5
+config WINDFARM_PM112
+ tristate "Support for thermal management on PowerMac11,2"
+ depends on WINDFARM && I2C && PMAC_SMU
+ select I2C_POWERMAC
+ help
+ This driver provides thermal control for the PowerMac11,2
+ which are the recent dual and quad G5 machines using the
+ 970MP dual-core processor.
config ANSLCD
tristate "Support for ANS LCD display"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index f4657aa81fb0..6081acdea404 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -35,3 +35,8 @@ obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \
windfarm_smu_sensors.o \
windfarm_lm75_sensor.o windfarm_pid.o \
windfarm_cpufreq_clamp.o windfarm_pm91.o
+obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
+ windfarm_smu_controls.o \
+ windfarm_smu_sensors.o \
+ windfarm_max6690_sensor.o \
+ windfarm_lm75_sensor.o windfarm_pid.o
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 6eb93e45fcd3..4a478eb0e27d 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -825,7 +825,7 @@ proc_get_info(char *page, char **start, off_t off,
p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION);
p += sprintf(p, "PMU firmware version : %02x\n", pmu_version);
p += sprintf(p, "AC Power : %d\n",
- ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0));
+ ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0) || pmu_battery_count == 0);
p += sprintf(p, "Battery count : %d\n", pmu_battery_count);
return p - page;
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index 3f0cb0312ea3..7a2482cc26a7 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/notifier.h>
+#include <linux/device.h>
/* Display a 16.16 fixed point value */
#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16)
@@ -39,6 +40,7 @@ struct wf_control {
char *name;
int type;
struct kref ref;
+ struct device_attribute attr;
};
#define WF_CONTROL_TYPE_GENERIC 0
@@ -87,6 +89,7 @@ struct wf_sensor {
struct wf_sensor_ops *ops;
char *name;
struct kref ref;
+ struct device_attribute attr;
};
/* Same lifetime rules as controls */
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 6c2a471ea6c0..6c0ba04bc57a 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -33,6 +33,9 @@
#include <linux/reboot.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/mutex.h>
+
+#include <asm/prom.h>
#include "windfarm.h"
@@ -48,13 +51,17 @@
static LIST_HEAD(wf_controls);
static LIST_HEAD(wf_sensors);
-static DECLARE_MUTEX(wf_lock);
+static DEFINE_MUTEX(wf_lock);
static struct notifier_block *wf_client_list;
static int wf_client_count;
static unsigned int wf_overtemp;
static unsigned int wf_overtemp_counter;
struct task_struct *wf_thread;
+static struct platform_device wf_platform_device = {
+ .name = "windfarm",
+};
+
/*
* Utilities & tick thread
*/
@@ -156,26 +163,67 @@ static void wf_control_release(struct kref *kref)
kfree(ct);
}
+static ssize_t wf_show_control(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+ s32 val = 0;
+ int err;
+
+ err = ctrl->ops->get_value(ctrl, &val);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%d\n", val);
+}
+
+/* This is really only for debugging... */
+static ssize_t wf_store_control(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+ int val;
+ int err;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ while (endp < buf + count && (*endp == ' ' || *endp == '\n'))
+ ++endp;
+ if (endp - buf < count)
+ return -EINVAL;
+ err = ctrl->ops->set_value(ctrl, val);
+ if (err < 0)
+ return err;
+ return count;
+}
+
int wf_register_control(struct wf_control *new_ct)
{
struct wf_control *ct;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(ct, &wf_controls, link) {
if (!strcmp(ct->name, new_ct->name)) {
printk(KERN_WARNING "windfarm: trying to register"
" duplicate control %s\n", ct->name);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return -EEXIST;
}
}
kref_init(&new_ct->ref);
list_add(&new_ct->link, &wf_controls);
+ new_ct->attr.attr.name = new_ct->name;
+ new_ct->attr.attr.owner = THIS_MODULE;
+ new_ct->attr.attr.mode = 0644;
+ new_ct->attr.show = wf_show_control;
+ new_ct->attr.store = wf_store_control;
+ device_create_file(&wf_platform_device.dev, &new_ct->attr);
+
DBG("wf: Registered control %s\n", new_ct->name);
wf_notify(WF_EVENT_NEW_CONTROL, new_ct);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return 0;
}
@@ -183,9 +231,9 @@ EXPORT_SYMBOL_GPL(wf_register_control);
void wf_unregister_control(struct wf_control *ct)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_del(&ct->link);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
DBG("wf: Unregistered control %s\n", ct->name);
@@ -197,16 +245,16 @@ struct wf_control * wf_find_control(const char *name)
{
struct wf_control *ct;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(ct, &wf_controls, link) {
if (!strcmp(ct->name, name)) {
if (wf_get_control(ct))
ct = NULL;
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return ct;
}
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return NULL;
}
EXPORT_SYMBOL_GPL(wf_find_control);
@@ -246,26 +294,46 @@ static void wf_sensor_release(struct kref *kref)
kfree(sr);
}
+static ssize_t wf_show_sensor(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr);
+ s32 val = 0;
+ int err;
+
+ err = sens->ops->get_value(sens, &val);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val));
+}
+
int wf_register_sensor(struct wf_sensor *new_sr)
{
struct wf_sensor *sr;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(sr, &wf_sensors, link) {
if (!strcmp(sr->name, new_sr->name)) {
printk(KERN_WARNING "windfarm: trying to register"
" duplicate sensor %s\n", sr->name);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return -EEXIST;
}
}
kref_init(&new_sr->ref);
list_add(&new_sr->link, &wf_sensors);
+ new_sr->attr.attr.name = new_sr->name;
+ new_sr->attr.attr.owner = THIS_MODULE;
+ new_sr->attr.attr.mode = 0444;
+ new_sr->attr.show = wf_show_sensor;
+ new_sr->attr.store = NULL;
+ device_create_file(&wf_platform_device.dev, &new_sr->attr);
+
DBG("wf: Registered sensor %s\n", new_sr->name);
wf_notify(WF_EVENT_NEW_SENSOR, new_sr);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return 0;
}
@@ -273,9 +341,9 @@ EXPORT_SYMBOL_GPL(wf_register_sensor);
void wf_unregister_sensor(struct wf_sensor *sr)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_del(&sr->link);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
DBG("wf: Unregistered sensor %s\n", sr->name);
@@ -287,16 +355,16 @@ struct wf_sensor * wf_find_sensor(const char *name)
{
struct wf_sensor *sr;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(sr, &wf_sensors, link) {
if (!strcmp(sr->name, name)) {
if (wf_get_sensor(sr))
sr = NULL;
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return sr;
}
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return NULL;
}
EXPORT_SYMBOL_GPL(wf_find_sensor);
@@ -329,7 +397,7 @@ int wf_register_client(struct notifier_block *nb)
struct wf_control *ct;
struct wf_sensor *sr;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
rc = notifier_chain_register(&wf_client_list, nb);
if (rc != 0)
goto bail;
@@ -341,19 +409,19 @@ int wf_register_client(struct notifier_block *nb)
if (wf_client_count == 1)
wf_start_thread();
bail:
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return rc;
}
EXPORT_SYMBOL_GPL(wf_register_client);
int wf_unregister_client(struct notifier_block *nb)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
notifier_chain_unregister(&wf_client_list, nb);
wf_client_count++;
if (wf_client_count == 0)
wf_stop_thread();
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return 0;
}
@@ -361,23 +429,23 @@ EXPORT_SYMBOL_GPL(wf_unregister_client);
void wf_set_overtemp(void)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
wf_overtemp++;
if (wf_overtemp == 1) {
printk(KERN_WARNING "windfarm: Overtemp condition detected !\n");
wf_overtemp_counter = 0;
wf_notify(WF_EVENT_OVERTEMP, NULL);
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
}
EXPORT_SYMBOL_GPL(wf_set_overtemp);
void wf_clear_overtemp(void)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
WARN_ON(wf_overtemp == 0);
if (wf_overtemp == 0) {
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return;
}
wf_overtemp--;
@@ -385,7 +453,7 @@ void wf_clear_overtemp(void)
printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n");
wf_notify(WF_EVENT_NORMALTEMP, NULL);
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
}
EXPORT_SYMBOL_GPL(wf_clear_overtemp);
@@ -395,14 +463,15 @@ int wf_is_overtemp(void)
}
EXPORT_SYMBOL_GPL(wf_is_overtemp);
-static struct platform_device wf_platform_device = {
- .name = "windfarm",
-};
-
static int __init windfarm_core_init(void)
{
DBG("wf: core loaded\n");
+ /* Don't register on old machines that use therm_pm72 for now */
+ if (machine_is_compatible("PowerMac7,2") ||
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
platform_device_register(&wf_platform_device);
return 0;
}
diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c
index 607dbaca69c9..81337cd16e80 100644
--- a/drivers/macintosh/windfarm_cpufreq_clamp.c
+++ b/drivers/macintosh/windfarm_cpufreq_clamp.c
@@ -8,6 +8,8 @@
#include <linux/wait.h>
#include <linux/cpufreq.h>
+#include <asm/prom.h>
+
#include "windfarm.h"
#define VERSION "0.3"
@@ -74,6 +76,12 @@ static int __init wf_cpufreq_clamp_init(void)
{
struct wf_control *clamp;
+ /* Don't register on old machines that use therm_pm72 for now */
+ if (machine_is_compatible("PowerMac7,2") ||
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
+
clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
if (clamp == NULL)
return -ENOMEM;
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 906d3ecae6e6..423bfa2432c0 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -25,7 +25,7 @@
#include "windfarm.h"
-#define VERSION "0.1"
+#define VERSION "0.2"
#undef DEBUG
@@ -113,6 +113,7 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
const char *loc)
{
struct wf_lm75_sensor *lm;
+ int rc;
DBG("wf_lm75: creating %s device at address 0x%02x\n",
ds1775 ? "ds1775" : "lm75", addr);
@@ -139,9 +140,11 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
lm->i2c.driver = &wf_lm75_driver;
strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1);
- if (i2c_attach_client(&lm->i2c)) {
- printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n",
- ds1775 ? "ds1775" : "lm75", lm->i2c.name);
+ rc = i2c_attach_client(&lm->i2c);
+ if (rc) {
+ printk(KERN_ERR "windfarm: failed to attach %s %s to i2c,"
+ " err %d\n", ds1775 ? "ds1775" : "lm75",
+ lm->i2c.name, rc);
goto fail;
}
@@ -175,16 +178,22 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
(dev = of_get_next_child(busnode, dev)) != NULL;) {
const char *loc =
get_property(dev, "hwsensor-location", NULL);
- u32 *reg = (u32 *)get_property(dev, "reg", NULL);
- DBG(" dev: %s... (loc: %p, reg: %p)\n", dev->name, loc, reg);
- if (loc == NULL || reg == NULL)
+ u8 addr;
+
+ /* We must re-match the adapter in order to properly check
+ * the channel on multibus setups
+ */
+ if (!pmac_i2c_match_adapter(dev, adapter))
+ continue;
+ addr = pmac_i2c_get_dev_addr(dev);
+ if (loc == NULL || addr == 0)
continue;
/* real lm75 */
if (device_is_compatible(dev, "lm75"))
- wf_lm75_create(adapter, *reg, 0, loc);
+ wf_lm75_create(adapter, addr, 0, loc);
/* ds1775 (compatible, better resolution */
else if (device_is_compatible(dev, "ds1775"))
- wf_lm75_create(adapter, *reg, 1, loc);
+ wf_lm75_create(adapter, addr, 1, loc);
}
return 0;
}
@@ -206,6 +215,11 @@ static int wf_lm75_detach(struct i2c_client *client)
static int __init wf_lm75_sensor_init(void)
{
+ /* Don't register on old machines that use therm_pm72 for now */
+ if (machine_is_compatible("PowerMac7,2") ||
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
return i2c_add_driver(&wf_lm75_driver);
}
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
new file mode 100644
index 000000000000..8e99d408fddd
--- /dev/null
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -0,0 +1,180 @@
+/*
+ * Windfarm PowerMac thermal control. MAX6690 sensor.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/prom.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "0.2"
+
+/* This currently only exports the external temperature sensor,
+ since that's all the control loops need. */
+
+/* Some MAX6690 register numbers */
+#define MAX6690_INTERNAL_TEMP 0
+#define MAX6690_EXTERNAL_TEMP 1
+
+struct wf_6690_sensor {
+ struct i2c_client i2c;
+ struct wf_sensor sens;
+};
+
+#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens)
+#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c)
+
+static int wf_max6690_attach(struct i2c_adapter *adapter);
+static int wf_max6690_detach(struct i2c_client *client);
+
+static struct i2c_driver wf_max6690_driver = {
+ .driver = {
+ .name = "wf_max6690",
+ },
+ .attach_adapter = wf_max6690_attach,
+ .detach_client = wf_max6690_detach,
+};
+
+static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_6690_sensor *max = wf_to_6690(sr);
+ s32 data;
+
+ if (max->i2c.adapter == NULL)
+ return -ENODEV;
+
+ /* chip gets initialized by firmware */
+ data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
+ if (data < 0)
+ return data;
+ *value = data << 16;
+ return 0;
+}
+
+static void wf_max6690_release(struct wf_sensor *sr)
+{
+ struct wf_6690_sensor *max = wf_to_6690(sr);
+
+ if (max->i2c.adapter) {
+ i2c_detach_client(&max->i2c);
+ max->i2c.adapter = NULL;
+ }
+ kfree(max);
+}
+
+static struct wf_sensor_ops wf_max6690_ops = {
+ .get_value = wf_max6690_get,
+ .release = wf_max6690_release,
+ .owner = THIS_MODULE,
+};
+
+static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
+{
+ struct wf_6690_sensor *max;
+ char *name = "backside-temp";
+
+ max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
+ if (max == NULL) {
+ printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
+ "no memory\n", name);
+ return;
+ }
+
+ max->sens.ops = &wf_max6690_ops;
+ max->sens.name = name;
+ max->i2c.addr = addr >> 1;
+ max->i2c.adapter = adapter;
+ max->i2c.driver = &wf_max6690_driver;
+ strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
+
+ if (i2c_attach_client(&max->i2c)) {
+ printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
+ goto fail;
+ }
+
+ if (wf_register_sensor(&max->sens)) {
+ i2c_detach_client(&max->i2c);
+ goto fail;
+ }
+
+ return;
+
+ fail:
+ kfree(max);
+}
+
+static int wf_max6690_attach(struct i2c_adapter *adapter)
+{
+ struct device_node *busnode, *dev = NULL;
+ struct pmac_i2c_bus *bus;
+ const char *loc;
+
+ bus = pmac_i2c_adapter_to_bus(adapter);
+ if (bus == NULL)
+ return -ENODEV;
+ busnode = pmac_i2c_get_bus_node(bus);
+
+ while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+ u8 addr;
+
+ /* We must re-match the adapter in order to properly check
+ * the channel on multibus setups
+ */
+ if (!pmac_i2c_match_adapter(dev, adapter))
+ continue;
+ if (!device_is_compatible(dev, "max6690"))
+ continue;
+ addr = pmac_i2c_get_dev_addr(dev);
+ loc = get_property(dev, "hwsensor-location", NULL);
+ if (loc == NULL || addr == 0)
+ continue;
+ printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
+ if (strcmp(loc, "BACKSIDE"))
+ continue;
+ wf_max6690_create(adapter, addr);
+ }
+
+ return 0;
+}
+
+static int wf_max6690_detach(struct i2c_client *client)
+{
+ struct wf_6690_sensor *max = i2c_to_6690(client);
+
+ max->i2c.adapter = NULL;
+ wf_unregister_sensor(&max->sens);
+
+ return 0;
+}
+
+static int __init wf_max6690_sensor_init(void)
+{
+ /* Don't register on old machines that use therm_pm72 for now */
+ if (machine_is_compatible("PowerMac7,2") ||
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
+ return i2c_add_driver(&wf_max6690_driver);
+}
+
+static void __exit wf_max6690_sensor_exit(void)
+{
+ i2c_del_driver(&wf_max6690_driver);
+}
+
+module_init(wf_max6690_sensor_init);
+module_exit(wf_max6690_sensor_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c
index 2e803b368757..f10efb28cae4 100644
--- a/drivers/macintosh/windfarm_pid.c
+++ b/drivers/macintosh/windfarm_pid.c
@@ -88,8 +88,8 @@ EXPORT_SYMBOL_GPL(wf_cpu_pid_init);
s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
{
- s64 error, integ, deriv, prop;
- s32 target, sval, adj;
+ s64 integ, deriv, prop;
+ s32 error, target, sval, adj;
int i, hlen = st->param.history_len;
/* Calculate error term */
@@ -117,7 +117,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
integ += st->errors[(st->index + hlen - i) % hlen];
integ *= st->param.interval;
integ *= st->param.gr;
- sval = st->param.tmax - ((integ >> 20) & 0xffffffff);
+ sval = st->param.tmax - (s32)(integ >> 20);
adj = min(st->param.ttarget, sval);
DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj);
@@ -129,7 +129,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
deriv *= st->param.gd;
/* Calculate proportional term */
- prop = (new_temp - adj);
+ prop = st->last_delta = (new_temp - adj);
prop *= st->param.gp;
DBG("deriv: %lx, prop: %lx\n", deriv, prop);
@@ -143,3 +143,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
return st->target;
}
EXPORT_SYMBOL_GPL(wf_cpu_pid_run);
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("PID algorithm for PowerMacs thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pid.h b/drivers/macintosh/windfarm_pid.h
index a364c2a2499c..bbccc22d42b8 100644
--- a/drivers/macintosh/windfarm_pid.h
+++ b/drivers/macintosh/windfarm_pid.h
@@ -72,6 +72,7 @@ struct wf_cpu_pid_state {
int index; /* index of current power */
int tindex; /* index of current temp */
s32 target; /* current target value */
+ s32 last_delta; /* last Tactual - Ttarget */
s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */
s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */
s32 temps[2]; /* temp. history buffer */
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
new file mode 100644
index 000000000000..ef66bf2778ec
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm112.c
@@ -0,0 +1,700 @@
+/*
+ * Windfarm PowerMac thermal control.
+ * Control loops for machines with SMU and PPC970MP processors.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+
+#define VERSION "0.2"
+
+#define DEBUG
+#undef LOTSA_DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+#ifdef LOTSA_DEBUG
+#define DBG_LOTS(args...) printk(args)
+#else
+#define DBG_LOTS(args...) do { } while(0)
+#endif
+
+/* define this to force CPU overtemp to 60 degree, useful for testing
+ * the overtemp code
+ */
+#undef HACKED_OVERTEMP
+
+/* We currently only handle 2 chips, 4 cores... */
+#define NR_CHIPS 2
+#define NR_CORES 4
+#define NR_CPU_FANS 3 * NR_CHIPS
+
+/* Controls and sensors */
+static struct wf_sensor *sens_cpu_temp[NR_CORES];
+static struct wf_sensor *sens_cpu_power[NR_CORES];
+static struct wf_sensor *hd_temp;
+static struct wf_sensor *slots_power;
+static struct wf_sensor *u4_temp;
+
+static struct wf_control *cpu_fans[NR_CPU_FANS];
+static char *cpu_fan_names[NR_CPU_FANS] = {
+ "cpu-rear-fan-0",
+ "cpu-rear-fan-1",
+ "cpu-front-fan-0",
+ "cpu-front-fan-1",
+ "cpu-pump-0",
+ "cpu-pump-1",
+};
+static struct wf_control *cpufreq_clamp;
+
+/* Second pump isn't required (and isn't actually present) */
+#define CPU_FANS_REQD (NR_CPU_FANS - 2)
+#define FIRST_PUMP 4
+#define LAST_PUMP 5
+
+/* We keep a temperature history for average calculation of 180s */
+#define CPU_TEMP_HIST_SIZE 180
+
+/* Scale factor for fan speed, *100 */
+static int cpu_fan_scale[NR_CPU_FANS] = {
+ 100,
+ 100,
+ 97, /* inlet fans run at 97% of exhaust fan */
+ 97,
+ 100, /* updated later */
+ 100, /* updated later */
+};
+
+static struct wf_control *backside_fan;
+static struct wf_control *slots_fan;
+static struct wf_control *drive_bay_fan;
+
+/* PID loop state */
+static struct wf_cpu_pid_state cpu_pid[NR_CORES];
+static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
+static int cpu_thist_pt;
+static s64 cpu_thist_total;
+static s32 cpu_all_tmax = 100 << 16;
+static int cpu_last_target;
+static struct wf_pid_state backside_pid;
+static int backside_tick;
+static struct wf_pid_state slots_pid;
+static int slots_started;
+static struct wf_pid_state drive_bay_pid;
+static int drive_bay_tick;
+
+static int nr_cores;
+static int have_all_controls;
+static int have_all_sensors;
+static int started;
+
+static int failure_state;
+#define FAILURE_SENSOR 1
+#define FAILURE_FAN 2
+#define FAILURE_PERM 4
+#define FAILURE_LOW_OVERTEMP 8
+#define FAILURE_HIGH_OVERTEMP 16
+
+/* Overtemp values */
+#define LOW_OVER_AVERAGE 0
+#define LOW_OVER_IMMEDIATE (10 << 16)
+#define LOW_OVER_CLEAR ((-10) << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+#define HIGH_OVER_AVERAGE (10 << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+
+
+/* Implementation... */
+static int create_cpu_loop(int cpu)
+{
+ int chip = cpu / 2;
+ int core = cpu & 1;
+ struct smu_sdbp_header *hdr;
+ struct smu_sdbp_cpupiddata *piddata;
+ struct wf_cpu_pid_param pid;
+ struct wf_control *main_fan = cpu_fans[0];
+ s32 tmax;
+ int fmin;
+
+ /* Get PID params from the appropriate SAT */
+ hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
+ if (hdr == NULL) {
+ printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
+ return -EINVAL;
+ }
+ piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
+
+ /* Get FVT params to get Tmax; if not found, assume default */
+ hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL);
+ if (hdr) {
+ struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1];
+ tmax = fvt->maxtemp << 16;
+ } else
+ tmax = 95 << 16; /* default to 95 degrees C */
+
+ /* We keep a global tmax for overtemp calculations */
+ if (tmax < cpu_all_tmax)
+ cpu_all_tmax = tmax;
+
+ /*
+ * Darwin has a minimum fan speed of 1000 rpm for the 4-way and
+ * 515 for the 2-way. That appears to be overkill, so for now,
+ * impose a minimum of 750 or 515.
+ */
+ fmin = (nr_cores > 2) ? 750 : 515;
+
+ /* Initialize PID loop */
+ pid.interval = 1; /* seconds */
+ pid.history_len = piddata->history_len;
+ pid.gd = piddata->gd;
+ pid.gp = piddata->gp;
+ pid.gr = piddata->gr / piddata->history_len;
+ pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8);
+ pid.ttarget = tmax - (piddata->target_temp_delta << 16);
+ pid.tmax = tmax;
+ pid.min = main_fan->ops->get_min(main_fan);
+ pid.max = main_fan->ops->get_max(main_fan);
+ if (pid.min < fmin)
+ pid.min = fmin;
+
+ wf_cpu_pid_init(&cpu_pid[cpu], &pid);
+ return 0;
+}
+
+static void cpu_max_all_fans(void)
+{
+ int i;
+
+ /* We max all CPU fans in case of a sensor error. We also do the
+ * cpufreq clamping now, even if it's supposedly done later by the
+ * generic code anyway, we do it earlier here to react faster
+ */
+ if (cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ for (i = 0; i < NR_CPU_FANS; ++i)
+ if (cpu_fans[i])
+ wf_control_set_max(cpu_fans[i]);
+}
+
+static int cpu_check_overtemp(s32 temp)
+{
+ int new_state = 0;
+ s32 t_avg, t_old;
+
+ /* First check for immediate overtemps */
+ if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
+ " temperature !\n");
+ }
+ if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " immediate CPU temperature !\n");
+ }
+
+ /* We calculate a history of max temperatures and use that for the
+ * overtemp management
+ */
+ t_old = cpu_thist[cpu_thist_pt];
+ cpu_thist[cpu_thist_pt] = temp;
+ cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
+ cpu_thist_total -= t_old;
+ cpu_thist_total += temp;
+ t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
+
+ DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
+ FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
+
+ /* Now check for average overtemps */
+ if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to average CPU"
+ " temperature !\n");
+ }
+ if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " average CPU temperature !\n");
+ }
+
+ /* Now handle overtemp conditions. We don't currently use the windfarm
+ * overtemp handling core as it's not fully suited to the needs of those
+ * new machine. This will be fixed later.
+ */
+ if (new_state) {
+ /* High overtemp -> immediate shutdown */
+ if (new_state & FAILURE_HIGH_OVERTEMP)
+ machine_power_off();
+ if ((failure_state & new_state) != new_state)
+ cpu_max_all_fans();
+ failure_state |= new_state;
+ } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
+ (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
+ printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
+ failure_state &= ~FAILURE_LOW_OVERTEMP;
+ }
+
+ return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
+}
+
+static void cpu_fans_tick(void)
+{
+ int err, cpu;
+ s32 greatest_delta = 0;
+ s32 temp, power, t_max = 0;
+ int i, t, target = 0;
+ struct wf_sensor *sr;
+ struct wf_control *ct;
+ struct wf_cpu_pid_state *sp;
+
+ DBG_LOTS(KERN_DEBUG);
+ for (cpu = 0; cpu < nr_cores; ++cpu) {
+ /* Get CPU core temperature */
+ sr = sens_cpu_temp[cpu];
+ err = sr->ops->get_value(sr, &temp);
+ if (err) {
+ DBG("\n");
+ printk(KERN_WARNING "windfarm: CPU %d temperature "
+ "sensor error %d\n", cpu, err);
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Keep track of highest temp */
+ t_max = max(t_max, temp);
+
+ /* Get CPU power */
+ sr = sens_cpu_power[cpu];
+ err = sr->ops->get_value(sr, &power);
+ if (err) {
+ DBG("\n");
+ printk(KERN_WARNING "windfarm: CPU %d power "
+ "sensor error %d\n", cpu, err);
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Run PID */
+ sp = &cpu_pid[cpu];
+ t = wf_cpu_pid_run(sp, power, temp);
+
+ if (cpu == 0 || sp->last_delta > greatest_delta) {
+ greatest_delta = sp->last_delta;
+ target = t;
+ }
+ DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ",
+ cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp));
+ }
+ DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max));
+
+ /* Darwin limits decrease to 20 per iteration */
+ if (target < (cpu_last_target - 20))
+ target = cpu_last_target - 20;
+ cpu_last_target = target;
+ for (cpu = 0; cpu < nr_cores; ++cpu)
+ cpu_pid[cpu].target = target;
+
+ /* Handle possible overtemps */
+ if (cpu_check_overtemp(t_max))
+ return;
+
+ /* Set fans */
+ for (i = 0; i < NR_CPU_FANS; ++i) {
+ ct = cpu_fans[i];
+ if (ct == NULL)
+ continue;
+ err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100);
+ if (err) {
+ printk(KERN_WARNING "windfarm: fan %s reports "
+ "error %d\n", ct->name, err);
+ failure_state |= FAILURE_FAN;
+ break;
+ }
+ }
+}
+
+/* Backside/U4 fan */
+static struct wf_pid_param backside_param = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 48 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 64 << 16,
+ .additive = 1,
+};
+
+static void backside_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!backside_fan || !u4_temp)
+ return;
+ if (!backside_tick) {
+ /* first time; initialize things */
+ printk(KERN_INFO "windfarm: Backside control loop started.\n");
+ backside_param.min = backside_fan->ops->get_min(backside_fan);
+ backside_param.max = backside_fan->ops->get_max(backside_fan);
+ wf_pid_init(&backside_pid, &backside_param);
+ backside_tick = 1;
+ }
+ if (--backside_tick > 0)
+ return;
+ backside_tick = backside_pid.param.interval;
+
+ err = u4_temp->ops->get_value(u4_temp, &temp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(backside_fan);
+ return;
+ }
+ speed = wf_pid_run(&backside_pid, temp);
+ DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = backside_fan->ops->set_value(backside_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+/* Drive bay fan */
+static struct wf_pid_param drive_bay_prm = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 30 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 40 << 16,
+ .additive = 1,
+};
+
+static void drive_bay_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!drive_bay_fan || !hd_temp)
+ return;
+ if (!drive_bay_tick) {
+ /* first time; initialize things */
+ printk(KERN_INFO "windfarm: Drive bay control loop started.\n");
+ drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan);
+ drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan);
+ wf_pid_init(&drive_bay_pid, &drive_bay_prm);
+ drive_bay_tick = 1;
+ }
+ if (--drive_bay_tick > 0)
+ return;
+ drive_bay_tick = drive_bay_pid.param.interval;
+
+ err = hd_temp->ops->get_value(hd_temp, &temp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: drive bay temp sensor "
+ "error %d\n", err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(drive_bay_fan);
+ return;
+ }
+ speed = wf_pid_run(&drive_bay_pid, temp);
+ DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = drive_bay_fan->ops->set_value(drive_bay_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+/* PCI slots area fan */
+/* This makes the fan speed proportional to the power consumed */
+static struct wf_pid_param slots_param = {
+ .interval = 1,
+ .history_len = 2,
+ .gd = 0,
+ .gp = 0,
+ .gr = 0x1277952,
+ .itarget = 0,
+ .min = 1560,
+ .max = 3510,
+};
+
+static void slots_fan_tick(void)
+{
+ s32 power;
+ int speed;
+ int err;
+
+ if (!slots_fan || !slots_power)
+ return;
+ if (!slots_started) {
+ /* first time; initialize things */
+ printk(KERN_INFO "windfarm: Slots control loop started.\n");
+ wf_pid_init(&slots_pid, &slots_param);
+ slots_started = 1;
+ }
+
+ err = slots_power->ops->get_value(slots_power, &power);
+ if (err) {
+ printk(KERN_WARNING "windfarm: slots power sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(slots_fan);
+ return;
+ }
+ speed = wf_pid_run(&slots_pid, power);
+ DBG_LOTS("slots PID power=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(power), speed);
+
+ err = slots_fan->ops->set_value(slots_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: slots fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+static void set_fail_state(void)
+{
+ int i;
+
+ if (cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ for (i = 0; i < NR_CPU_FANS; ++i)
+ if (cpu_fans[i])
+ wf_control_set_max(cpu_fans[i]);
+ if (backside_fan)
+ wf_control_set_max(backside_fan);
+ if (slots_fan)
+ wf_control_set_max(slots_fan);
+ if (drive_bay_fan)
+ wf_control_set_max(drive_bay_fan);
+}
+
+static void pm112_tick(void)
+{
+ int i, last_failure;
+
+ if (!started) {
+ started = 1;
+ printk(KERN_INFO "windfarm: CPUs control loops started.\n");
+ for (i = 0; i < nr_cores; ++i) {
+ if (create_cpu_loop(i) < 0) {
+ failure_state = FAILURE_PERM;
+ set_fail_state();
+ break;
+ }
+ }
+ DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
+
+#ifdef HACKED_OVERTEMP
+ cpu_all_tmax = 60 << 16;
+#endif
+ }
+
+ /* Permanent failure, bail out */
+ if (failure_state & FAILURE_PERM)
+ return;
+ /* Clear all failure bits except low overtemp which will be eventually
+ * cleared by the control loop itself
+ */
+ last_failure = failure_state;
+ failure_state &= FAILURE_LOW_OVERTEMP;
+ cpu_fans_tick();
+ backside_fan_tick();
+ slots_fan_tick();
+ drive_bay_fan_tick();
+
+ DBG_LOTS("last_failure: 0x%x, failure_state: %x\n",
+ last_failure, failure_state);
+
+ /* Check for failures. Any failure causes cpufreq clamping */
+ if (failure_state && last_failure == 0 && cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ if (failure_state == 0 && last_failure && cpufreq_clamp)
+ wf_control_set_min(cpufreq_clamp);
+
+ /* That's it for now, we might want to deal with other failures
+ * differently in the future though
+ */
+}
+
+static void pm112_new_control(struct wf_control *ct)
+{
+ int i, max_exhaust;
+
+ if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
+ if (wf_get_control(ct) == 0)
+ cpufreq_clamp = ct;
+ }
+
+ for (i = 0; i < NR_CPU_FANS; ++i) {
+ if (!strcmp(ct->name, cpu_fan_names[i])) {
+ if (cpu_fans[i] == NULL && wf_get_control(ct) == 0)
+ cpu_fans[i] = ct;
+ break;
+ }
+ }
+ if (i >= NR_CPU_FANS) {
+ /* not a CPU fan, try the others */
+ if (!strcmp(ct->name, "backside-fan")) {
+ if (backside_fan == NULL && wf_get_control(ct) == 0)
+ backside_fan = ct;
+ } else if (!strcmp(ct->name, "slots-fan")) {
+ if (slots_fan == NULL && wf_get_control(ct) == 0)
+ slots_fan = ct;
+ } else if (!strcmp(ct->name, "drive-bay-fan")) {
+ if (drive_bay_fan == NULL && wf_get_control(ct) == 0)
+ drive_bay_fan = ct;
+ }
+ return;
+ }
+
+ for (i = 0; i < CPU_FANS_REQD; ++i)
+ if (cpu_fans[i] == NULL)
+ return;
+
+ /* work out pump scaling factors */
+ max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]);
+ for (i = FIRST_PUMP; i <= LAST_PUMP; ++i)
+ if ((ct = cpu_fans[i]) != NULL)
+ cpu_fan_scale[i] =
+ ct->ops->get_max(ct) * 100 / max_exhaust;
+
+ have_all_controls = 1;
+}
+
+static void pm112_new_sensor(struct wf_sensor *sr)
+{
+ unsigned int i;
+
+ if (!strncmp(sr->name, "cpu-temp-", 9)) {
+ i = sr->name[9] - '0';
+ if (sr->name[10] == 0 && i < NR_CORES &&
+ sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0)
+ sens_cpu_temp[i] = sr;
+
+ } else if (!strncmp(sr->name, "cpu-power-", 10)) {
+ i = sr->name[10] - '0';
+ if (sr->name[11] == 0 && i < NR_CORES &&
+ sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0)
+ sens_cpu_power[i] = sr;
+ } else if (!strcmp(sr->name, "hd-temp")) {
+ if (hd_temp == NULL && wf_get_sensor(sr) == 0)
+ hd_temp = sr;
+ } else if (!strcmp(sr->name, "slots-power")) {
+ if (slots_power == NULL && wf_get_sensor(sr) == 0)
+ slots_power = sr;
+ } else if (!strcmp(sr->name, "backside-temp")) {
+ if (u4_temp == NULL && wf_get_sensor(sr) == 0)
+ u4_temp = sr;
+ } else
+ return;
+
+ /* check if we have all the sensors we need */
+ for (i = 0; i < nr_cores; ++i)
+ if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL)
+ return;
+
+ have_all_sensors = 1;
+}
+
+static int pm112_wf_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ switch (event) {
+ case WF_EVENT_NEW_SENSOR:
+ pm112_new_sensor(data);
+ break;
+ case WF_EVENT_NEW_CONTROL:
+ pm112_new_control(data);
+ break;
+ case WF_EVENT_TICK:
+ if (have_all_controls && have_all_sensors)
+ pm112_tick();
+ }
+ return 0;
+}
+
+static struct notifier_block pm112_events = {
+ .notifier_call = pm112_wf_notify,
+};
+
+static int wf_pm112_probe(struct device *dev)
+{
+ wf_register_client(&pm112_events);
+ return 0;
+}
+
+static int wf_pm112_remove(struct device *dev)
+{
+ wf_unregister_client(&pm112_events);
+ /* should release all sensors and controls */
+ return 0;
+}
+
+static struct device_driver wf_pm112_driver = {
+ .name = "windfarm",
+ .bus = &platform_bus_type,
+ .probe = wf_pm112_probe,
+ .remove = wf_pm112_remove,
+};
+
+static int __init wf_pm112_init(void)
+{
+ struct device_node *cpu;
+
+ if (!machine_is_compatible("PowerMac11,2"))
+ return -ENODEV;
+
+ /* Count the number of CPU cores */
+ nr_cores = 0;
+ for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
+ ++nr_cores;
+
+ printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n");
+ driver_register(&wf_pm112_driver);
+ return 0;
+}
+
+static void __exit wf_pm112_exit(void)
+{
+ driver_unregister(&wf_pm112_driver);
+}
+
+module_init(wf_pm112_init);
+module_exit(wf_pm112_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index eb69a601e765..f1df6efcbe68 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -538,45 +538,6 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
}
}
-
-/*
- * ****** Attributes ******
- *
- */
-
-#define BUILD_SHOW_FUNC_FIX(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- ssize_t r; \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \
- return r; \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-
-#define BUILD_SHOW_FUNC_INT(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- return sprintf(buf, "%d", val); \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main);
-BUILD_SHOW_FUNC_INT(sys_fan, fan_system);
-BUILD_SHOW_FUNC_INT(hd_fan, fan_hd);
-
-BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp);
-BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power);
-BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp);
-
/*
* ****** Setup / Init / Misc ... ******
*
@@ -654,17 +615,13 @@ static void wf_smu_new_control(struct wf_control *ct)
return;
if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_cpu_main = ct;
- device_create_file(wf_smu_dev, &dev_attr_cpu_fan);
- }
}
if (fan_system == NULL && !strcmp(ct->name, "system-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_system = ct;
- device_create_file(wf_smu_dev, &dev_attr_sys_fan);
- }
}
if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
@@ -683,10 +640,8 @@ static void wf_smu_new_control(struct wf_control *ct)
}
if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_hd = ct;
- device_create_file(wf_smu_dev, &dev_attr_hd_fan);
- }
}
if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp)
@@ -699,24 +654,18 @@ static void wf_smu_new_sensor(struct wf_sensor *sr)
return;
if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_power = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_power);
- }
}
if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_temp);
- }
}
if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_hd_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_hd_temp);
- }
}
if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp)
@@ -794,32 +743,20 @@ static int wf_smu_remove(struct device *ddev)
* with that except by adding locks all over... I'll do that
* eventually but heh, who ever rmmod this module anyway ?
*/
- if (sensor_cpu_power) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_power);
+ if (sensor_cpu_power)
wf_put_sensor(sensor_cpu_power);
- }
- if (sensor_cpu_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_temp);
+ if (sensor_cpu_temp)
wf_put_sensor(sensor_cpu_temp);
- }
- if (sensor_hd_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_temp);
+ if (sensor_hd_temp)
wf_put_sensor(sensor_hd_temp);
- }
/* Release all controls */
- if (fan_cpu_main) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_fan);
+ if (fan_cpu_main)
wf_put_control(fan_cpu_main);
- }
- if (fan_hd) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_fan);
+ if (fan_hd)
wf_put_control(fan_hd);
- }
- if (fan_system) {
- device_remove_file(wf_smu_dev, &dev_attr_sys_fan);
+ if (fan_system)
wf_put_control(fan_system);
- }
if (cpufreq_clamp)
wf_put_control(cpufreq_clamp);
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index 43243cf7410b..0d6372e96d32 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -458,45 +458,6 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
/*
- * ****** Attributes ******
- *
- */
-
-#define BUILD_SHOW_FUNC_FIX(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- ssize_t r; \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \
- return r; \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-
-#define BUILD_SHOW_FUNC_INT(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- return sprintf(buf, "%d", val); \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main);
-BUILD_SHOW_FUNC_INT(hd_fan, fan_hd);
-BUILD_SHOW_FUNC_INT(slots_fan, fan_slots);
-
-BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp);
-BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power);
-BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp);
-BUILD_SHOW_FUNC_FIX(slots_power, sensor_slots_power);
-
-/*
* ****** Setup / Init / Misc ... ******
*
*/
@@ -581,10 +542,8 @@ static void wf_smu_new_control(struct wf_control *ct)
return;
if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_cpu_main = ct;
- device_create_file(wf_smu_dev, &dev_attr_cpu_fan);
- }
}
if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) {
@@ -603,17 +562,13 @@ static void wf_smu_new_control(struct wf_control *ct)
}
if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_hd = ct;
- device_create_file(wf_smu_dev, &dev_attr_hd_fan);
- }
}
if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_slots = ct;
- device_create_file(wf_smu_dev, &dev_attr_slots_fan);
- }
}
if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd &&
@@ -627,31 +582,23 @@ static void wf_smu_new_sensor(struct wf_sensor *sr)
return;
if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_power = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_power);
- }
}
if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_temp);
- }
}
if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_hd_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_hd_temp);
- }
}
if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_slots_power = sr;
- device_create_file(wf_smu_dev, &dev_attr_slots_power);
- }
}
if (sensor_cpu_power && sensor_cpu_temp &&
@@ -720,40 +667,26 @@ static int wf_smu_remove(struct device *ddev)
* with that except by adding locks all over... I'll do that
* eventually but heh, who ever rmmod this module anyway ?
*/
- if (sensor_cpu_power) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_power);
+ if (sensor_cpu_power)
wf_put_sensor(sensor_cpu_power);
- }
- if (sensor_cpu_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_temp);
+ if (sensor_cpu_temp)
wf_put_sensor(sensor_cpu_temp);
- }
- if (sensor_hd_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_temp);
+ if (sensor_hd_temp)
wf_put_sensor(sensor_hd_temp);
- }
- if (sensor_slots_power) {
- device_remove_file(wf_smu_dev, &dev_attr_slots_power);
+ if (sensor_slots_power)
wf_put_sensor(sensor_slots_power);
- }
/* Release all controls */
- if (fan_cpu_main) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_fan);
+ if (fan_cpu_main)
wf_put_control(fan_cpu_main);
- }
if (fan_cpu_second)
wf_put_control(fan_cpu_second);
if (fan_cpu_third)
wf_put_control(fan_cpu_third);
- if (fan_hd) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_fan);
+ if (fan_hd)
wf_put_control(fan_hd);
- }
- if (fan_slots) {
- device_remove_file(wf_smu_dev, &dev_attr_slots_fan);
+ if (fan_slots)
wf_put_control(fan_slots);
- }
if (cpufreq_clamp)
wf_put_control(cpufreq_clamp);
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 4d811600bdab..a9e88edc0c72 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -24,7 +24,7 @@
#include "windfarm.h"
-#define VERSION "0.3"
+#define VERSION "0.4"
#undef DEBUG
@@ -34,6 +34,8 @@
#define DBG(args...) do { } while(0)
#endif
+static int smu_supports_new_fans_ops = 1;
+
/*
* SMU fans control object
*/
@@ -59,23 +61,49 @@ static int smu_set_fan(int pwm, u8 id, u16 value)
/* Fill SMU command structure */
cmd.cmd = SMU_CMD_FAN_COMMAND;
- cmd.data_len = 14;
+
+ /* The SMU has an "old" and a "new" way of setting the fan speed
+ * Unfortunately, I found no reliable way to know which one works
+ * on a given machine model. After some investigations it appears
+ * that MacOS X just tries the new one, and if it fails fallbacks
+ * to the old ones ... Ugh.
+ */
+ retry:
+ if (smu_supports_new_fans_ops) {
+ buffer[0] = 0x30;
+ buffer[1] = id;
+ *((u16 *)(&buffer[2])) = value;
+ cmd.data_len = 4;
+ } else {
+ if (id > 7)
+ return -EINVAL;
+ /* Fill argument buffer */
+ memset(buffer, 0, 16);
+ buffer[0] = pwm ? 0x10 : 0x00;
+ buffer[1] = 0x01 << id;
+ *((u16 *)&buffer[2 + id * 2]) = value;
+ cmd.data_len = 14;
+ }
+
cmd.reply_len = 16;
cmd.data_buf = cmd.reply_buf = buffer;
cmd.status = 0;
cmd.done = smu_done_complete;
cmd.misc = &comp;
- /* Fill argument buffer */
- memset(buffer, 0, 16);
- buffer[0] = pwm ? 0x10 : 0x00;
- buffer[1] = 0x01 << id;
- *((u16 *)&buffer[2 + id * 2]) = value;
-
rc = smu_queue_cmd(&cmd);
if (rc)
return rc;
wait_for_completion(&comp);
+
+ /* Handle fallback (see coment above) */
+ if (cmd.status != 0 && smu_supports_new_fans_ops) {
+ printk(KERN_WARNING "windfarm: SMU failed new fan command "
+ "falling back to old method\n");
+ smu_supports_new_fans_ops = 0;
+ goto retry;
+ }
+
return cmd.status;
}
@@ -158,19 +186,29 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
/* Names used on desktop models */
if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") ||
- !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan"))
+ !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") ||
+ !strcmp(l, "CPU A EXHAUST"))
fct->ctrl.name = "cpu-rear-fan-0";
- else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1"))
+ else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") ||
+ !strcmp(l, "CPU B EXHAUST"))
fct->ctrl.name = "cpu-rear-fan-1";
else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") ||
- !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan"))
+ !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") ||
+ !strcmp(l, "CPU A INTAKE"))
fct->ctrl.name = "cpu-front-fan-0";
- else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1"))
+ else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") ||
+ !strcmp(l, "CPU B INTAKE"))
fct->ctrl.name = "cpu-front-fan-1";
- else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan"))
+ else if (!strcmp(l, "CPU A PUMP"))
+ fct->ctrl.name = "cpu-pump-0";
+ else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") ||
+ !strcmp(l, "EXPANSION SLOTS INTAKE"))
fct->ctrl.name = "slots-fan";
- else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay"))
+ else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") ||
+ !strcmp(l, "DRIVE BAY A INTAKE"))
fct->ctrl.name = "drive-bay-fan";
+ else if (!strcmp(l, "BACKSIDE"))
+ fct->ctrl.name = "backside-fan";
/* Names used on iMac models */
if (!strcmp(l, "System Fan") || !strcmp(l, "System fan"))
@@ -223,7 +261,8 @@ static int __init smu_controls_init(void)
/* Look for RPM fans */
for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;)
- if (!strcmp(fans->name, "rpm-fans"))
+ if (!strcmp(fans->name, "rpm-fans") ||
+ device_is_compatible(fans, "smu-rpm-fans"))
break;
for (fan = NULL;
fans && (fan = of_get_next_child(fans, fan)) != NULL;) {
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
new file mode 100644
index 000000000000..24e51d5e97fc
--- /dev/null
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -0,0 +1,419 @@
+/*
+ * Windfarm PowerMac thermal control. SMU "satellite" controller sensors.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * Released under the terms of the GNU GPL v2.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/semaphore.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "0.2"
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+/* If the cache is older than 800ms we'll refetch it */
+#define MAX_AGE msecs_to_jiffies(800)
+
+struct wf_sat {
+ int nr;
+ atomic_t refcnt;
+ struct semaphore mutex;
+ unsigned long last_read; /* jiffies when cache last updated */
+ u8 cache[16];
+ struct i2c_client i2c;
+ struct device_node *node;
+};
+
+static struct wf_sat *sats[2];
+
+struct wf_sat_sensor {
+ int index;
+ int index2; /* used for power sensors */
+ int shift;
+ struct wf_sat *sat;
+ struct wf_sensor sens;
+};
+
+#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens)
+#define i2c_to_sat(c) container_of(c, struct wf_sat, i2c)
+
+static int wf_sat_attach(struct i2c_adapter *adapter);
+static int wf_sat_detach(struct i2c_client *client);
+
+static struct i2c_driver wf_sat_driver = {
+ .driver = {
+ .name = "wf_smu_sat",
+ },
+ .attach_adapter = wf_sat_attach,
+ .detach_client = wf_sat_detach,
+};
+
+/*
+ * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested
+ * length down to the low-level driver, so we use this, which
+ * works well enough with the SMU i2c driver code...
+ */
+static int sat_read_block(struct i2c_client *client, u8 command,
+ u8 *values, int len)
+{
+ union i2c_smbus_data data;
+ int err;
+
+ data.block[0] = len;
+ err = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
+ &data);
+ if (!err)
+ memcpy(values, data.block, len);
+ return err;
+}
+
+struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
+ unsigned int *size)
+{
+ struct wf_sat *sat;
+ int err;
+ unsigned int i, len;
+ u8 *buf;
+ u8 data[4];
+
+ /* TODO: Add the resulting partition to the device-tree */
+
+ if (sat_id > 1 || (sat = sats[sat_id]) == NULL)
+ return NULL;
+
+ err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8);
+ if (err) {
+ printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err);
+ return NULL;
+ }
+
+ len = i2c_smbus_read_word_data(&sat->i2c, 9);
+ if (len < 0) {
+ printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
+ return NULL;
+ }
+ if (len == 0) {
+ printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id);
+ return NULL;
+ }
+
+ len = le16_to_cpu(len);
+ len = (len + 3) & ~3;
+ buf = kmalloc(len, GFP_KERNEL);
+ if (buf == NULL)
+ return NULL;
+
+ for (i = 0; i < len; i += 4) {
+ err = sat_read_block(&sat->i2c, 0xa, data, 4);
+ if (err) {
+ printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
+ err);
+ goto fail;
+ }
+ buf[i] = data[1];
+ buf[i+1] = data[0];
+ buf[i+2] = data[3];
+ buf[i+3] = data[2];
+ }
+#ifdef DEBUG
+ DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id);
+ for (i = 0; i < len; ++i)
+ DBG(" %x", buf[i]);
+ DBG("\n");
+#endif
+
+ if (size)
+ *size = len;
+ return (struct smu_sdbp_header *) buf;
+
+ fail:
+ kfree(buf);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(smu_sat_get_sdb_partition);
+
+/* refresh the cache */
+static int wf_sat_read_cache(struct wf_sat *sat)
+{
+ int err;
+
+ err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16);
+ if (err)
+ return err;
+ sat->last_read = jiffies;
+#ifdef LOTSA_DEBUG
+ {
+ int i;
+ DBG(KERN_DEBUG "wf_sat_get: data is");
+ for (i = 0; i < 16; ++i)
+ DBG(" %.2x", sat->cache[i]);
+ DBG("\n");
+ }
+#endif
+ return 0;
+}
+
+static int wf_sat_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_sat_sensor *sens = wf_to_sat(sr);
+ struct wf_sat *sat = sens->sat;
+ int i, err;
+ s32 val;
+
+ if (sat->i2c.adapter == NULL)
+ return -ENODEV;
+
+ down(&sat->mutex);
+ if (time_after(jiffies, (sat->last_read + MAX_AGE))) {
+ err = wf_sat_read_cache(sat);
+ if (err)
+ goto fail;
+ }
+
+ i = sens->index * 2;
+ val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift;
+ if (sens->index2 >= 0) {
+ i = sens->index2 * 2;
+ /* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */
+ val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4;
+ }
+
+ *value = val;
+ err = 0;
+
+ fail:
+ up(&sat->mutex);
+ return err;
+}
+
+static void wf_sat_release(struct wf_sensor *sr)
+{
+ struct wf_sat_sensor *sens = wf_to_sat(sr);
+ struct wf_sat *sat = sens->sat;
+
+ if (atomic_dec_and_test(&sat->refcnt)) {
+ if (sat->i2c.adapter) {
+ i2c_detach_client(&sat->i2c);
+ sat->i2c.adapter = NULL;
+ }
+ if (sat->nr >= 0)
+ sats[sat->nr] = NULL;
+ kfree(sat);
+ }
+ kfree(sens);
+}
+
+static struct wf_sensor_ops wf_sat_ops = {
+ .get_value = wf_sat_get,
+ .release = wf_sat_release,
+ .owner = THIS_MODULE,
+};
+
+static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
+{
+ struct wf_sat *sat;
+ struct wf_sat_sensor *sens;
+ u32 *reg;
+ char *loc, *type;
+ u8 addr, chip, core;
+ struct device_node *child;
+ int shift, cpu, index;
+ char *name;
+ int vsens[2], isens[2];
+
+ reg = (u32 *) get_property(dev, "reg", NULL);
+ if (reg == NULL)
+ return;
+ addr = *reg;
+ DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
+
+ sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL);
+ if (sat == NULL)
+ return;
+ sat->nr = -1;
+ sat->node = of_node_get(dev);
+ atomic_set(&sat->refcnt, 0);
+ init_MUTEX(&sat->mutex);
+ sat->i2c.addr = (addr >> 1) & 0x7f;
+ sat->i2c.adapter = adapter;
+ sat->i2c.driver = &wf_sat_driver;
+ strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1);
+
+ if (i2c_attach_client(&sat->i2c)) {
+ printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
+ goto fail;
+ }
+
+ vsens[0] = vsens[1] = -1;
+ isens[0] = isens[1] = -1;
+ child = NULL;
+ while ((child = of_get_next_child(dev, child)) != NULL) {
+ reg = (u32 *) get_property(child, "reg", NULL);
+ type = get_property(child, "device_type", NULL);
+ loc = get_property(child, "location", NULL);
+ if (reg == NULL || loc == NULL)
+ continue;
+
+ /* the cooked sensors are between 0x30 and 0x37 */
+ if (*reg < 0x30 || *reg > 0x37)
+ continue;
+ index = *reg - 0x30;
+
+ /* expect location to be CPU [AB][01] ... */
+ if (strncmp(loc, "CPU ", 4) != 0)
+ continue;
+ chip = loc[4] - 'A';
+ core = loc[5] - '0';
+ if (chip > 1 || core > 1) {
+ printk(KERN_ERR "wf_sat_create: don't understand "
+ "location %s for %s\n", loc, child->full_name);
+ continue;
+ }
+ cpu = 2 * chip + core;
+ if (sat->nr < 0)
+ sat->nr = chip;
+ else if (sat->nr != chip) {
+ printk(KERN_ERR "wf_sat_create: can't cope with "
+ "multiple CPU chips on one SAT (%s)\n", loc);
+ continue;
+ }
+
+ if (strcmp(type, "voltage-sensor") == 0) {
+ name = "cpu-voltage";
+ shift = 4;
+ vsens[core] = index;
+ } else if (strcmp(type, "current-sensor") == 0) {
+ name = "cpu-current";
+ shift = 8;
+ isens[core] = index;
+ } else if (strcmp(type, "temp-sensor") == 0) {
+ name = "cpu-temp";
+ shift = 10;
+ } else
+ continue; /* hmmm shouldn't happen */
+
+ /* the +16 is enough for "cpu-voltage-n" */
+ sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL);
+ if (sens == NULL) {
+ printk(KERN_ERR "wf_sat_create: couldn't create "
+ "%s sensor %d (no memory)\n", name, cpu);
+ continue;
+ }
+ sens->index = index;
+ sens->index2 = -1;
+ sens->shift = shift;
+ sens->sat = sat;
+ atomic_inc(&sat->refcnt);
+ sens->sens.ops = &wf_sat_ops;
+ sens->sens.name = (char *) (sens + 1);
+ snprintf(sens->sens.name, 16, "%s-%d", name, cpu);
+
+ if (wf_register_sensor(&sens->sens)) {
+ atomic_dec(&sat->refcnt);
+ kfree(sens);
+ }
+ }
+
+ /* make the power sensors */
+ for (core = 0; core < 2; ++core) {
+ if (vsens[core] < 0 || isens[core] < 0)
+ continue;
+ cpu = 2 * sat->nr + core;
+ sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL);
+ if (sens == NULL) {
+ printk(KERN_ERR "wf_sat_create: couldn't create power "
+ "sensor %d (no memory)\n", cpu);
+ continue;
+ }
+ sens->index = vsens[core];
+ sens->index2 = isens[core];
+ sens->shift = 0;
+ sens->sat = sat;
+ atomic_inc(&sat->refcnt);
+ sens->sens.ops = &wf_sat_ops;
+ sens->sens.name = (char *) (sens + 1);
+ snprintf(sens->sens.name, 16, "cpu-power-%d", cpu);
+
+ if (wf_register_sensor(&sens->sens)) {
+ atomic_dec(&sat->refcnt);
+ kfree(sens);
+ }
+ }
+
+ if (sat->nr >= 0)
+ sats[sat->nr] = sat;
+
+ return;
+
+ fail:
+ kfree(sat);
+}
+
+static int wf_sat_attach(struct i2c_adapter *adapter)
+{
+ struct device_node *busnode, *dev = NULL;
+ struct pmac_i2c_bus *bus;
+
+ bus = pmac_i2c_adapter_to_bus(adapter);
+ if (bus == NULL)
+ return -ENODEV;
+ busnode = pmac_i2c_get_bus_node(bus);
+
+ while ((dev = of_get_next_child(busnode, dev)) != NULL)
+ if (device_is_compatible(dev, "smu-sat"))
+ wf_sat_create(adapter, dev);
+ return 0;
+}
+
+static int wf_sat_detach(struct i2c_client *client)
+{
+ struct wf_sat *sat = i2c_to_sat(client);
+
+ /* XXX TODO */
+
+ sat->i2c.adapter = NULL;
+ return 0;
+}
+
+static int __init sat_sensors_init(void)
+{
+ int err;
+
+ err = i2c_add_driver(&wf_sat_driver);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static void __exit sat_sensors_exit(void)
+{
+ i2c_del_driver(&wf_sat_driver);
+}
+
+module_init(sat_sensors_init);
+/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c
index 1a00d9c75a23..bed25dcf8a1e 100644
--- a/drivers/macintosh/windfarm_smu_sensors.c
+++ b/drivers/macintosh/windfarm_smu_sensors.c
@@ -220,14 +220,29 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node)
!strcmp(l, "CPU T-Diode")) {
ads->sens.ops = &smu_cputemp_ops;
ads->sens.name = "cpu-temp";
+ if (cpudiode == NULL) {
+ DBG("wf: cpudiode partition (%02x) not found\n",
+ SMU_SDB_CPUDIODE_ID);
+ goto fail;
+ }
} else if (!strcmp(c, "current-sensor") &&
!strcmp(l, "CPU Current")) {
ads->sens.ops = &smu_cpuamp_ops;
ads->sens.name = "cpu-current";
+ if (cpuvcp == NULL) {
+ DBG("wf: cpuvcp partition (%02x) not found\n",
+ SMU_SDB_CPUVCP_ID);
+ goto fail;
+ }
} else if (!strcmp(c, "voltage-sensor") &&
!strcmp(l, "CPU Voltage")) {
ads->sens.ops = &smu_cpuvolt_ops;
ads->sens.name = "cpu-voltage";
+ if (cpuvcp == NULL) {
+ DBG("wf: cpuvcp partition (%02x) not found\n",
+ SMU_SDB_CPUVCP_ID);
+ goto fail;
+ }
} else if (!strcmp(c, "power-sensor") &&
!strcmp(l, "Slots Power")) {
ads->sens.ops = &smu_slotspow_ops;
@@ -365,29 +380,22 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps)
return NULL;
}
-static int smu_fetch_param_partitions(void)
+static void smu_fetch_param_partitions(void)
{
struct smu_sdbp_header *hdr;
/* Get CPU voltage/current/power calibration data */
hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL);
- if (hdr == NULL) {
- DBG("wf: cpuvcp partition (%02x) not found\n",
- SMU_SDB_CPUVCP_ID);
- return -ENODEV;
+ if (hdr != NULL) {
+ cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1];
+ /* Keep version around */
+ cpuvcp_version = hdr->version;
}
- cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1];
- /* Keep version around */
- cpuvcp_version = hdr->version;
/* Get CPU diode calibration data */
hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL);
- if (hdr == NULL) {
- DBG("wf: cpudiode partition (%02x) not found\n",
- SMU_SDB_CPUDIODE_ID);
- return -ENODEV;
- }
- cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1];
+ if (hdr != NULL)
+ cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1];
/* Get slots power calibration data if any */
hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL);
@@ -398,23 +406,18 @@ static int smu_fetch_param_partitions(void)
hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL);
if (hdr != NULL)
debugswitches = (u8 *)&hdr[1];
-
- return 0;
}
static int __init smu_sensors_init(void)
{
struct device_node *smu, *sensors, *s;
struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL;
- int rc;
if (!smu_present())
return -ENODEV;
/* Get parameters partitions */
- rc = smu_fetch_param_partitions();
- if (rc)
- return rc;
+ smu_fetch_param_partitions();
smu = of_find_node_by_type(NULL, "smu");
if (smu == NULL)
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index ab89278a56bf..697aacafb02a 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -103,9 +103,15 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -EINVAL;
}
+ if (((uint32_t)ti->len) & (chunk_size - 1)) {
+ ti->error = "dm-stripe: Target length not divisible by "
+ "chunk size";
+ return -EINVAL;
+ }
+
width = ti->len;
if (sector_div(width, stripes)) {
- ti->error = "dm-stripe: Target length not divisable by "
+ ti->error = "dm-stripe: Target length not divisible by "
"number of stripes";
return -EINVAL;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e9adeb9d172f..745ca1f67b14 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -849,10 +849,16 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
static void free_dev(struct mapped_device *md)
{
- free_minor(md->disk->first_minor);
+ unsigned int minor = md->disk->first_minor;
+
+ if (md->suspended_bdev) {
+ thaw_bdev(md->suspended_bdev, NULL);
+ bdput(md->suspended_bdev);
+ }
mempool_destroy(md->tio_pool);
mempool_destroy(md->io_pool);
del_gendisk(md->disk);
+ free_minor(minor);
put_disk(md->disk);
blk_put_queue(md->queue);
kfree(md);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d39f584cd8b3..5d88329e3c7a 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -306,6 +306,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
conf_t *conf = mddev_to_conf(r1_bio->mddev);
+ struct bio *to_put = NULL;
if (bio->bi_size)
return 1;
@@ -323,6 +324,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
* this branch is our 'one mirror IO has finished' event handler:
*/
r1_bio->bios[mirror] = NULL;
+ to_put = bio;
if (!uptodate) {
md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
/* an I/O failed, we can't clear the bitmap */
@@ -375,7 +377,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
/* Don't dec_pending yet, we want to hold
* the reference over the retry
*/
- return 0;
+ goto out;
}
if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
/* free extra copy of the data pages */
@@ -392,10 +394,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
raid_end_bio_io(r1_bio);
}
- if (r1_bio->bios[mirror]==NULL)
- bio_put(bio);
-
rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+ out:
+ if (to_put)
+ bio_put(to_put);
+
return 0;
}
@@ -857,7 +860,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
atomic_set(&r1_bio->remaining, 0);
atomic_set(&r1_bio->behind_remaining, 0);
- do_barriers = bio->bi_rw & BIO_RW_BARRIER;
+ do_barriers = bio_barrier(bio);
if (do_barriers)
set_bit(R1BIO_Barrier, &r1_bio->state);
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 2583a865a58e..2963605c0ecc 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0299
select DVB_MT352
select DVB_MT312
- select DVB_NXT2002
+ select DVB_NXT200X
select DVB_STV0297
select DVB_BCM3510
select DVB_LGDT330X
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 344a3c898460..7d7e1613c5a7 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma);
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx);
int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff);
int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
-int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets);
/* from flexcop-eeprom.c */
/* the PCI part uses this call to get the MAC address, the USB part has its own */
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
index cf4ed1df6086..6f592bc32d22 100644
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
}
EXPORT_SYMBOL(flexcop_dma_config_timer);
-/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc,
- flexcop_dma_index_t no,
- int onoff)
-{
- flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
-
- deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
- if (no & FC_DMA_1)
- v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
-
- if (no & FC_DMA_2)
- v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
-
- fc->write_ibi_reg(fc,ctrl_208,v);
- deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
-
- return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
-
-int flexcop_dma_config_packet_count(struct flexcop_device *fc,
- flexcop_dma_index_t dma_idx,
- u8 packets)
-{
- flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
- flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-
- flexcop_dma_remap(fc,dma_idx,1);
-
- v.dma_0x4_remap.DMA_maxpackets = packets;
- fc->write_ibi_reg(fc,r,v);
- return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 0b940e152b79..9c7f122826e0 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -9,7 +9,7 @@
#include "stv0299.h"
#include "mt352.h"
-#include "nxt2002.h"
+#include "nxt200x.h"
#include "bcm3510.h"
#include "stv0297.h"
#include "mt312.h"
@@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.clock_polarity_flip = 1,
};
-static struct nxt2002_config samsung_tbmv_config = {
+static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a,
- .request_firmware = flexcop_fe_request_firmware,
+ .pll_address = 0xc2,
+ .pll_desc = &dvb_pll_samsung_tbmv,
};
static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
} else
/* try the air atsc 2nd generation (nxt2002) */
- if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+ if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC2;
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else
@@ -525,7 +526,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
} else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
- if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
+ if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
ops = fc->fe->ops;
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 62282d8dbfa8..167583bf0621 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc)
/* bus parts have to decide if hw pid filtering is used or not. */
}
-const char *flexcop_revision_names[] = {
+static const char *flexcop_revision_names[] = {
"Unkown chip",
"FlexCopII",
"FlexCopIIb",
"FlexCopIII",
};
-const char *flexcop_device_names[] = {
+static const char *flexcop_device_names[] = {
"Unkown device",
"Air2PC/AirStar 2 DVB-T",
"Air2PC/AirStar 2 ATSC 1st generation",
@@ -54,7 +54,7 @@ const char *flexcop_device_names[] = {
"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
};
-const char *flexcop_bus_names[] = {
+static const char *flexcop_bus_names[] = {
"USB",
"PCI",
};
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 2f76eb3fea40..9bc40bdcc282 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs)
fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
- deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
- jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+ deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
+ jiffies_to_usecs(jiffies - fc_pci->last_irq),
+ v.raw, (unsigned long long)cur_addr, cur_pos,
+ fc_pci->last_dma1_cur_pos);
fc_pci->last_irq = jiffies;
/* buffer end was reached, restarted from the beginning
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 3153f9513c63..491f9bd6e195 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -16,8 +16,6 @@ typedef enum {
FLEXCOP_III,
} flexcop_revision_t;
-extern const char *flexcop_revision_names[];
-
typedef enum {
FC_UNK = 0,
FC_AIR_DVB,
@@ -34,8 +32,6 @@ typedef enum {
FC_PCI,
} flexcop_bus_t;
-extern const char *flexcop_device_names[];
-
/* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h"
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index a04bb61f21f4..356f447ee2ab 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *
EXPORT_SYMBOL(bt878_device_control);
+
+static struct cards card_list[] __devinitdata = {
+
+ { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
+ { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
+ { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" },
+ { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
+ { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" },
+ { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
+ { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
+ { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
+ { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
+ { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"},
+ { 0, -1, NULL }
+};
+
+
/***********************/
/* PCI device handling */
/***********************/
@@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control);
static int __devinit bt878_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
- int result;
+ int result = 0, has_dvb = 0, i;
unsigned char lat;
struct bt878 *bt;
#if defined(__powerpc__)
unsigned int cmd;
#endif
+ unsigned int cardid;
+ unsigned short id;
+ struct cards *dvb_cards;
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num);
if (pci_enable_device(dev))
return -EIO;
+ pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id);
+ cardid = id << 16;
+ pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id);
+ cardid |= id;
+
+ for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) {
+ if (cardid == dvb_cards->pci_id) {
+ printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n",
+ __func__, cardid, dvb_cards->name);
+ has_dvb = 1;
+ }
+ }
+
+ if (!has_dvb) {
+ printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid);
+ result = -EINVAL;
+
+ goto fail0;
+ }
+
bt = &bt878[bt878_num];
bt->dev = dev;
bt->nr = bt878_num;
@@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+
+
printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
bt878_num, bt->id, bt->revision, dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index a73baf00ca39..9faf93770d08 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -88,6 +88,23 @@
#define BT878_RISC_SYNC_MASK (1 << 15)
+
+#define BTTV_BOARD_UNKNOWN 0x00
+#define BTTV_BOARD_PINNACLESAT 0x5e
+#define BTTV_BOARD_NEBULA_DIGITV 0x68
+#define BTTV_BOARD_PC_HDTV 0x70
+#define BTTV_BOARD_TWINHAN_DST 0x71
+#define BTTV_BOARD_AVDVBT_771 0x7b
+#define BTTV_BOARD_AVDVBT_761 0x7c
+#define BTTV_BOARD_DVICO_DVBT_LITE 0x80
+#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+
+struct cards {
+ __u32 pci_id;
+ __u16 card_id;
+ char *name;
+};
+
extern int bt878_num;
struct bt878 {
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 3a2ff1cc24b7..0310e3dd07e6 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -602,7 +602,7 @@ static int dst_type_print(u8 type)
*/
-struct dst_types dst_tlist[] = {
+static struct dst_types dst_tlist[] = {
{
.device_id = "200103A",
.offset = 0,
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 9f025825b2d2..0c1d87c5227a 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -216,7 +216,7 @@ struct dmx_frontend {
/*--------------------------------------------------------------------------*/
/*
- * Flags OR'ed in the capabilites field of struct dmx_demux.
+ * Flags OR'ed in the capabilities field of struct dmx_demux.
*/
#define DMX_TS_FILTERING 1
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 90a69d343b79..d3df12039b06 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -83,12 +83,18 @@ config DVB_USB_UMT_010
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
config DVB_USB_CXUSB
- tristate "Medion MD95700 hybrid USB2.0 (Conexant) support"
+ tristate "Conexant USB2.0 hybrid reference design support"
depends on DVB_USB
select DVB_CX22702
+ select DVB_LGDT330X
+ select DVB_MT352
help
- Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently
- only the DVB-T part is supported.
+ Say Y here to support the Conexant USB2.0 hybrid reference design.
+ Currently, only DVB and ATSC modes are supported, analog mode
+ shall be added in the future. Devices that require this module:
+
+ Medion MD95700 hybrid USB2.0 device.
+ DViCO FusionHDTV (Bluebird) USB2.0 devices
config DVB_USB_DIGITV
tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index a7fb06f4cd34..162f9795cd89 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
-struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 },
{ 0xfe, 0x1a, KEY_DVD },
@@ -234,7 +234,7 @@ struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
- static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
@@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
{ /* used in both lgz201 and th7579 */
- static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 };
static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
@@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
return 0;
}
-struct cx22702_config cxusb_cx22702_config = {
+static struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
.output_mode = CX22702_PARALLEL_OUTPUT,
@@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c,
};
-struct lgdt330x_config cxusb_lgdt330x_config = {
+static struct lgdt330x_config cxusb_lgdt3303_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
.pll_set = dvb_usb_pll_set_i2c,
};
-struct mt352_config cxusb_dee1601_config = {
+static struct mt352_config cxusb_dee1601_config = {
.demod_address = 0x0f,
.demod_init = cxusb_dee1601_demod_init,
.pll_set = dvb_usb_pll_set,
@@ -357,14 +357,14 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
return -EIO;
}
-static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d)
{
if (usb_set_interface(d->udev,0,7) < 0)
err("set interface failed");
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL)
+ if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
return 0;
return -EIO;
@@ -506,7 +506,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
- .frontend_attach = cxusb_lgdt330x_frontend_attach,
+ .frontend_attach = cxusb_lgdt3303_frontend_attach,
.tuner_attach = cxusb_lgh064f_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index e6c55c9c9417..caa1346e3063 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -175,11 +175,13 @@ static int digitv_probe(struct usb_interface *intf,
if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
u8 b[4] = { 0 };
- b[0] = 1;
- digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+ if (d != NULL) { /* do that only when the firmware is loaded */
+ b[0] = 1;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
- b[0] = 0;
- digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ b[0] = 0;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ }
}
return ret;
}
@@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
- .firmware = "dvb-usb-digitv-01.fw",
+ .firmware = "dvb-usb-digitv-02.fw",
.size_of_priv = 0,
@@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = {
{ &digitv_table[0], NULL },
{ NULL },
},
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 130ea7f21f5e..12ebaf8bddca 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
- { 0 },
+ { NULL },
}
};
@@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = {
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
- { 0 },
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 8535895819fb..9222b0a81f74 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = {
{ .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
};
+static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+ int *pos);
+
/*
* load a firmware packet to the device
*/
@@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties
return ret;
}
-int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
+static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+ int *pos)
{
u8 *b = (u8 *) &fw->data[*pos];
int data_offs = 4;
@@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
return *pos;
}
-EXPORT_SYMBOL(dvb_usb_get_hexline);
-
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index 716f8bf528cd..ce34a55e5c24 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -47,7 +47,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
d->state = DVB_USB_STATE_INIT;
-/* check the capabilites and set appropriate variables */
+/* check the capabilities and set appropriate variables */
/* speed - when running at FULL speed we need a HW PID filter */
if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index dd568396e594..d4909e5c67e0 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -87,7 +87,7 @@ struct dvb_usb_device;
/**
* struct dvb_usb_properties - properties of a dvb-usb-device
- * @caps: capabilites of the DVB USB device.
+ * @caps: capabilities of the DVB USB device.
* @pid_filter_count: number of PID filter position in the optional hardware
* PID-filter.
*
@@ -341,7 +341,6 @@ struct hexline {
u8 data[255];
u8 chk;
};
-extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index afa00fdb5ec0..4a95eca81c5c 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
return ret;
}
-int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+ u16 index, u8 *b, int blen)
{
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
debug_dump(b,blen,deb_xfer);
@@ -88,7 +89,8 @@ unlock:
return ret;
}
-int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
+static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
+ int olen, u8 *i, int ilen, int msec)
{
u8 bout[olen+2];
u8 bin[ilen+1];
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index a808d48e7bf2..c2f97f96c21f 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug;
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
-extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
-extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
#endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 5242cca5db4a..9999336aeeb6 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -23,10 +23,11 @@
struct vp7045_fe_state {
struct dvb_frontend fe;
+ struct dvb_frontend_ops ops;
+
struct dvb_usb_device *d;
};
-
static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
{
struct vp7045_fe_state *state = fe->demodulator_priv;
@@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
goto error;
s->d = d;
- s->fe.ops = &vp7045_fe_ops;
+ memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
+ s->fe.ops = &s->ops;
s->fe.demodulator_priv = s;
goto success;
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 028204956bb0..3835235b68df 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
- { 0 },
+ { NULL },
}
};
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index db3a8b40031e..c676b1e23ab0 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -28,14 +28,8 @@ config DVB_TDA8083
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_TDA80XX
- tristate "Philips TDA8044 or TDA8083 based"
- depends on DVB_CORE
- help
- A DVB-S tuner module. Say Y when you want to support this frontend.
-
config DVB_MT312
- tristate "Zarlink MT312 based"
+ tristate "Zarlink VP310/MT312 based"
depends on DVB_CORE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
@@ -139,12 +133,6 @@ config DVB_DIB3000MC
comment "DVB-C (cable) frontends"
depends on DVB_CORE
-config DVB_ATMEL_AT76C651
- tristate "Atmel AT76C651 based"
- depends on DVB_CORE
- help
- A DVB-C tuner module. Say Y when you want to support this frontend.
-
config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
@@ -166,18 +154,6 @@ config DVB_STV0297
comment "ATSC (North American/Korean Terresterial DTV) frontends"
depends on DVB_CORE
-config DVB_NXT2002
- tristate "Nxt2002 based"
- depends on DVB_CORE
- select FW_LOADER
- help
- An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
-
- This driver needs external firmware. Please use the command
- "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware
- or /lib/firmware (depending on configuration of firmware hotplug).
-
config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 615ec830e1c9..1af769cd90c0 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
obj-$(CONFIG_DVB_SP8870) += sp8870.o
obj-$(CONFIG_DVB_CX22700) += cx22700.o
-obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o
obj-$(CONFIG_DVB_CX24110) += cx24110.o
obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o
@@ -22,10 +21,8 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o
-obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o
-obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
obj-$(CONFIG_DVB_OR51211) += or51211.o
obj-$(CONFIG_DVB_OR51132) += or51132.o
diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c
deleted file mode 100644
index 8e0f4b3a1417..000000000000
--- a/drivers/media/dvb/frontends/at76c651.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * at76c651.c
- *
- * Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
- *
- * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
- * & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- * & 2003 Wolfram Joost <dbox2@frokaschwei.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * AT76C651
- * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
- * http://www.atmel.com/atmel/acrobat/doc1320.pdf
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include "dvb_frontend.h"
-#include "at76c651.h"
-
-
-struct at76c651_state {
-
- struct i2c_adapter* i2c;
-
- struct dvb_frontend_ops ops;
-
- const struct at76c651_config* config;
-
- struct dvb_frontend frontend;
-
- /* revision of the chip */
- u8 revision;
-
- /* last QAM value set */
- u8 qam;
-};
-
-static int debug;
-#define dprintk(args...) \
- do { \
- if (debug) printk(KERN_DEBUG "at76c651: " args); \
- } while (0)
-
-
-#if ! defined(__powerpc__)
-static __inline__ int __ilog2(unsigned long x)
-{
- int i;
-
- if (x == 0)
- return -1;
-
- for (i = 0; x != 0; i++)
- x >>= 1;
-
- return i - 1;
-}
-#endif
-
-static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data)
-{
- int ret;
- u8 buf[] = { reg, data };
- struct i2c_msg msg =
- { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1)
- dprintk("%s: writereg error "
- "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- __FUNCTION__, reg, data, ret);
-
- msleep(10);
-
- return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static u8 at76c651_readreg(struct at76c651_state* state, u8 reg)
-{
- int ret;
- u8 val;
- struct i2c_msg msg[] = {
- { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 }
- };
-
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2)
- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
-
- return val;
-}
-
-static int at76c651_reset(struct at76c651_state* state)
-{
- return at76c651_writereg(state, 0x07, 0x01);
-}
-
-static void at76c651_disable_interrupts(struct at76c651_state* state)
-{
- at76c651_writereg(state, 0x0b, 0x00);
-}
-
-static int at76c651_set_auto_config(struct at76c651_state *state)
-{
- /*
- * Autoconfig
- */
-
- at76c651_writereg(state, 0x06, 0x01);
-
- /*
- * Performance optimizations, should be done after autoconfig
- */
-
- at76c651_writereg(state, 0x10, 0x06);
- at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10);
- at76c651_writereg(state, 0x15, 0x28);
- at76c651_writereg(state, 0x20, 0x09);
- at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90);
- at76c651_writereg(state, 0x30, 0x90);
- if (state->qam == 5)
- at76c651_writereg(state, 0x35, 0x2A);
-
- /*
- * Initialize A/D-converter
- */
-
- if (state->revision == 0x11) {
- at76c651_writereg(state, 0x2E, 0x38);
- at76c651_writereg(state, 0x2F, 0x13);
- }
-
- at76c651_disable_interrupts(state);
-
- /*
- * Restart operation
- */
-
- at76c651_reset(state);
-
- return 0;
-}
-
-static void at76c651_set_bbfreq(struct at76c651_state* state)
-{
- at76c651_writereg(state, 0x04, 0x3f);
- at76c651_writereg(state, 0x05, 0xee);
-}
-
-static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate)
-{
- u8 exponent;
- u32 mantissa;
-
- if (symbol_rate > 9360000)
- return -EINVAL;
-
- /*
- * FREF = 57800 kHz
- * exponent = 10 + floor (log2(symbol_rate / FREF))
- * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent))
- */
-
- exponent = __ilog2((symbol_rate << 4) / 903125);
- mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289;
-
- at76c651_writereg(state, 0x00, mantissa >> 13);
- at76c651_writereg(state, 0x01, mantissa >> 5);
- at76c651_writereg(state, 0x02, (mantissa << 3) | exponent);
-
- return 0;
-}
-
-static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam)
-{
- switch (qam) {
- case QPSK:
- state->qam = 0x02;
- break;
- case QAM_16:
- state->qam = 0x04;
- break;
- case QAM_32:
- state->qam = 0x05;
- break;
- case QAM_64:
- state->qam = 0x06;
- break;
- case QAM_128:
- state->qam = 0x07;
- break;
- case QAM_256:
- state->qam = 0x08;
- break;
-#if 0
- case QAM_512:
- state->qam = 0x09;
- break;
- case QAM_1024:
- state->qam = 0x0A;
- break;
-#endif
- default:
- return -EINVAL;
-
- }
-
- return at76c651_writereg(state, 0x03, state->qam);
-}
-
-static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion)
-{
- u8 feciqinv = at76c651_readreg(state, 0x60);
-
- switch (inversion) {
- case INVERSION_OFF:
- feciqinv |= 0x02;
- feciqinv &= 0xFE;
- break;
-
- case INVERSION_ON:
- feciqinv |= 0x03;
- break;
-
- case INVERSION_AUTO:
- feciqinv &= 0xFC;
- break;
-
- default:
- return -EINVAL;
- }
-
- return at76c651_writereg(state, 0x60, feciqinv);
-}
-
-static int at76c651_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
-{
- int ret;
- struct at76c651_state* state = fe->demodulator_priv;
-
- at76c651_writereg(state, 0x0c, 0xc3);
- state->config->pll_set(fe, p);
- at76c651_writereg(state, 0x0c, 0xc2);
-
- if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate)))
- return ret;
-
- if ((ret = at76c651_set_inversion(state, p->inversion)))
- return ret;
-
- return at76c651_set_auto_config(state);
-}
-
-static int at76c651_set_defaults(struct dvb_frontend* fe)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- at76c651_set_symbol_rate(state, 6900000);
- at76c651_set_qam(state, QAM_64);
- at76c651_set_bbfreq(state);
- at76c651_set_auto_config(state);
-
- if (state->config->pll_init) {
- at76c651_writereg(state, 0x0c, 0xc3);
- state->config->pll_init(fe);
- at76c651_writereg(state, 0x0c, 0xc2);
- }
-
- return 0;
-}
-
-static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
- struct at76c651_state* state = fe->demodulator_priv;
- u8 sync;
-
- /*
- * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
- */
- sync = at76c651_readreg(state, 0x80);
- *status = 0;
-
- if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
- *status |= FE_HAS_SIGNAL;
- if (sync & 0x10) /* TIM */
- *status |= FE_HAS_CARRIER;
- if (sync & 0x80) /* FEC */
- *status |= FE_HAS_VITERBI;
- if (sync & 0x40) /* CAR */
- *status |= FE_HAS_SYNC;
- if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
- *status |= FE_HAS_LOCK;
-
- return 0;
-}
-
-static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
- *ber |= at76c651_readreg(state, 0x82) << 8;
- *ber |= at76c651_readreg(state, 0x83);
- *ber *= 10;
-
- return 0;
-}
-
-static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- u8 gain = ~at76c651_readreg(state, 0x91);
- *strength = (gain << 8) | gain;
-
- return 0;
-}
-
-static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- *snr = 0xFFFF -
- ((at76c651_readreg(state, 0x8F) << 8) |
- at76c651_readreg(state, 0x90));
-
- return 0;
-}
-
-static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- *ucblocks = at76c651_readreg(state, 0x82);
-
- return 0;
-}
-
-static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings)
-{
- fesettings->min_delay_ms = 50;
- fesettings->step_size = 0;
- fesettings->max_drift = 0;
- return 0;
-}
-
-static void at76c651_release(struct dvb_frontend* fe)
-{
- struct at76c651_state* state = fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops at76c651_ops;
-
-struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
- struct i2c_adapter* i2c)
-{
- struct at76c651_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->qam = 0;
-
- /* check if the demod is there */
- if (at76c651_readreg(state, 0x0e) != 0x65) goto error;
-
- /* finalise state setup */
- state->i2c = i2c;
- state->revision = at76c651_readreg(state, 0x0f) & 0xfe;
- memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops));
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops at76c651_ops = {
-
- .info = {
- .name = "Atmel AT76C651B DVB-C",
- .type = FE_QAM,
- .frequency_min = 48250000,
- .frequency_max = 863250000,
- .frequency_stepsize = 62500,
- /*.frequency_tolerance = */ /* FIXME: 12% of SR */
- .symbol_rate_min = 0, /* FIXME */
- .symbol_rate_max = 9360000, /* FIXME */
- .symbol_rate_tolerance = 4000,
- .caps = FE_CAN_INVERSION_AUTO |
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
- FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
- },
-
- .release = at76c651_release,
-
- .init = at76c651_set_defaults,
-
- .set_frontend = at76c651_set_parameters,
- .get_tune_settings = at76c651_get_tune_settings,
-
- .read_status = at76c651_read_status,
- .read_ber = at76c651_read_ber,
- .read_signal_strength = at76c651_read_signal_strength,
- .read_snr = at76c651_read_snr,
- .read_ucblocks = at76c651_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver");
-MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(at76c651_attach);
diff --git a/drivers/media/dvb/frontends/at76c651.h b/drivers/media/dvb/frontends/at76c651.h
deleted file mode 100644
index 34054df93608..000000000000
--- a/drivers/media/dvb/frontends/at76c651.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * at76c651.c
- *
- * Atmel DVB-C Frontend Driver (at76c651)
- *
- * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
- * & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- * & 2003 Wolfram Joost <dbox2@frokaschwei.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * AT76C651
- * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
- * http://www.atmel.com/atmel/acrobat/doc1320.pdf
- */
-
-#ifndef AT76C651_H
-#define AT76C651_H
-
-#include <linux/dvb/frontend.h>
-
-struct at76c651_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-};
-
-extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
- struct i2c_adapter* i2c);
-
-#endif // AT76C651_H
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 1b9934ea5b06..4dcb6050d4fa 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -326,11 +326,11 @@ struct dvb_pll_desc dvb_pll_tuv1236d = {
};
EXPORT_SYMBOL(dvb_pll_tuv1236d);
-/* Samsung TBMV30111IN
+/* Samsung TBMV30111IN / TBMV30712IN1
* used in Air2PC ATSC - 2nd generation (nxt2002)
*/
-struct dvb_pll_desc dvb_pll_tbmv30111in = {
- .name = "Samsung TBMV30111IN",
+struct dvb_pll_desc dvb_pll_samsung_tbmv = {
+ .name = "Samsung TBMV30111IN / TBMV30712IN1",
.min = 54000000,
.max = 860000000,
.count = 6,
@@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
{ 999999999, 44000000, 166666, 0xfc, 0x02 },
}
};
-EXPORT_SYMBOL(dvb_pll_tbmv30111in);
+EXPORT_SYMBOL(dvb_pll_samsung_tbmv);
/*
* Philips SD1878 Tuner.
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index f682c09189b3..bb8d4b4eb183 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4;
extern struct dvb_pll_desc dvb_pll_tuv1236d;
extern struct dvb_pll_desc dvb_pll_tdhu2;
-extern struct dvb_pll_desc dvb_pll_tbmv30111in;
+extern struct dvb_pll_desc dvb_pll_samsung_tbmv;
extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index ec4e641acc64..d3aea83cf218 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -612,76 +612,6 @@ static void mt312_release(struct dvb_frontend* fe)
kfree(state);
}
-static struct dvb_frontend_ops vp310_mt312_ops;
-
-struct dvb_frontend* vp310_attach(const struct mt312_config* config,
- struct i2c_adapter* i2c)
-{
- struct mt312_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
- if (state == NULL)
- goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
- strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
-
- /* check if the demod is there */
- if (mt312_readreg(state, ID, &state->id) < 0)
- goto error;
- if (state->id != ID_VP310) {
- goto error;
- }
-
- /* create dvb_frontend */
- state->frequency = 90;
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-struct dvb_frontend* mt312_attach(const struct mt312_config* config,
- struct i2c_adapter* i2c)
-{
- struct mt312_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
- if (state == NULL)
- goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
- strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
-
- /* check if the demod is there */
- if (mt312_readreg(state, ID, &state->id) < 0)
- goto error;
- if (state->id != ID_MT312) {
- goto error;
- }
-
- /* create dvb_frontend */
- state->frequency = 60;
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
static struct dvb_frontend_ops vp310_mt312_ops = {
.info = {
@@ -720,6 +650,49 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
.set_voltage = mt312_set_voltage,
};
+struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct mt312_state* state = NULL;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
+
+ /* check if the demod is there */
+ if (mt312_readreg(state, ID, &state->id) < 0)
+ goto error;
+
+ switch (state->id) {
+ case ID_VP310:
+ strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
+ state->frequency = 90;
+ break;
+ case ID_MT312:
+ strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
+ state->frequency = 60;
+ break;
+ default:
+ printk (KERN_WARNING "Only Zarlink VP310/MT312 are supported chips.\n");
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
@@ -727,5 +700,4 @@ MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(mt312_attach);
-EXPORT_SYMBOL(vp310_attach);
+EXPORT_SYMBOL(vp310_mt312_attach);
diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
index b3a53a73a117..074d844f0139 100644
--- a/drivers/media/dvb/frontends/mt312.h
+++ b/drivers/media/dvb/frontends/mt312.h
@@ -38,10 +38,8 @@ struct mt312_config
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
-extern struct dvb_frontend* mt312_attach(const struct mt312_config* config,
- struct i2c_adapter* i2c);
+struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+ struct i2c_adapter* i2c);
-extern struct dvb_frontend* vp310_attach(const struct mt312_config* config,
- struct i2c_adapter* i2c);
#endif // MT312_H
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
deleted file mode 100644
index 4f263e65ba14..000000000000
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- Support for B2C2/BBTI Technisat Air2PC - ATSC
-
- Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/*
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
-#define CRC_CCIT_MASK 0x1021
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "nxt2002.h"
-
-struct nxt2002_state {
-
- struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
- const struct nxt2002_config* config;
- struct dvb_frontend frontend;
-
- /* demodulator private data */
- u8 initialised:1;
-};
-
-static int debug;
-#define dprintk(args...) \
- do { \
- if (debug) printk(KERN_DEBUG "nxt2002: " args); \
- } while (0)
-
-static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len)
-{
- /* probbably a much better way or doing this */
- u8 buf2 [256],x;
- int err;
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
-
- buf2[0] = reg;
- for (x = 0 ; x < len ; x++)
- buf2[x+1] = buf[x];
-
- if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
- printk ("%s: i2c write error (addr %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len)
-{
- u8 reg2 [] = { reg };
-
- struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
- int err;
-
- if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
- printk ("%s: i2c read error (addr %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static u16 nxt2002_crc(u16 crc, u8 c)
-{
-
- u8 i;
- u16 input = (u16) c & 0xFF;
-
- input<<=8;
- for(i=0 ;i<8 ;i++) {
- if((crc ^ input) & 0x8000)
- crc=(crc<<1)^CRC_CCIT_MASK;
- else
- crc<<=1;
- input<<=1;
- }
- return crc;
-}
-
-static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
-{
- u8 buf;
- dprintk("%s\n", __FUNCTION__);
-
- /* set multi register length */
- i2c_writebytes(state,0x34,&len,1);
-
- /* set mutli register register */
- i2c_writebytes(state,0x35,&reg,1);
-
- /* send the actual data */
- i2c_writebytes(state,0x36,data,len);
-
- /* toggle the multireg write bit*/
- buf = 0x02;
- i2c_writebytes(state,0x21,&buf,1);
-
- i2c_readbytes(state,0x21,&buf,1);
-
- if ((buf & 0x02) == 0)
- return 0;
-
- dprintk("Error writing multireg register %02X\n",reg);
-
- return 0;
-}
-
-static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
-{
- u8 len2;
- dprintk("%s\n", __FUNCTION__);
-
- /* set multi register length */
- len2 = len & 0x80;
- i2c_writebytes(state,0x34,&len2,1);
-
- /* set mutli register register */
- i2c_writebytes(state,0x35,&reg,1);
-
- /* send the actual data */
- i2c_readbytes(state,reg,data,len);
-
- return 0;
-}
-
-static void nxt2002_microcontroller_stop (struct nxt2002_state* state)
-{
- u8 buf[2],counter = 0;
- dprintk("%s\n", __FUNCTION__);
-
- buf[0] = 0x80;
- i2c_writebytes(state,0x22,buf,1);
-
- while (counter < 20) {
- i2c_readbytes(state,0x31,buf,1);
- if (buf[0] & 0x40)
- return;
- msleep(10);
- counter++;
- }
-
- dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n");
- return;
-}
-
-static void nxt2002_microcontroller_start (struct nxt2002_state* state)
-{
- u8 buf;
- dprintk("%s\n", __FUNCTION__);
-
- buf = 0x00;
- i2c_writebytes(state,0x22,&buf,1);
-}
-
-static int nxt2002_writetuner (struct nxt2002_state* state, u8* data)
-{
- u8 buf,count = 0;
-
- dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]);
-
- dprintk("%s\n", __FUNCTION__);
- /* stop the micro first */
- nxt2002_microcontroller_stop(state);
-
- /* set the i2c transfer speed to the tuner */
- buf = 0x03;
- i2c_writebytes(state,0x20,&buf,1);
-
- /* setup to transfer 4 bytes via i2c */
- buf = 0x04;
- i2c_writebytes(state,0x34,&buf,1);
-
- /* write actual tuner bytes */
- i2c_writebytes(state,0x36,data,4);
-
- /* set tuner i2c address */
- buf = 0xC2;
- i2c_writebytes(state,0x35,&buf,1);
-
- /* write UC Opmode to begin transfer */
- buf = 0x80;
- i2c_writebytes(state,0x21,&buf,1);
-
- while (count < 20) {
- i2c_readbytes(state,0x21,&buf,1);
- if ((buf & 0x80)== 0x00)
- return 0;
- msleep(100);
- count++;
- }
-
- printk("nxt2002: timeout error writing tuner\n");
- return 0;
-}
-
-static void nxt2002_agc_reset(struct nxt2002_state* state)
-{
- u8 buf;
- dprintk("%s\n", __FUNCTION__);
-
- buf = 0x08;
- i2c_writebytes(state,0x08,&buf,1);
-
- buf = 0x00;
- i2c_writebytes(state,0x08,&buf,1);
-
- return;
-}
-
-static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
-{
-
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 buf[256],written = 0,chunkpos = 0;
- u16 rambase,position,crc = 0;
-
- dprintk("%s\n", __FUNCTION__);
- dprintk("Firmware is %zu bytes\n",fw->size);
-
- /* Get the RAM base for this nxt2002 */
- i2c_readbytes(state,0x10,buf,1);
-
- if (buf[0] & 0x10)
- rambase = 0x1000;
- else
- rambase = 0x0000;
-
- dprintk("rambase on this nxt2002 is %04X\n",rambase);
-
- /* Hold the micro in reset while loading firmware */
- buf[0] = 0x80;
- i2c_writebytes(state,0x2B,buf,1);
-
- for (position = 0; position < fw->size ; position++) {
- if (written == 0) {
- crc = 0;
- chunkpos = 0x28;
- buf[0] = ((rambase + position) >> 8);
- buf[1] = (rambase + position) & 0xFF;
- buf[2] = 0x81;
- /* write starting address */
- i2c_writebytes(state,0x29,buf,3);
- }
- written++;
- chunkpos++;
-
- if ((written % 4) == 0)
- i2c_writebytes(state,chunkpos,&fw->data[position-3],4);
-
- crc = nxt2002_crc(crc,fw->data[position]);
-
- if ((written == 255) || (position+1 == fw->size)) {
- /* write remaining bytes of firmware */
- i2c_writebytes(state, chunkpos+4-(written %4),
- &fw->data[position-(written %4) + 1],
- written %4);
- buf[0] = crc << 8;
- buf[1] = crc & 0xFF;
-
- /* write crc */
- i2c_writebytes(state,0x2C,buf,2);
-
- /* do a read to stop things */
- i2c_readbytes(state,0x2A,buf,1);
-
- /* set transfer mode to complete */
- buf[0] = 0x80;
- i2c_writebytes(state,0x2B,buf,1);
-
- written = 0;
- }
- }
-
- printk ("done.\n");
- return 0;
-};
-
-static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u32 freq = 0;
- u16 tunerfreq = 0;
- u8 buf[4];
-
- freq = 44000 + ( p->frequency / 1000 );
-
- dprintk("freq = %d p->frequency = %d\n",freq,p->frequency);
-
- tunerfreq = freq * 24/4000;
-
- buf[0] = (tunerfreq >> 8) & 0x7F;
- buf[1] = (tunerfreq & 0xFF);
-
- if (p->frequency <= 214000000) {
- buf[2] = 0x84 + (0x06 << 3);
- buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02;
- } else if (p->frequency <= 721000000) {
- buf[2] = 0x84 + (0x07 << 3);
- buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08;
- } else if (p->frequency <= 841000000) {
- buf[2] = 0x84 + (0x0E << 3);
- buf[3] = 0x08;
- } else {
- buf[2] = 0x84 + (0x0F << 3);
- buf[3] = 0x02;
- }
-
- /* write frequency information */
- nxt2002_writetuner(state,buf);
-
- /* reset the agc now that tuning has been completed */
- nxt2002_agc_reset(state);
-
- /* set target power level */
- switch (p->u.vsb.modulation) {
- case QAM_64:
- case QAM_256:
- buf[0] = 0x74;
- break;
- case VSB_8:
- buf[0] = 0x70;
- break;
- default:
- return -EINVAL;
- break;
- }
- i2c_writebytes(state,0x42,buf,1);
-
- /* configure sdm */
- buf[0] = 0x87;
- i2c_writebytes(state,0x57,buf,1);
-
- /* write sdm1 input */
- buf[0] = 0x10;
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x58,buf,2);
-
- /* write sdmx input */
- switch (p->u.vsb.modulation) {
- case QAM_64:
- buf[0] = 0x68;
- break;
- case QAM_256:
- buf[0] = 0x64;
- break;
- case VSB_8:
- buf[0] = 0x60;
- break;
- default:
- return -EINVAL;
- break;
- }
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x5C,buf,2);
-
- /* write adc power lpf fc */
- buf[0] = 0x05;
- i2c_writebytes(state,0x43,buf,1);
-
- /* write adc power lpf fc */
- buf[0] = 0x05;
- i2c_writebytes(state,0x43,buf,1);
-
- /* write accumulator2 input */
- buf[0] = 0x80;
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x4B,buf,2);
-
- /* write kg1 */
- buf[0] = 0x00;
- i2c_writebytes(state,0x4D,buf,1);
-
- /* write sdm12 lpf fc */
- buf[0] = 0x44;
- i2c_writebytes(state,0x55,buf,1);
-
- /* write agc control reg */
- buf[0] = 0x04;
- i2c_writebytes(state,0x41,buf,1);
-
- /* write agc ucgp0 */
- switch (p->u.vsb.modulation) {
- case QAM_64:
- buf[0] = 0x02;
- break;
- case QAM_256:
- buf[0] = 0x03;
- break;
- case VSB_8:
- buf[0] = 0x00;
- break;
- default:
- return -EINVAL;
- break;
- }
- i2c_writebytes(state,0x30,buf,1);
-
- /* write agc control reg */
- buf[0] = 0x00;
- i2c_writebytes(state,0x41,buf,1);
-
- /* write accumulator2 input */
- buf[0] = 0x80;
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x49,buf,2);
- nxt2002_writereg_multibyte(state,0x4B,buf,2);
-
- /* write agc control reg */
- buf[0] = 0x04;
- i2c_writebytes(state,0x41,buf,1);
-
- nxt2002_microcontroller_start(state);
-
- /* adjacent channel detection should be done here, but I don't
- have any stations with this need so I cannot test it */
-
- return 0;
-}
-
-static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 lock;
- i2c_readbytes(state,0x31,&lock,1);
-
- *status = 0;
- if (lock & 0x20) {
- *status |= FE_HAS_SIGNAL;
- *status |= FE_HAS_CARRIER;
- *status |= FE_HAS_VITERBI;
- *status |= FE_HAS_SYNC;
- *status |= FE_HAS_LOCK;
- }
- return 0;
-}
-
-static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[3];
-
- nxt2002_readreg_multibyte(state,0xE6,b,3);
-
- *ber = ((b[0] << 8) + b[1]) * 8;
-
- return 0;
-}
-
-static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[2];
- u16 temp = 0;
-
- /* setup to read cluster variance */
- b[0] = 0x00;
- i2c_writebytes(state,0xA1,b,1);
-
- /* get multreg val */
- nxt2002_readreg_multibyte(state,0xA6,b,2);
-
- temp = (b[0] << 8) | b[1];
- *strength = ((0x7FFF - temp) & 0x0FFF) * 16;
-
- return 0;
-}
-
-static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[2];
- u16 temp = 0, temp2;
- u32 snrdb = 0;
-
- /* setup to read cluster variance */
- b[0] = 0x00;
- i2c_writebytes(state,0xA1,b,1);
-
- /* get multreg val from 0xA6 */
- nxt2002_readreg_multibyte(state,0xA6,b,2);
-
- temp = (b[0] << 8) | b[1];
- temp2 = 0x7FFF - temp;
-
- /* snr will be in db */
- if (temp2 > 0x7F00)
- snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
- else if (temp2 > 0x7EC0)
- snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
- else if (temp2 > 0x7C00)
- snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
- else
- snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
-
- /* the value reported back from the frontend will be FFFF=32db 0000=0db */
-
- *snr = snrdb * (0xFFFF/32000);
-
- return 0;
-}
-
-static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[3];
-
- nxt2002_readreg_multibyte(state,0xE6,b,3);
- *ucblocks = b[2];
-
- return 0;
-}
-
-static int nxt2002_sleep(struct dvb_frontend* fe)
-{
- return 0;
-}
-
-static int nxt2002_init(struct dvb_frontend* fe)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- const struct firmware *fw;
- int ret;
- u8 buf[2];
-
- if (!state->initialised) {
- /* request the firmware, this will block until someone uploads it */
- printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
- ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE);
- printk("nxt2002: Waiting for firmware upload(2)...\n");
- if (ret) {
- printk("nxt2002: no firmware upload (timeout or file not found?)\n");
- return ret;
- }
-
- ret = nxt2002_load_firmware(fe, fw);
- if (ret) {
- printk("nxt2002: writing firmware to device failed\n");
- release_firmware(fw);
- return ret;
- }
- printk("nxt2002: firmware upload complete\n");
-
- /* Put the micro into reset */
- nxt2002_microcontroller_stop(state);
-
- /* ensure transfer is complete */
- buf[0]=0;
- i2c_writebytes(state,0x2B,buf,1);
-
- /* Put the micro into reset for real this time */
- nxt2002_microcontroller_stop(state);
-
- /* soft reset everything (agc,frontend,eq,fec)*/
- buf[0] = 0x0F;
- i2c_writebytes(state,0x08,buf,1);
- buf[0] = 0x00;
- i2c_writebytes(state,0x08,buf,1);
-
- /* write agc sdm configure */
- buf[0] = 0xF1;
- i2c_writebytes(state,0x57,buf,1);
-
- /* write mod output format */
- buf[0] = 0x20;
- i2c_writebytes(state,0x09,buf,1);
-
- /* write fec mpeg mode */
- buf[0] = 0x7E;
- buf[1] = 0x00;
- i2c_writebytes(state,0xE9,buf,2);
-
- /* write mux selection */
- buf[0] = 0x00;
- i2c_writebytes(state,0xCC,buf,1);
-
- state->initialised = 1;
- }
-
- return 0;
-}
-
-static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
- fesettings->min_delay_ms = 500;
- fesettings->step_size = 0;
- fesettings->max_drift = 0;
- return 0;
-}
-
-static void nxt2002_release(struct dvb_frontend* fe)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops nxt2002_ops;
-
-struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
- struct i2c_adapter* i2c)
-{
- struct nxt2002_state* state = NULL;
- u8 buf [] = {0,0,0,0,0};
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
-
- /* Check the first 5 registers to ensure this a revision we can handle */
-
- i2c_readbytes(state, 0x00, buf, 5);
- if (buf[0] != 0x04) goto error; /* device id */
- if (buf[1] != 0x02) goto error; /* fab id */
- if (buf[2] != 0x11) goto error; /* month */
- if (buf[3] != 0x20) goto error; /* year msb */
- if (buf[4] != 0x00) goto error; /* year lsb */
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops nxt2002_ops = {
-
- .info = {
- .name = "Nextwave nxt2002 VSB/QAM frontend",
- .type = FE_ATSC,
- .frequency_min = 54000000,
- .frequency_max = 860000000,
- /* stepsize is just a guess */
- .frequency_stepsize = 166666,
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
- },
-
- .release = nxt2002_release,
-
- .init = nxt2002_init,
- .sleep = nxt2002_sleep,
-
- .set_frontend = nxt2002_setup_frontend_parameters,
- .get_tune_settings = nxt2002_get_tune_settings,
-
- .read_status = nxt2002_read_status,
- .read_ber = nxt2002_read_ber,
- .read_signal_strength = nxt2002_read_signal_strength,
- .read_snr = nxt2002_read_snr,
- .read_ucblocks = nxt2002_read_ucblocks,
-
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
-MODULE_AUTHOR("Taylor Jacob");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(nxt2002_attach);
diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h
deleted file mode 100644
index 462301f577ee..000000000000
--- a/drivers/media/dvb/frontends/nxt2002.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- Driver for the Nxt2002 demodulator
-*/
-
-#ifndef NXT2002_H
-#define NXT2002_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct nxt2002_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-
- /* request firmware for device */
- int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
- struct i2c_adapter* i2c);
-
-#endif // NXT2002_H
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 78d2b93d35b9..9e3535394509 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -1,9 +1,10 @@
/*
* Support for NXT2002 and NXT2004 - VSB/QAM
*
- * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
+ * Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
+ * Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
* based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
- * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com)
+ * and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.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
@@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write sdm1 input */
buf[0] = 0x10;
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x58, buf, 2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x58, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x58, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write sdmx input */
switch (p->u.vsb.modulation) {
@@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
break;
}
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x5C, buf, 2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x5C, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write adc power lpf fc */
buf[0] = 0x05;
@@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write accumulator2 input */
buf[0] = 0x80;
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x4B, buf, 2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x4B, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write kg1 */
buf[0] = 0x00;
@@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write accumulator2 input */
buf[0] = 0x80;
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x49, buf,2);
- nxt200x_writebytes(state, 0x4B, buf,2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x49, buf, 2);
+ nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x49, buf, 2);
+ nxt200x_writebytes(state, 0x4B, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write agc control reg */
buf[0] = 0x04;
@@ -1199,7 +1241,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
-MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob");
+MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(nxt200x_attach);
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 6122ba754bc5..eb15676d374f 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -393,10 +393,6 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
break;
case QAM_128:
- delay = 150;
- sweeprate = 1000;
- break;
-
case QAM_256:
delay = 200;
sweeprate = 500;
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
deleted file mode 100644
index d1cabb6a0a13..000000000000
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- * tda80xx.c
- *
- * Philips TDA8044 / TDA8083 QPSK demodulator driver
- *
- * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "tda80xx.h"
-
-enum {
- ID_TDA8044 = 0x04,
- ID_TDA8083 = 0x05,
-};
-
-
-struct tda80xx_state {
-
- struct i2c_adapter* i2c;
-
- struct dvb_frontend_ops ops;
-
- /* configuration settings */
- const struct tda80xx_config* config;
-
- struct dvb_frontend frontend;
-
- u32 clk;
- int afc_loop;
- struct work_struct worklet;
- fe_code_rate_t code_rate;
- fe_spectral_inversion_t spectral_inversion;
- fe_status_t status;
- u8 id;
-};
-
-static int debug = 1;
-#define dprintk if (debug) printk
-
-static u8 tda8044_inittab_pre[] = {
- 0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
- 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58,
- 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
- 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00,
- 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
-};
-
-static u8 tda8044_inittab_post[] = {
- 0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
- 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50,
- 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
- 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c,
- 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
-};
-
-static u8 tda8083_inittab[] = {
- 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
- 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
- 0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
- 0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
- 0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-static __inline__ u32 tda80xx_div(u32 a, u32 b)
-{
- return (a + (b / 2)) / b;
-}
-
-static __inline__ u32 tda80xx_gcd(u32 a, u32 b)
-{
- u32 r;
-
- while ((r = a % b)) {
- a = b;
- b = r;
- }
-
- return b;
-}
-
-static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len)
-{
- int ret;
- struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2)
- dprintk("%s: readreg error (reg %02x, ret == %i)\n",
- __FUNCTION__, reg, ret);
-
- mdelay(10);
-
- return (ret == 2) ? 0 : -EREMOTEIO;
-}
-
-static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len)
-{
- int ret;
- u8 wbuf[len + 1];
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 };
-
- wbuf[0] = reg;
- memcpy(&wbuf[1], buf, len);
-
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1)
- dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret);
-
- mdelay(10);
-
- return (ret == 1) ? 0 : -EREMOTEIO;
-}
-
-static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg)
-{
- u8 val;
-
- tda80xx_read(state, reg, &val, 1);
-
- return val;
-}
-
-static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data)
-{
- return tda80xx_write(state, reg, &data, 1);
-}
-
-static int tda80xx_set_parameters(struct tda80xx_state* state,
- fe_spectral_inversion_t inversion,
- u32 symbol_rate,
- fe_code_rate_t fec_inner)
-{
- u8 buf[15];
- u64 ratio;
- u32 clk;
- u32 k;
- u32 sr = symbol_rate;
- u32 gcd;
- u8 scd;
-
- if (symbol_rate > (state->clk * 3) / 16)
- scd = 0;
- else if (symbol_rate > (state->clk * 3) / 32)
- scd = 1;
- else if (symbol_rate > (state->clk * 3) / 64)
- scd = 2;
- else
- scd = 3;
-
- clk = scd ? (state->clk / (scd * 2)) : state->clk;
-
- /*
- * Viterbi decoder:
- * Differential decoding off
- * Spectral inversion unknown
- * QPSK modulation
- */
- if (inversion == INVERSION_ON)
- buf[0] = 0x60;
- else if (inversion == INVERSION_OFF)
- buf[0] = 0x20;
- else
- buf[0] = 0x00;
-
- /*
- * CLK ratio:
- * system clock frequency is up to 64 or 96 MHz
- *
- * formula:
- * r = k * clk / symbol_rate
- *
- * k: 2^21 for caa 0..3,
- * 2^20 for caa 4..5,
- * 2^19 for caa 6..7
- */
- if (symbol_rate <= (clk * 3) / 32)
- k = (1 << 19);
- else if (symbol_rate <= (clk * 3) / 16)
- k = (1 << 20);
- else
- k = (1 << 21);
-
- gcd = tda80xx_gcd(clk, sr);
- clk /= gcd;
- sr /= gcd;
-
- gcd = tda80xx_gcd(k, sr);
- k /= gcd;
- sr /= gcd;
-
- ratio = (u64)k * (u64)clk;
- do_div(ratio, sr);
-
- buf[1] = ratio >> 16;
- buf[2] = ratio >> 8;
- buf[3] = ratio;
-
- /* nyquist filter roll-off factor 35% */
- buf[4] = 0x20;
-
- clk = scd ? (state->clk / (scd * 2)) : state->clk;
-
- /* Anti Alias Filter */
- if (symbol_rate < (clk * 3) / 64)
- printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate);
- else if (symbol_rate <= clk / 16)
- buf[4] |= 0x07;
- else if (symbol_rate <= (clk * 3) / 32)
- buf[4] |= 0x06;
- else if (symbol_rate <= clk / 8)
- buf[4] |= 0x05;
- else if (symbol_rate <= (clk * 3) / 16)
- buf[4] |= 0x04;
- else if (symbol_rate <= clk / 4)
- buf[4] |= 0x03;
- else if (symbol_rate <= (clk * 3) / 8)
- buf[4] |= 0x02;
- else if (symbol_rate <= clk / 2)
- buf[4] |= 0x01;
- else
- buf[4] |= 0x00;
-
- /* Sigma Delta converter */
- buf[5] = 0x00;
-
- /* FEC: Possible puncturing rates */
- if (fec_inner == FEC_NONE)
- buf[6] = 0x00;
- else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9))
- buf[6] = (1 << (8 - fec_inner));
- else if (fec_inner == FEC_AUTO)
- buf[6] = 0xff;
- else
- return -EINVAL;
-
- /* carrier lock detector threshold value */
- buf[7] = 0x30;
- /* AFC1: proportional part settings */
- buf[8] = 0x42;
- /* AFC1: integral part settings */
- buf[9] = 0x98;
- /* PD: Leaky integrator SCPC mode */
- buf[10] = 0x28;
- /* AFC2, AFC1 controls */
- buf[11] = 0x30;
- /* PD: proportional part settings */
- buf[12] = 0x42;
- /* PD: integral part settings */
- buf[13] = 0x99;
- /* AGC */
- buf[14] = 0x50 | scd;
-
- printk("symbol_rate=%u clk=%u\n", symbol_rate, clk);
-
- return tda80xx_write(state, 0x01, buf, sizeof(buf));
-}
-
-static int tda80xx_set_clk(struct tda80xx_state* state)
-{
- u8 buf[2];
-
- /* CLK proportional part */
- buf[0] = (0x06 << 5) | 0x08; /* CMP[2:0], CSP[4:0] */
- /* CLK integral part */
- buf[1] = (0x04 << 5) | 0x1a; /* CMI[2:0], CSI[4:0] */
-
- return tda80xx_write(state, 0x17, buf, sizeof(buf));
-}
-
-#if 0
-static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state)
-{
- /* a constant value is nonsense here imho */
- return tda80xx_writereg(state, 0x22, 0xf9);
-}
-#endif
-
-static int tda80xx_close_loop(struct tda80xx_state* state)
-{
- u8 buf[2];
-
- /* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */
- buf[0] = 0x68;
- /* AFC1: Loop closed, CAR Feedback: 8192 */
- buf[1] = 0x70;
-
- return tda80xx_write(state, 0x0b, buf, sizeof(buf));
-}
-
-static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt)
-{
- schedule_work(priv);
-
- return IRQ_HANDLED;
-}
-
-static void tda80xx_read_status_int(struct tda80xx_state* state)
-{
- u8 val;
-
- static const fe_spectral_inversion_t inv_tab[] = {
- INVERSION_OFF, INVERSION_ON
- };
-
- static const fe_code_rate_t fec_tab[] = {
- FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
- FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8,
- };
-
- val = tda80xx_readreg(state, 0x02);
-
- state->status = 0;
-
- if (val & 0x01) /* demodulator lock */
- state->status |= FE_HAS_SIGNAL;
- if (val & 0x02) /* clock recovery lock */
- state->status |= FE_HAS_CARRIER;
- if (val & 0x04) /* viterbi lock */
- state->status |= FE_HAS_VITERBI;
- if (val & 0x08) /* deinterleaver lock (packet sync) */
- state->status |= FE_HAS_SYNC;
- if (val & 0x10) /* derandomizer lock (frame sync) */
- state->status |= FE_HAS_LOCK;
- if (val & 0x20) /* frontend can not lock */
- state->status |= FE_TIMEDOUT;
-
- if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) {
- printk("tda80xx: closing loop\n");
- tda80xx_close_loop(state);
- state->afc_loop = 0;
- }
-
- if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) {
- val = tda80xx_readreg(state, 0x0e);
- state->code_rate = fec_tab[val & 0x07];
- if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK))
- state->spectral_inversion = inv_tab[(val >> 7) & 0x01];
- else
- state->spectral_inversion = INVERSION_AUTO;
- }
- else {
- state->code_rate = FEC_AUTO;
- }
-}
-
-static void tda80xx_worklet(void *priv)
-{
- struct tda80xx_state *state = priv;
-
- tda80xx_writereg(state, 0x00, 0x04);
- enable_irq(state->config->irq);
-
- tda80xx_read_status_int(state);
-}
-
-static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state)
-{
- size_t i;
-
- for (i = 0; i < 100; i++) {
- if (tda80xx_readreg(state, 0x02) & 0x80)
- break;
- msleep(10);
- }
-}
-
-static int tda8044_init(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
- int ret;
-
- /*
- * this function is a mess...
- */
-
- if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre))))
- return ret;
-
- tda80xx_writereg(state, 0x0f, 0x50);
-#if 1
- tda80xx_writereg(state, 0x20, 0x8F); /* FIXME */
- tda80xx_writereg(state, 0x20, state->config->volt18setting); /* FIXME */
- //tda80xx_writereg(state, 0x00, 0x04);
- tda80xx_writereg(state, 0x00, 0x0C);
-#endif
- //tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */
-
- tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post));
-
- if (state->config->pll_init) {
- tda80xx_writereg(state, 0x1c, 0x80);
- state->config->pll_init(fe);
- tda80xx_writereg(state, 0x1c, 0x00);
- }
-
- return 0;
-}
-
-static int tda8083_init(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
-
- if (state->config->pll_init) {
- tda80xx_writereg(state, 0x1c, 0x80);
- state->config->pll_init(fe);
- tda80xx_writereg(state, 0x1c, 0x00);
- }
-
- return 0;
-}
-
-static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch (voltage) {
- case SEC_VOLTAGE_13:
- return tda80xx_writereg(state, 0x20, state->config->volt13setting);
- case SEC_VOLTAGE_18:
- return tda80xx_writereg(state, 0x20, state->config->volt18setting);
- case SEC_VOLTAGE_OFF:
- return tda80xx_writereg(state, 0x20, 0);
- default:
- return -EINVAL;
- }
-}
-
-static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch (tone) {
- case SEC_TONE_OFF:
- return tda80xx_writereg(state, 0x29, 0x00);
- case SEC_TONE_ON:
- return tda80xx_writereg(state, 0x29, 0x80);
- default:
- return -EINVAL;
- }
-}
-
-static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (cmd->msg_len > 6)
- return -EINVAL;
-
- tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3));
- tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len);
- tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3));
- tda80xx_wait_diseqc_fifo(state);
-
- return 0;
-}
-
-static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch (cmd) {
- case SEC_MINI_A:
- tda80xx_writereg(state, 0x29, 0x14);
- break;
- case SEC_MINI_B:
- tda80xx_writereg(state, 0x29, 0x1c);
- break;
- default:
- return -EINVAL;
- }
-
- tda80xx_wait_diseqc_fifo(state);
-
- return 0;
-}
-
-static int tda80xx_sleep(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- tda80xx_writereg(state, 0x00, 0x02); /* enter standby */
-
- return 0;
-}
-
-static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- tda80xx_writereg(state, 0x1c, 0x80);
- state->config->pll_set(fe, p);
- tda80xx_writereg(state, 0x1c, 0x00);
-
- tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);
- tda80xx_set_clk(state);
- //tda80xx_set_scpc_freq_offset(state);
- state->afc_loop = 1;
-
- return 0;
-}
-
-static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (!state->config->irq)
- tda80xx_read_status_int(state);
-
- p->inversion = state->spectral_inversion;
- p->u.qpsk.fec_inner = state->code_rate;
-
- return 0;
-}
-
-static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (!state->config->irq)
- tda80xx_read_status_int(state);
- *status = state->status;
-
- return 0;
-}
-
-static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
- int ret;
- u8 buf[3];
-
- if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf))))
- return ret;
-
- *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
-
- return 0;
-}
-
-static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- u8 gain = ~tda80xx_readreg(state, 0x01);
- *strength = (gain << 8) | gain;
-
- return 0;
-}
-
-static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- u8 quality = tda80xx_readreg(state, 0x08);
- *snr = (quality << 8) | quality;
-
- return 0;
-}
-
-static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- *ucblocks = tda80xx_readreg(state, 0x0f);
- if (*ucblocks == 0xff)
- *ucblocks = 0xffffffff;
-
- return 0;
-}
-
-static int tda80xx_init(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch(state->id) {
- case ID_TDA8044:
- return tda8044_init(fe);
-
- case ID_TDA8083:
- return tda8083_init(fe);
- }
- return 0;
-}
-
-static void tda80xx_release(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (state->config->irq)
- free_irq(state->config->irq, &state->worklet);
-
- kfree(state);
-}
-
-static struct dvb_frontend_ops tda80xx_ops;
-
-struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
- struct i2c_adapter* i2c)
-{
- struct tda80xx_state* state = NULL;
- int ret;
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops));
- state->spectral_inversion = INVERSION_AUTO;
- state->code_rate = FEC_AUTO;
- state->status = 0;
- state->afc_loop = 0;
-
- /* check if the demod is there */
- if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error;
- state->id = tda80xx_readreg(state, 0x00);
-
- switch (state->id) {
- case ID_TDA8044:
- state->clk = 96000000;
- printk("tda80xx: Detected tda8044\n");
- break;
-
- case ID_TDA8083:
- state->clk = 64000000;
- printk("tda80xx: Detected tda8083\n");
- break;
-
- default:
- goto error;
- }
-
- /* setup IRQ */
- if (state->config->irq) {
- INIT_WORK(&state->worklet, tda80xx_worklet, state);
- if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) {
- printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret);
- goto error;
- }
- }
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops tda80xx_ops = {
-
- .info = {
- .name = "Philips TDA80xx DVB-S",
- .type = FE_QPSK,
- .frequency_min = 500000,
- .frequency_max = 2700000,
- .frequency_stepsize = 125,
- .symbol_rate_min = 4500000,
- .symbol_rate_max = 45000000,
- .caps = FE_CAN_INVERSION_AUTO |
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- FE_CAN_QPSK |
- FE_CAN_MUTE_TS
- },
-
- .release = tda80xx_release,
-
- .init = tda80xx_init,
- .sleep = tda80xx_sleep,
-
- .set_frontend = tda80xx_set_frontend,
- .get_frontend = tda80xx_get_frontend,
-
- .read_status = tda80xx_read_status,
- .read_ber = tda80xx_read_ber,
- .read_signal_strength = tda80xx_read_signal_strength,
- .read_snr = tda80xx_read_snr,
- .read_ucblocks = tda80xx_read_ucblocks,
-
- .diseqc_send_master_cmd = tda80xx_send_diseqc_msg,
- .diseqc_send_burst = tda80xx_send_diseqc_burst,
- .set_tone = tda80xx_set_tone,
- .set_voltage = tda80xx_set_voltage,
-};
-
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver");
-MODULE_AUTHOR("Felix Domke, Andreas Oberritter");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda80xx_attach);
diff --git a/drivers/media/dvb/frontends/tda80xx.h b/drivers/media/dvb/frontends/tda80xx.h
deleted file mode 100644
index cd639a0aad55..000000000000
--- a/drivers/media/dvb/frontends/tda80xx.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * tda80xx.c
- *
- * Philips TDA8044 / TDA8083 QPSK demodulator driver
- *
- * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef TDA80XX_H
-#define TDA80XX_H
-
-#include <linux/dvb/frontend.h>
-
-struct tda80xx_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-
- /* IRQ to use (0=>no IRQ used) */
- u32 irq;
-
- /* Register setting to use for 13v */
- u8 volt13setting;
-
- /* Register setting to use for 18v */
- u8 volt18setting;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-};
-
-extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
- struct i2c_adapter* i2c);
-
-#endif // TDA80XX_H
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 27494901975f..7c6ccb96b157 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -1439,7 +1439,7 @@ static int check_firmware(struct av7110* av7110)
len = ntohl(*(u32*) ptr);
ptr += 4;
if (len >= 512) {
- printk("dvb-ttpci: dpram file is way to big.\n");
+ printk("dvb-ttpci: dpram file is way too big.\n");
return -EINVAL;
}
if (crc != crc32_le(0, ptr, len)) {
@@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break;
+ case 0x0004: // Galaxis DVB-S rev1.3
+ /* ALPS BSRV2 */
+ av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ }
+ break;
+
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
/* Grundig 29504-451 */
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
@@ -2466,7 +2477,8 @@ static int frontend_init(struct av7110 *av7110)
* The same behaviour of missing VSYNC can be duplicated on budget
* cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
*/
-static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
+static int __devinit av7110_attach(struct saa7146_dev* dev,
+ struct saa7146_pci_extension_data *pci_ext)
{
const int length = TS_WIDTH * TS_HEIGHT;
struct pci_dev *pdev = dev->pci;
@@ -2816,7 +2828,7 @@ err_kfree_0:
goto out;
}
-static int av7110_detach(struct saa7146_dev* saa)
+static int __devexit av7110_detach(struct saa7146_dev* saa)
{
struct av7110 *av7110 = saa->ext_priv;
dprintk(4, "%p\n", av7110);
@@ -2930,6 +2942,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
+MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
@@ -2937,13 +2950,13 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
+ MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
-/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
@@ -2962,7 +2975,7 @@ static struct saa7146_extension av7110_extension = {
.module = THIS_MODULE,
.pci_tbl = &pci_tbl[0],
.attach = av7110_attach,
- .detach = av7110_detach,
+ .detach = __devexit_p(av7110_detach),
.irq_mask = MASK_19 | MASK_03 | MASK_10,
.irq_func = av7110_irq,
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 6ea30df2e823..fafd25fab835 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -273,8 +273,6 @@ struct av7110 {
extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid);
-extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
-
extern int av7110_ir_init(struct av7110 *av7110);
extern void av7110_ir_exit(struct av7110 *av7110);
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index b2e63e9fc053..0bb6e74ae7f0 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -245,6 +245,9 @@ int av7110_bootarm(struct av7110 *av7110)
/* test DEBI */
iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
+ /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
+ iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
+
if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
"%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 9138132ad25f..d54bbcdde2cc 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data)
}
+static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
+{
+ int ret = 0;
+
+ dprintk(4, "%p\n", av7110);
+ if (av7110) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+ av7110->ir_config = ir_config;
+ }
+ return ret;
+}
+
+
static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
@@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
}
-int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
-{
- int ret = 0;
-
- dprintk(4, "%p\n", av7110);
- if (av7110) {
- ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
- av7110->ir_config = ir_config;
- }
- return ret;
-}
-
-
static void ir_handler(struct av7110 *av7110, u32 ircom)
{
dprintk(4, "ircommand = %08x\n", ircom);
@@ -208,7 +208,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom)
}
-int __init av7110_ir_init(struct av7110 *av7110)
+int __devinit av7110_ir_init(struct av7110 *av7110)
{
static struct proc_dir_entry *e;
@@ -248,7 +248,7 @@ int __init av7110_ir_init(struct av7110 *av7110)
}
-void __exit av7110_ir_exit(struct av7110 *av7110)
+void __devexit av7110_ir_exit(struct av7110 *av7110)
{
int i;
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index aa4c4c521880..578b20085082 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
we can capture, of the first and second field. */
.vbistart = { 7,320 },
},{
- .v4l2_id = V4L2_STD_NTSC_M,
+ .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
.name = "NTSC",
.Fsc = 28636363,
.swidth = 768,
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 297c32ab51e3..840fe0177121 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -167,29 +167,32 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
- struct v4l2_clip32 *uclips = compat_ptr(up->clips);
- struct v4l2_clip *kclips;
+ struct v4l2_clip32 __user *uclips;
+ struct v4l2_clip __user *kclips;
int n = kp->clipcount;
+ compat_caddr_t p;
+ if (get_user(p, &up->clips))
+ return -EFAULT;
+ uclips = compat_ptr(p);
kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
kp->clips = kclips;
while (--n >= 0) {
- if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) ||
- copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+ if (put_user(n ? kclips + 1 : NULL, &kclips->next))
return -EFAULT;
- kclips->next = n ? kclips + 1 : 0;
uclips += 1;
kclips += 1;
}
} else
- kp->clips = 0;
+ kp->clips = NULL;
return 0;
}
static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) ||
- copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
+ if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
put_user(kp->field, &up->field) ||
put_user(kp->chromakey, &up->chromakey) ||
put_user(kp->clipcount, &up->clipcount))
@@ -199,33 +202,29 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
return 0;
}
static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
return 0;
}
@@ -279,18 +278,16 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_standard)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_standard)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_standard)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_standard)))
+ return -EFAULT;
return 0;
}
@@ -328,18 +325,16 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
return 0;
}
@@ -380,11 +375,13 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
break;
case V4L2_MEMORY_USERPTR:
{
- unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
+ compat_long_t tmp;
- if(get_user(kp->length, &up->length) ||
- get_user(kp->m.userptr, &tmp))
- return -EFAULT;
+ if (get_user(kp->length, &up->length) ||
+ get_user(tmp, &up->m.userptr))
+ return -EFAULT;
+
+ kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
case V4L2_MEMORY_OVERLAY:
@@ -468,33 +465,29 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) ||
- copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) ||
- copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
return 0;
}
static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_input)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_input)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_input)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_input)))
+ return -EFAULT;
return 0;
}
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 9f59541155d9..85d964b5b33c 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3369,7 +3369,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
//DBG("cpia_ioctl: %u\n", ioctlnr);
switch (ioctlnr) {
- /* query capabilites */
+ /* query capabilities */
case VIDIOCGCAP:
{
struct video_capability *b = arg;
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index c66c2c1f4809..5588b9a5c430 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_NTSC) {
- /* NTSC */
- if (state->pvr150_workaround) {
- /* Certain Hauppauge PVR150 models have a hardware bug
- that causes audio to drop out. For these models the
- audio standard must be set explicitly.
- To be precise: it affects cards with tuner models
- 85, 99 and 112 (model numbers from tveeprom). */
- if (std == V4L2_STD_NTSC_M_JP) {
- /* Japan uses EIAJ audio standard */
- cx25840_write(client, 0x808, 0x2f);
- } else {
- /* Others use the BTSC audio standard */
- cx25840_write(client, 0x808, 0x1f);
- }
- /* South Korea uses the A2-M (aka Zweiton M) audio
- standard, and should set 0x808 to 0x3f, but I don't
- know how to detect this. */
- } else if (std == V4L2_STD_NTSC_M_JP) {
+ /* Certain Hauppauge PVR150 models have a hardware bug
+ that causes audio to drop out. For these models the
+ audio standard must be set explicitly.
+ To be precise: it affects cards with tuner models
+ 85, 99 and 112 (model numbers from tveeprom). */
+ int hw_fix = state->pvr150_workaround;
+
+ if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */
- cx25840_write(client, 0x808, 0xf7);
+ cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
+ } else if (std == V4L2_STD_NTSC_M_KR) {
+ /* South Korea uses A2 audio standard */
+ cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
} else {
/* Others use the BTSC audio standard */
- cx25840_write(client, 0x808, 0xf6);
+ cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
}
- /* South Korea uses the A2-M (aka Zweiton M) audio standard,
- and should set 0x808 to 0xf8, but I don't know how to
- detect this. */
cx25840_write(client, 0x80b, 0x00);
}
@@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
u8 fmt=0; /* zero is autodetect */
/* First tests should be against specific std */
- if (std & V4L2_STD_NTSC_M_JP) {
+ if (std == V4L2_STD_NTSC_M_JP) {
fmt=0x2;
- } else if (std & V4L2_STD_NTSC_443) {
+ } else if (std == V4L2_STD_NTSC_443) {
fmt=0x3;
- } else if (std & V4L2_STD_PAL_M) {
+ } else if (std == V4L2_STD_PAL_M) {
fmt=0x5;
- } else if (std & V4L2_STD_PAL_N) {
+ } else if (std == V4L2_STD_PAL_N) {
fmt=0x6;
- } else if (std & V4L2_STD_PAL_Nc) {
+ } else if (std == V4L2_STD_PAL_Nc) {
fmt=0x7;
- } else if (std & V4L2_STD_PAL_60) {
+ } else if (std == V4L2_STD_PAL_60) {
fmt=0x8;
} else {
/* Then, test against generic ones */
@@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
}
switch (fmt) {
- case 0x1: return V4L2_STD_NTSC_M;
+ case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
case 0x2: return V4L2_STD_NTSC_M_JP;
case 0x3: return V4L2_STD_NTSC_443;
case 0x4: return V4L2_STD_PAL;
@@ -577,7 +567,7 @@ static struct v4l2_queryctrl cx25840_qctrl[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 255,
+ .maximum = 127,
.step = 1,
.default_value = 64,
.flags = 0,
@@ -586,7 +576,7 @@ static struct v4l2_queryctrl cx25840_qctrl[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Saturation",
.minimum = 0,
- .maximum = 255,
+ .maximum = 127,
.step = 1,
.default_value = 64,
.flags = 0,
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 53308911ae6e..87d79df05336 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -15,23 +15,10 @@ config VIDEO_CX88
To compile this driver as a module, choose M here: the
module will be called cx8800
-config VIDEO_CX88_DVB
- tristate "DVB/ATSC Support for cx2388x based TV cards"
- depends on VIDEO_CX88 && DVB_CORE
- select VIDEO_BUF_DVB
- ---help---
- This adds support for DVB/ATSC cards based on the
- Connexant 2388x chip.
-
- To compile this driver as a module, choose M here: the
- module will be called cx88-dvb.
-
- You must also select one or more DVB/ATSC demodulators.
- If you are unsure which you need, choose all of them.
-
config VIDEO_CX88_ALSA
tristate "ALSA DMA audio support"
depends on VIDEO_CX88 && SND && EXPERIMENTAL
+ select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio on
Conexant 2388x based TV cards.
@@ -43,11 +30,26 @@ config VIDEO_CX88_ALSA
To compile this driver as a module, choose M here: the
module will be called cx88-alsa.
+config VIDEO_CX88_DVB
+ tristate "DVB/ATSC Support for cx2388x based TV cards"
+ depends on VIDEO_CX88 && DVB_CORE
+ select VIDEO_BUF_DVB
+ ---help---
+ This adds support for DVB/ATSC cards based on the
+ Connexant 2388x chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cx88-dvb.
+
+ You must also select one or more DVB/ATSC demodulators.
+ If you are unsure which you need, choose all of them.
+
config VIDEO_CX88_DVB_ALL_FRONTENDS
bool "Build all supported frontends for cx2388x based TV cards"
default y
depends on VIDEO_CX88_DVB
select DVB_MT352
+ select VIDEO_CX88_VP3054
select DVB_OR51132
select DVB_CX22702
select DVB_LGDT330X
@@ -69,6 +71,16 @@ config VIDEO_CX88_DVB_MT352
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator.
+config VIDEO_CX88_VP3054
+ tristate "VP-3054 Secondary I2C Bus Support"
+ default m
+ depends on DVB_MT352
+ ---help---
+ This adds DVB-T support for cards based on the
+ Connexant 2388x chip and the MT352 demodulator,
+ which also require support for the VP-3054
+ Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
config VIDEO_CX88_DVB_OR51132
bool "OR51132 ATSC Support"
default y
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 6e5eaa22619e..2b902784facc 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -4,8 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
+obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -18,6 +19,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1
-extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
+extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index a2e36a1e5f59..2acccd6d49bc 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages");
* BOARD Specific: Sets audio DMA
*/
-int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
{
struct cx88_buffer *buf = chip->buf;
struct cx88_core *core=chip->core;
@@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip)
/*
* BOARD Specific: Resets audio DMA
*/
-int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
{
struct cx88_core *core=chip->core;
dprintk(1, "Stopping audio DMA\n");
@@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = {
* Only boards with eeprom and byte 1 at eeprom=1 have it
*/
-struct pci_device_id cx88_audio_pci_tbl[] = {
+static struct pci_device_id cx88_audio_pci_tbl[] = {
{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0, }
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index ad2f565f522c..1bc999247fdc 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1246,6 +1246,11 @@ struct cx88_subid cx88_subids[] = {
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
},{
.subvendor = 0x18ac,
+ .subdevice = 0xdb54,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+ /* Re-branded DViCO: DigitalNow DVB-T Dual */
+ },{
+ .subvendor = 0x18ac,
.subdevice = 0xdb11,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
/* Re-branded DViCO: UltraView DVB-T Plus */
@@ -1293,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
switch (tv.model)
{
case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
+ case 34519: /* WinTV-PCI-FM */
case 90002: /* Nova-T-PCI (9002) */
case 92001: /* Nova-S-Plus (Video and IR) */
case 92002: /* Nova-S-Plus (Video and IR) */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 8d6d6a6cf785..3720f24a25cf 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -787,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
int cx88_start_audio_dma(struct cx88_core *core)
{
+ /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
+ int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
/* setup fifo + format */
- cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
- cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
- cx_write(MO_AUDD_LNGTH, 128); /* fifo bpl size */
- cx_write(MO_AUDR_LNGTH, 128); /* fifo bpl size */
+ cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
+ cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
/* start dma */
cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index da2ad5c4b553..165d948624a3 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -482,6 +482,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
switch (core->board) {
case CX88_BOARD_DNTV_LIVE_DVB_T:
case CX88_BOARD_KWORLD_DVB_T:
+ case CX88_BOARD_KWORLD_DVB_T_CX22702:
ir_codes = ir_codes_dntv_live_dvb_t;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keycode = 0x1f;
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index dff3893f32fd..e5ee8bceb210 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
{
int ret, byte;
+ if (dev->state & DEV_DISCONNECTED)
+ return(-ENODEV);
+
em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
@@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
u8 val;
int ret;
+ if (dev->state & DEV_DISCONNECTED)
+ return(-ENODEV);
+
em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
@@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
int ret;
/*usb_control_msg seems to expect a kmalloced buffer */
- unsigned char *bufs = kmalloc(len, GFP_KERNEL);
+ unsigned char *bufs;
+
+ if (dev->state & DEV_DISCONNECTED)
+ return(-ENODEV);
+
+ bufs = kmalloc(len, GFP_KERNEL);
em28xx_regdbg("req=%02x reg=%02x:", req, reg);
@@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, bufs, len, HZ);
- mdelay(5); /* FIXME: magic number */
+ msleep(5); /* FIXME: magic number */
kfree(bufs);
return ret;
}
@@ -253,7 +264,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret;
else if (((u8) ret) & 0x01) {
- em28xx_warn ("AC97 command still being exectuted: not handled properly!\n");
+ em28xx_warn ("AC97 command still being executed: not handled properly!\n");
}
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 0591a705b7a1..6ca8631bc36d 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
ret = dev->em28xx_read_reg(dev, 0x05);
if (ret == 0x80 + len - 1)
return len;
- mdelay(5);
+ msleep(5);
}
em28xx_warn("i2c write timed out\n");
return -EIO;
@@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
return -ENODEV;
else if (msg == 0x84)
return 0;
- mdelay(5);
+ msleep(5);
}
return -ENODEV;
}
@@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
msgs[i].buf,
msgs[i].len,
i == num - 1);
- if (rc < 0)
- goto err;
}
+ if (rc < 0)
+ goto err;
if (i2c_debug>=2)
printk("\n");
}
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index eea304f75176..5b267808a9d4 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -6,6 +6,9 @@
Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Sascha Sommer <saschasommer@freenet.de>
+ Some parts based on SN9C10x PC Camera Controllers GPL driver made
+ by Luca Risolia <luca.risolia@studio.unibo.it>
+
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
@@ -364,6 +367,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
em28xx_capture_start(dev, 1);
em28xx_resolution_set(dev);
+ /* device needs to be initialized before isoc transfer */
+ video_mux(dev, 0);
+
/* start the transfer */
errCode = em28xx_init_isoc(dev);
if (errCode)
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index 8416ceff524b..41715cacf926 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -1,7 +1,7 @@
/*
mxb - v4l2 driver for the Multimedia eXtension Board
- Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+ Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
Visit http://www.mihu.de/linux/saa7146/mxb/
for further details about this card.
@@ -327,6 +327,7 @@ static int mxb_init_done(struct saa7146_dev* dev)
struct video_decoder_init init;
struct i2c_msg msg;
struct tuner_setup tun_setup;
+ v4l2_std_id std = V4L2_STD_PAL_BG;
int i = 0, err = 0;
struct tea6415c_multiplex vm;
@@ -361,6 +362,9 @@ static int mxb_init_done(struct saa7146_dev* dev)
mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY,
&mxb->cur_freq);
+ /* set a default video standard */
+ mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
+
/* mute audio on tea6420s */
mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
@@ -921,17 +925,21 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
int one = 1;
if(V4L2_STD_PAL_I == std->id ) {
+ v4l2_std_id std = V4L2_STD_PAL_I;
DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* unset the 7111 gpio register -- I don't know what this does exactly */
mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero);
+ mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
} else {
+ v4l2_std_id std = V4L2_STD_PAL_BG;
DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* set the 7111 gpio register -- I don't know what this does exactly */
mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one);
+ mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
}
return 0;
}
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 048d000941c7..ffd87ce55556 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1027,7 +1027,7 @@ static struct v4l2_queryctrl saa7115_qctrl[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 255,
+ .maximum = 127,
.step = 1,
.default_value = 64,
.flags = 0,
@@ -1036,7 +1036,7 @@ static struct v4l2_queryctrl saa7115_qctrl[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Saturation",
.minimum = 0,
- .maximum = 255,
+ .maximum = 127,
.step = 1,
.default_value = 64,
.flags = 0,
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index a7a6ab9298a9..7df5e0826e12 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -54,10 +54,12 @@ MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444);
+module_param_array(enable, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
+MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s).");
#define dprintk(fmt, arg...) if (debug) \
printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg)
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index c64718aec9cb..6bc63a4086c1 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_FLYVIDEO2000] = {
/* "TC Wan" <tcwan@cs.usm.my> */
- .name = "LifeView FlyVIDEO2000",
+ .name = "LifeView/Typhoon FlyVIDEO2000",
.audio_clock = 0x00200000,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.radio_type = UNSET,
@@ -977,7 +977,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -1666,7 +1666,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
@@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x000,
},
},
- [SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = {
- .name = "Typhoon DVB-T Duo Digital/Analog Cardbus",
+ [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
+ .name = "LifeView/Typhoon FlyDVB-T Duo Cardbus",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB,
- /* .gpiomask = 0xe000, */
+ .gpiomask = 0x00200000,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
- /* .gpio = 0x0000, */
+ .gpio = 0x200000, /* GPIO21=High for TV input */
.tv = 1,
},{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ },{
.name = name_comp1, /* Composite signal on S-Video input */
.vmux = 0,
.amux = LINE2,
- /* .gpio = 0x4000, */
},{
.name = name_comp2, /* Composite input */
.vmux = 3,
.amux = LINE2,
- /* .gpio = 0x4000, */
- },{
- .name = name_svideo, /* S-Video signal on S-Video input */
- .vmux = 8,
- .amux = LINE2,
- /* .gpio = 0x4000, */
}},
.radio = {
.name = name_radio,
- .amux = LINE2,
- },
- .mute = {
- .name = name_mute,
- .amux = LINE1,
+ .amux = TV,
+ .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
},
},
[SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
@@ -2193,7 +2187,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = 0x61,
.radio_addr = ADDR_UNSET,
- .tda9887_conf = TDA9887_PRESENT,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
@@ -2217,7 +2211,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = 0x61,
.radio_addr = ADDR_UNSET,
- .tda9887_conf = TDA9887_PRESENT,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
@@ -2398,7 +2392,7 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_PINNACLE_PCTV_110i] = {
- .name = "Pinnacle PCTV 110i (saa7133)",
+ .name = "Pinnacle PCTV 40i/50i/110i (saa7133)",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
@@ -2413,6 +2407,10 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_comp1,
.vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = name_comp2,
+ .vmux = 0,
.amux = LINE2,
},{
.name = name_svideo,
@@ -2701,6 +2699,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_FLYVIDEO2000,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x4e42, /* Typhoon */
+ .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */
+ .driver_data = SAA7134_BOARD_FLYVIDEO2000,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168,
.subdevice = 0x0212, /* minipci, LR212 */
@@ -2745,7 +2749,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = 0x1048,
- .subdevice = 0x226b,
+ .subdevice = 0x226a,
.driver_data = SAA7134_BOARD_ELSA_500TV,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
@@ -2935,7 +2939,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168,
.subdevice = 0x0502, /* Cardbus version */
- .driver_data = SAA7134_BOARD_FLYDVBTDUO,
+ .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -2980,12 +2984,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x1370, /* cardbus version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
- },{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */
+ },{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
- .subvendor = 0x4e42,
- .subdevice = 0x0502,
- .driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS,
+ .subvendor = 0x4e42, /* Typhoon */
+ .subdevice = 0x0502, /* LifeView LR502 OEM */
+ .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -3201,13 +3205,17 @@ int saa7134_board_init1(struct saa7134_dev *dev)
/* power-up tuner chip */
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
+ case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
+ /* this turns the remote control chip off to work around a bug in it */
+ saa_writeb(SAA7134_GPIO_GPMODE1, 0x80);
+ saa_writeb(SAA7134_GPIO_GPSTATUS1, 0x80);
+ break;
case SAA7134_BOARD_MONSTERTV_MOBILE:
/* power-up tuner chip */
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
break;
- case SAA7134_BOARD_FLYDVBTDUO:
- case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
+ case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
/* turn the fan on */
saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 399f9952596c..9db8e13f21c3 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -110,6 +110,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
mt352_write(fe, fsm_ctl_cfg, sizeof(fsm_ctl_cfg));
mt352_write(fe, scan_ctl_cfg, sizeof(scan_ctl_cfg));
mt352_write(fe, irq_cfg, sizeof(irq_cfg));
+
return 0;
}
@@ -117,8 +118,10 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
u8* pllbuf)
{
- static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
- static int off = TDA9887_PRESENT | TDA9887_PORT2_ACTIVE;
+ u8 off[] = { 0x00, 0xf1};
+ u8 on[] = { 0x00, 0x71};
+ struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)};
+
struct saa7134_dev *dev = fe->dvb->priv;
struct v4l2_frequency f;
@@ -126,9 +129,10 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe,
f.tuner = 0;
f.type = V4L2_TUNER_DIGITAL_TV;
f.frequency = params->frequency / 1000 * 16 / 1000;
- saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on);
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
- saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&off);
+ msg.buf = on;
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
pinnacle_antenna_pwr(dev, antenna_pwr);
@@ -861,7 +865,7 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap);
break;
- case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
+ case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap);
break;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index e70eae8d29bb..3261d8bebdd1 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -185,7 +185,7 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
#define SAA7134_BOARD_ADS_INSTANT_TV 58
#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
-#define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60
+#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
#define SAA7134_BOARD_PHILIPS_TOUGH 61
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
#define SAA7134_BOARD_KWORLD_XPERT 63
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 54fc33011ffb..9d769264a329 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
{
struct saa7146 *saa = pci_get_drvdata(pdev);
- memset(saa, 0, sizeof(*saa));
saa->user = 0;
/* reset the saa7146 */
saawrite(0xffff0000, SAA7146_MC1);
@@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
}
if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
- goto errvid;
+ goto errfree;
}
if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
- goto erraud;
+ goto errfree;
}
/* allocate 81920 byte buffer for clipping */
if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
- goto errosd;
+ goto errfree;
}
/* setup clipping registers */
saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
@@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
I2CBusScan(saa);
return 0;
-errosd:
+errfree:
vfree(saa->osdbuf);
- saa->osdbuf = NULL;
-erraud:
vfree(saa->audbuf);
- saa->audbuf = NULL;
-errvid:
vfree(saa->vidbuf);
- saa->vidbuf = NULL;
+ saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
err:
return -ENOMEM;
}
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index 7b4fb282ac82..a796a4e1917c 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -580,9 +580,10 @@ int tda8290_init(struct i2c_client *c)
int tda8290_probe(struct i2c_client *c)
{
- unsigned char soft_reset[] = { 0x00, 0x00 };
- unsigned char easy_mode_b[] = { 0x01, 0x02 };
- unsigned char easy_mode_g[] = { 0x01, 0x04 };
+ unsigned char soft_reset[] = { 0x00, 0x00 };
+ unsigned char easy_mode_b[] = { 0x01, 0x02 };
+ unsigned char easy_mode_g[] = { 0x01, 0x04 };
+ unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
unsigned char addr_dto_lsb = 0x07;
unsigned char data;
@@ -599,6 +600,7 @@ int tda8290_probe(struct i2c_client *c)
return 0;
}
}
+ i2c_master_send(c, restore_9886, 3);
return -1;
}
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 5815649bdc78..0d54f6c1982b 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = {
cAudioIF_6_5 |
cVideoIF_38_90 ),
},{
- .std = V4L2_STD_NTSC_M,
+ .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
.name = "NTSC-M",
.b = ( cNegativeFmTV |
cQSS ),
@@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
t->std = V4L2_STD_NTSC_M_JP;
break;
+ case 'k':
+ case 'K':
+ tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
+ t->std = V4L2_STD_NTSC_M_KR;
+ break;
case '-':
/* default parameter, do nothing */
break;
@@ -876,7 +881,7 @@ static int tda9887_resume(struct device * dev)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .id = -1, /* FIXME */
+ .id = I2C_DRIVERID_TDA9887,
.attach_adapter = tda9887_probe,
.detach_client = tda9887_detach,
.command = tda9887_command,
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 2995b22acb43..b6101bf446d4 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -216,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
buffer[3] = 0xa4;
i2c_master_send(c,buffer,4);
default_tuner_init(c);
+ break;
default:
default_tuner_init(c);
break;
@@ -365,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
t->std = V4L2_STD_NTSC_M_JP;
break;
+ case 'k':
+ case 'K':
+ tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
+ t->std = V4L2_STD_NTSC_M_KR;
+ break;
case '-':
/* default parameter, do nothing */
break;
@@ -448,7 +454,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
printk("%02x ",buffer[i]);
printk("\n");
}
- /* TEA5767 autodetection code - only for addr = 0xc0 */
+ /* autodetection code based on the i2c addr */
if (!no_autodetect) {
switch (addr) {
case 0x42:
@@ -707,8 +713,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct v4l2_frequency *f = arg;
switch_v4l2();
- if (V4L2_TUNER_RADIO == f->type &&
- V4L2_TUNER_RADIO != t->mode) {
+ if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode)
+ || (V4L2_TUNER_DIGITAL_TV == f->type
+ && V4L2_TUNER_DIGITAL_TV != t->mode)) {
if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
== EINVAL)
return 0;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 6d03b9b05c6e..c8e5ad0e8185 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9840_SW, t);
}
+static int tda9840_checkit(struct CHIPSTATE *chip)
+{
+ int rc;
+ rc = chip_read(chip);
+ /* lower 5 bits should be 0 */
+ return ((rc & 0x1f) == 0) ? 1 : 0;
+}
+
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda985x */
@@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = {
.addr_hi = I2C_TDA9840 >> 1,
.registers = 5,
+ .checkit = tda9840_checkit,
.getmode = tda9840_getmode,
.setmode = tda9840_setmode,
.checkmode = generic_checkmode,
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index fad9ea0ae4f2..1864423b3046 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std)
static inline void tvp5150_reset(struct i2c_client *c)
{
- u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom;
+ u8 msb_id, lsb_id, msb_rom, lsb_rom;
struct tvp5150 *decoder = i2c_get_clientdata(c);
- type=tvp5150_read(c,TVP5150_AUTOSW_MSK);
msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID);
lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID);
msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER);
lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER);
- if (type==0xdc) {
- ver_656=tvp5150_read(c,TVP5150_REV_SELECT);
- tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656);
- } else if (type==0xfc) {
- tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+ if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */
+ tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id);
+
+ /* ITU-T BT.656.4 timing */
+ tvp5150_write(c,TVP5150_REV_SELECT,0);
} else {
- tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type);
+ if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */
+ tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+ } else {
+ tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id);
+ tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom);
+ }
}
- tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom);
/* Initializes TVP5150 to its default values */
tvp5150_write_inittab(c, tvp5150_init_default);
@@ -893,6 +896,17 @@ static int tvp5150_command(struct i2c_client *c,
}
case DECODER_GET_STATUS:
{
+ int *iarg = arg;
+ int status;
+ int res=0;
+ status = tvp5150_read(c, 0x88);
+ if(status&0x08){
+ res |= DECODER_STATUS_COLOR;
+ }
+ if(status&0x04 && status&0x02){
+ res |= DECODER_STATUS_GOOD;
+ }
+ *iarg=res;
break;
}
diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h
index 156ae57096fe..b1239ac7f371 100644
--- a/drivers/media/video/videocodec.h
+++ b/drivers/media/video/videocodec.h
@@ -56,7 +56,7 @@
the slave is bound to it). Otherwise it doesn't need this functions and
therfor they may not be initialized.
- The other fuctions are just for convenience, as they are for shure used by
+ The other fuctions are just for convenience, as they are for sure used by
most/all of the codecs. The last ones may be ommited, too.
See the structure declaration below for more information and which data has
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index bd0cd28543ca..6699725be605 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -159,7 +159,7 @@ zr36050_wait_end (struct zr36050 *ptr)
while (!(zr36050_read_status1(ptr) & 0x4)) {
udelay(1);
- if (i++ > 200000) { // 200ms, there is for shure something wrong!!!
+ if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
dprintk(1,
"%s: timout at wait_end (last status: 0x%02x)\n",
ptr->name, ptr->status1);
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
index 28fa31a5f150..d8dd003a7aad 100644
--- a/drivers/media/video/zr36060.c
+++ b/drivers/media/video/zr36060.c
@@ -161,7 +161,7 @@ zr36060_wait_end (struct zr36060 *ptr)
while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
udelay(1);
- if (i++ > 200000) { // 200ms, there is for shure something wrong!!!
+ if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
dprintk(1,
"%s: timout at wait_end (last status: 0x%02x)\n",
ptr->name, ptr->status);
diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c
index 6bfe84d657f1..21fde43a6aed 100644
--- a/drivers/media/video/zr36120_i2c.c
+++ b/drivers/media/video/zr36120_i2c.c
@@ -65,7 +65,7 @@ void attach_inform(struct i2c_bus *bus, int id)
case I2C_DRIVERID_VIDEODECODER:
DEBUG(printk(CARD_INFO "decoder attached\n",CARD));
- /* fetch the capabilites of the decoder */
+ /* fetch the capabilities of the decoder */
rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc);
if (rv) {
DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD));
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 9a2c7605d49c..642a61b6d0a4 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -452,8 +452,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
} else if (func == MPI_FUNCTION_EVENT_ACK) {
dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
ioc->name));
- } else if (func == MPI_FUNCTION_CONFIG ||
- func == MPI_FUNCTION_TOOLBOX) {
+ } else if (func == MPI_FUNCTION_CONFIG) {
CONFIGPARMS *pCfg;
unsigned long flags;
@@ -5327,115 +5326,6 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mpt_toolbox - Generic function to issue toolbox message
- * @ioc - Pointer to an adapter structure
- * @cfg - Pointer to a toolbox structure. Struct contains
- * action, page address, direction, physical address
- * and pointer to a configuration page header
- * Page header is updated.
- *
- * Returns 0 for success
- * -EPERM if not allowed due to ISR context
- * -EAGAIN if no msg frames currently available
- * -EFAULT for non-successful reply or no reply (timeout)
- */
-int
-mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
-{
- ToolboxIstwiReadWriteRequest_t *pReq;
- MPT_FRAME_HDR *mf;
- struct pci_dev *pdev;
- unsigned long flags;
- int rc;
- u32 flagsLength;
- int in_isr;
-
- /* Prevent calling wait_event() (below), if caller happens
- * to be in ISR context, because that is fatal!
- */
- in_isr = in_interrupt();
- if (in_isr) {
- dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
- ioc->name));
- return -EPERM;
- }
-
- /* Get and Populate a free Frame
- */
- if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
- dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
- ioc->name));
- return -EAGAIN;
- }
- pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
- pReq->Tool = pCfg->action;
- pReq->Reserved = 0;
- pReq->ChainOffset = 0;
- pReq->Function = MPI_FUNCTION_TOOLBOX;
- pReq->Reserved1 = 0;
- pReq->Reserved2 = 0;
- pReq->MsgFlags = 0;
- pReq->Flags = pCfg->dir;
- pReq->BusNum = 0;
- pReq->Reserved3 = 0;
- pReq->NumAddressBytes = 0x01;
- pReq->Reserved4 = 0;
- pReq->DataLength = cpu_to_le16(0x04);
- pdev = ioc->pcidev;
- if (pdev->devfn & 1)
- pReq->DeviceAddr = 0xB2;
- else
- pReq->DeviceAddr = 0xB0;
- pReq->Addr1 = 0;
- pReq->Addr2 = 0;
- pReq->Addr3 = 0;
- pReq->Reserved5 = 0;
-
- /* Add a SGE to the config request.
- */
-
- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
-
- mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
-
- dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
- ioc->name, pReq->Tool));
-
- /* Append pCfg pointer to end of mf
- */
- *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
-
- /* Initalize the timer
- */
- init_timer(&pCfg->timer);
- pCfg->timer.data = (unsigned long) ioc;
- pCfg->timer.function = mpt_timer_expired;
- pCfg->wait_done = 0;
-
- /* Set the timer; ensure 10 second minimum */
- if (pCfg->timeout < 10)
- pCfg->timer.expires = jiffies + HZ*10;
- else
- pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
-
- /* Add to end of Q, set timer and then issue this command */
- spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&pCfg->linkage, &ioc->configQ);
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
- add_timer(&pCfg->timer);
- mpt_put_msg_frame(mpt_base_index, ioc, mf);
- wait_event(mpt_waitq, pCfg->wait_done);
-
- /* mf has been freed - do not access */
-
- rc = pCfg->status;
-
- return rc;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_timer_expired - Call back for timer process.
* Used only internal config functionality.
@@ -6142,7 +6032,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
int idx;
- idx = ioc->eventContext % ioc->eventLogSize;
+ idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
ioc->events[idx].event = event;
ioc->events[idx].eventContext = ioc->eventContext;
@@ -6540,7 +6430,6 @@ EXPORT_SYMBOL(mpt_lan_index);
EXPORT_SYMBOL(mpt_stm_index);
EXPORT_SYMBOL(mpt_HardResetHandler);
EXPORT_SYMBOL(mpt_config);
-EXPORT_SYMBOL(mpt_toolbox);
EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index ea2649ecad1f..723d54300953 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -616,6 +616,7 @@ typedef struct _MPT_ADAPTER
* increments by 32 bytes
*/
int errata_flag_1064;
+ int aen_event_read_flag; /* flag to indicate event log was read*/
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
@@ -1026,7 +1027,6 @@ extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
-extern int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index bdf709987982..9b64e07400da 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -136,6 +136,12 @@ static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
*/
static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
+/*
+ * Event Handler function
+ */
+static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+struct fasync_struct *async_queue=NULL;
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Scatter gather list (SGL) sizes and limits...
@@ -385,18 +391,18 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
}
/* Now wait for the command to complete */
- ii = wait_event_interruptible_timeout(mptctl_wait,
+ ii = wait_event_timeout(mptctl_wait,
ioctl->wait_done == 1,
HZ*5 /* 5 second timeout */);
if(ii <=0 && (ioctl->wait_done != 1 )) {
+ mpt_free_msg_frame(hd->ioc, mf);
ioctl->wait_done = 0;
retval = -1; /* return failure */
}
mptctl_bus_reset_done:
- mpt_free_msg_frame(hd->ioc, mf);
mptctl_free_tm_flags(ioctl->ioc);
return retval;
}
@@ -472,6 +478,69 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* ASYNC Event Notification Support */
+static int
+mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+ u8 event;
+
+ event = le32_to_cpu(pEvReply->Event) & 0xFF;
+
+ dctlprintk(("%s() called\n", __FUNCTION__));
+ if(async_queue == NULL)
+ return 1;
+
+ /* Raise SIGIO for persistent events.
+ * TODO - this define is not in MPI spec yet,
+ * but they plan to set it to 0x21
+ */
+ if (event == 0x21 ) {
+ ioc->aen_event_read_flag=1;
+ dctlprintk(("Raised SIGIO to application\n"));
+ devtprintk(("Raised SIGIO to application\n"));
+ kill_fasync(&async_queue, SIGIO, POLL_IN);
+ return 1;
+ }
+
+ /* This flag is set after SIGIO was raised, and
+ * remains set until the application has read
+ * the event log via ioctl=MPTEVENTREPORT
+ */
+ if(ioc->aen_event_read_flag)
+ return 1;
+
+ /* Signal only for the events that are
+ * requested for by the application
+ */
+ if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
+ ioc->aen_event_read_flag=1;
+ dctlprintk(("Raised SIGIO to application\n"));
+ devtprintk(("Raised SIGIO to application\n"));
+ kill_fasync(&async_queue, SIGIO, POLL_IN);
+ }
+ return 1;
+}
+
+static int
+mptctl_fasync(int fd, struct file *filep, int mode)
+{
+ MPT_ADAPTER *ioc;
+
+ list_for_each_entry(ioc, &ioc_list, list)
+ ioc->aen_event_read_flag=0;
+
+ dctlprintk(("%s() called\n", __FUNCTION__));
+ return fasync_helper(fd, filep, mode, &async_queue);
+}
+
+static int
+mptctl_release(struct inode *inode, struct file *filep)
+{
+ dctlprintk(("%s() called\n", __FUNCTION__));
+ return fasync_helper(-1, filep, 0, &async_queue);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* MPT ioctl handler
* cmd - specify the particular IOCTL command to be issued
@@ -674,22 +743,23 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
u16 iocstat;
pFWDownloadReply_t ReplyMsg = NULL;
- dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
+ dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
- dctlprintk((KERN_INFO "DbG: kfwdl.bufp = %p\n", ufwbuf));
- dctlprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen));
- dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc));
+ dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf));
+ dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen));
+ dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc));
- if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) {
- dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
- __FILE__, __LINE__, ioc));
+ if (mpt_verify_adapter(ioc, &iocp) < 0) {
+ dctlprintk(("ioctl_fwdl - ioc%d not found!\n",
+ ioc));
return -ENODEV; /* (-6) No such device or address */
- }
+ } else {
- /* Valid device. Get a message frame and construct the FW download message.
- */
- if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
- return -EAGAIN;
+ /* Valid device. Get a message frame and construct the FW download message.
+ */
+ if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+ return -EAGAIN;
+ }
dlmsg = (FWDownload_t*) mf;
ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
sgOut = (char *) (ptsge + 1);
@@ -702,7 +772,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
dlmsg->ChainOffset = 0;
dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
- dlmsg->MsgFlags = 0;
+ if (iocp->facts.MsgVersion >= MPI_VERSION_01_05)
+ dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
+ else
+ dlmsg->MsgFlags = 0;
+
/* Set up the Transaction SGE.
*/
@@ -754,7 +828,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
goto fwdl_out;
}
- dctlprintk((KERN_INFO "DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
+ dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
/*
* Parse SG list, copying sgl itself,
@@ -803,11 +877,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
/*
* Finally, perform firmware download.
*/
- iocp->ioctl->wait_done = 0;
+ ReplyMsg = NULL;
mpt_put_msg_frame(mptctl_id, iocp, mf);
/* Now wait for the command to complete */
- ret = wait_event_interruptible_timeout(mptctl_wait,
+ ret = wait_event_timeout(mptctl_wait,
iocp->ioctl->wait_done == 1,
HZ*60);
@@ -1145,7 +1219,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
/* Fill in the data and return the structure to the calling
* program
*/
- if (ioc->bus_type == FC)
+ if (ioc->bus_type == SAS)
+ karg->adapterType = MPT_IOCTL_INTERFACE_SAS;
+ else if (ioc->bus_type == FC)
karg->adapterType = MPT_IOCTL_INTERFACE_FC;
else
karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
@@ -1170,12 +1246,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
} else if (cim_rev == 2) {
- /* Get the PCI bus, device, function and segment ID numbers
+ /* Get the PCI bus, device, function and segment ID numbers
for the IOC */
karg->pciInfo.u.bits.busNumber = pdev->bus->number;
karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
- karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);
}
@@ -1500,7 +1575,7 @@ mptctl_eventquery (unsigned long arg)
return -ENODEV;
}
- karg.eventEntries = ioc->eventLogSize;
+ karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
karg.eventTypes = ioc->eventTypes;
/* Copy the data from kernel memory to user memory
@@ -1550,7 +1625,6 @@ mptctl_eventenable (unsigned long arg)
memset(ioc->events, 0, sz);
ioc->alloc_total += sz;
- ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE;
ioc->eventContext = 0;
}
@@ -1590,7 +1664,7 @@ mptctl_eventreport (unsigned long arg)
maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
- max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents;
+ max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents;
/* If fewer than 1 event is requested, there must have
* been some type of error.
@@ -1598,6 +1672,9 @@ mptctl_eventreport (unsigned long arg)
if ((max < 1) || !ioc->events)
return -ENODATA;
+ /* reset this flag so SIGIO can restart */
+ ioc->aen_event_read_flag=0;
+
/* Copy the data from kernel memory to user memory
*/
numBytes = max * sizeof(MPT_IOCTL_EVENTS);
@@ -1817,6 +1894,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
case MPI_FUNCTION_FW_DOWNLOAD:
case MPI_FUNCTION_FC_PRIMITIVE_SEND:
+ case MPI_FUNCTION_TOOLBOX:
+ case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
break;
case MPI_FUNCTION_SCSI_IO_REQUEST:
@@ -1837,7 +1916,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
goto done_free_mem;
}
- pScsiReq->MsgFlags = mpt_msg_flags();
+ pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+ pScsiReq->MsgFlags |= mpt_msg_flags();
+
/* verify that app has not requested
* more sense data than driver
@@ -1888,6 +1969,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
}
break;
+ case MPI_FUNCTION_SMP_PASSTHROUGH:
+ /* Check mf->PassthruFlags to determine if
+ * transfer is ImmediateMode or not.
+ * Immediate mode returns data in the ReplyFrame.
+ * Else, we are sending request and response data
+ * in two SGLs at the end of the mf.
+ */
+ break;
+
+ case MPI_FUNCTION_SATA_PASSTHROUGH:
+ if (!ioc->sh) {
+ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ "SCSI driver is not loaded. \n",
+ __FILE__, __LINE__);
+ rc = -EFAULT;
+ goto done_free_mem;
+ }
+ break;
+
case MPI_FUNCTION_RAID_ACTION:
/* Just add a SGE
*/
@@ -1900,7 +2000,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int scsidir = MPI_SCSIIO_CONTROL_READ;
int dataSize;
- pScsiReq->MsgFlags = mpt_msg_flags();
+ pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+ pScsiReq->MsgFlags |= mpt_msg_flags();
+
/* verify that app has not requested
* more sense data than driver
@@ -2130,7 +2232,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* Now wait for the command to complete */
timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
- timeout = wait_event_interruptible_timeout(mptctl_wait,
+ timeout = wait_event_timeout(mptctl_wait,
ioc->ioctl->wait_done == 1,
HZ*timeout);
@@ -2246,13 +2348,16 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
hp_host_info_t __user *uarg = (void __user *) arg;
MPT_ADAPTER *ioc;
struct pci_dev *pdev;
- char *pbuf;
+ char *pbuf=NULL;
dma_addr_t buf_dma;
hp_host_info_t karg;
CONFIGPARMS cfg;
ConfigPageHeader_t hdr;
int iocnum;
int rc, cim_rev;
+ ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
+ MPT_FRAME_HDR *mf = NULL;
+ MPIHeader_t *mpi_hdr;
dctlprintk((": mptctl_hp_hostinfo called.\n"));
/* Reset long to int. Should affect IA64 and SPARC only
@@ -2370,7 +2475,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
karg.base_io_addr = pci_resource_start(pdev, 0);
- if (ioc->bus_type == FC)
+ if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
karg.bus_phys_width = HP_BUS_WIDTH_UNK;
else
karg.bus_phys_width = HP_BUS_WIDTH_16;
@@ -2388,20 +2493,67 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
}
}
- cfg.pageAddr = 0;
- cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
- cfg.dir = MPI_TB_ISTWI_FLAGS_READ;
- cfg.timeout = 10;
+ /*
+ * Gather ISTWI(Industry Standard Two Wire Interface) Data
+ */
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+ dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+ ioc->name,__FUNCTION__));
+ goto out;
+ }
+
+ IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
+ mpi_hdr = (MPIHeader_t *) mf;
+ memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
+ IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
+ IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
+ IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
+ IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
+ IstwiRWRequest->NumAddressBytes = 0x01;
+ IstwiRWRequest->DataLength = cpu_to_le16(0x04);
+ if (pdev->devfn & 1)
+ IstwiRWRequest->DeviceAddr = 0xB2;
+ else
+ IstwiRWRequest->DeviceAddr = 0xB0;
+
pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
- if (pbuf) {
- cfg.physAddr = buf_dma;
- if ((mpt_toolbox(ioc, &cfg)) == 0) {
- karg.rsvd = *(u32 *)pbuf;
- }
- pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
- pbuf = NULL;
+ if (!pbuf)
+ goto out;
+ mpt_add_sge((char *)&IstwiRWRequest->SGL,
+ (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
+
+ ioc->ioctl->wait_done = 0;
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
+
+ rc = wait_event_timeout(mptctl_wait,
+ ioc->ioctl->wait_done == 1,
+ HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
+
+ if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
+ /*
+ * Now we need to reset the board
+ */
+ mpt_free_msg_frame(ioc, mf);
+ mptctl_timeout_expired(ioc->ioctl);
+ goto out;
}
+ /*
+ *ISTWI Data Definition
+ * pbuf[0] = FW_VERSION = 0x4
+ * pbuf[1] = Bay Count = 6 or 4 or 2, depending on
+ * the config, you should be seeing one out of these three values
+ * pbuf[2] = Drive Installed Map = bit pattern depend on which
+ * bays have drives in them
+ * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
+ */
+ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
+ karg.rsvd = *(u32 *)pbuf;
+
+ out:
+ if (pbuf)
+ pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
+
/* Copy the data from kernel memory to user memory
*/
if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
@@ -2459,7 +2611,7 @@ mptctl_hp_targetinfo(unsigned long arg)
/* There is nothing to do for FCP parts.
*/
- if (ioc->bus_type == FC)
+ if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
return 0;
if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
@@ -2569,6 +2721,8 @@ mptctl_hp_targetinfo(unsigned long arg)
static struct file_operations mptctl_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
+ .release = mptctl_release,
+ .fasync = mptctl_fasync,
.unlocked_ioctl = mptctl_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_mpctl_ioctl,
@@ -2813,6 +2967,11 @@ static int __init mptctl_init(void)
/* FIXME! */
}
+ if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
+ devtprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
return 0;
out_fail:
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index 518996e03481..a2f8a97992e6 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -169,8 +169,10 @@ struct mpt_ioctl_pci_info2 {
* Read only.
* Data starts at offset 0xC
*/
-#define MPT_IOCTL_INTERFACE_FC (0x01)
#define MPT_IOCTL_INTERFACE_SCSI (0x00)
+#define MPT_IOCTL_INTERFACE_FC (0x01)
+#define MPT_IOCTL_INTERFACE_FC_IP (0x02)
+#define MPT_IOCTL_INTERFACE_SAS (0x03)
#define MPT_IOCTL_VERSION_LENGTH (32)
struct mpt_ioctl_iocinfo {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 05789e505464..4fee6befc93d 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2489,7 +2489,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
int idx;
MPT_ADAPTER *ioc = hd->ioc;
- idx = ioc->eventContext % ioc->eventLogSize;
+ idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
ioc->events[idx].eventContext = ioc->eventContext;
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index f9e5a23697a1..c08ddac3717d 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -732,7 +732,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
- if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
+ if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
status = SUCCESS;
return status;
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 1cef2387fa65..6aba41954448 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -101,15 +101,16 @@ struct command {
static inline void command_put(struct command *cmd)
{
unsigned long flags;
+ spinlock_t *lock = cmd->lock;
- spin_lock_irqsave(cmd->lock, flags);
- kobject_put(&cmd->kobj);
- spin_unlock_irqrestore(cmd->lock, flags);
+ spin_lock_irqsave(lock, flags);
+ kobject_put(&cmd->kobj);
+ spin_unlock_irqrestore(lock, flags);
}
static inline void command_get(struct command *cmd)
{
- kobject_get(&cmd->kobj);
+ kobject_get(&cmd->kobj);
}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c483a863b116..5d397b7a5497 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -65,7 +65,7 @@ config MMC_AU1X
depends on SOC_AU1X00 && MMC
help
This selects the AMD Alchemy(R) Multimedia card interface.
- iIf you have a Alchemy platform with a MMC slot, say Y or M here.
+ If you have a Alchemy platform with a MMC slot, say Y or M here.
If unsure, say N.
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index aaf04638054e..8d84b045bc83 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -37,7 +37,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
@@ -194,7 +194,7 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
- switch(cmd->flags) {
+ switch (mmc_resp_type(cmd)) {
case MMC_RSP_R1:
mmccmd |= SD_CMD_RT_1;
break;
@@ -483,34 +483,35 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
cmd = mrq->cmd;
cmd->error = MMC_ERR_NONE;
- if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) {
-
- /* Techincally, we should be getting all 48 bits of the response
- * (SD_RESP1 + SD_RESP2), but because our response omits the CRC,
- * our data ends up being shifted 8 bits to the right. In this case,
- * that means that the OSR data starts at bit 31, so we can just
- * read RESP0 and return that
- */
-
- cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
- }
- else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
- u32 r[4];
- int i;
-
- r[0] = au_readl(host->iobase + SD_RESP3);
- r[1] = au_readl(host->iobase + SD_RESP2);
- r[2] = au_readl(host->iobase + SD_RESP1);
- r[3] = au_readl(host->iobase + SD_RESP0);
-
- /* The CRC is omitted from the response, so really we only got
- * 120 bytes, but the engine expects 128 bits, so we have to shift
- * things up
- */
-
- for(i = 0; i < 4; i++) {
- cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
- if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ u32 r[4];
+ int i;
+
+ r[0] = au_readl(host->iobase + SD_RESP3);
+ r[1] = au_readl(host->iobase + SD_RESP2);
+ r[2] = au_readl(host->iobase + SD_RESP1);
+ r[3] = au_readl(host->iobase + SD_RESP0);
+
+ /* The CRC is omitted from the response, so really
+ * we only got 120 bytes, but the engine expects
+ * 128 bits, so we have to shift things up
+ */
+
+ for(i = 0; i < 4; i++) {
+ cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
+ if (i != 3)
+ cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+ }
+ } else {
+ /* Techincally, we should be getting all 48 bits of
+ * the response (SD_RESP1 + SD_RESP2), but because
+ * our response omits the CRC, our data ends up
+ * being shifted 8 bits to the right. In this case,
+ * that means that the OSR data starts at bit 31,
+ * so we can just read RESP0 and return that
+ */
+ cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
}
}
@@ -739,7 +740,6 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs)
{
struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
- u32 status;
/* Avoid spurious interrupts */
@@ -886,7 +886,7 @@ struct mmc_host_ops au1xmmc_ops = {
.set_ios = au1xmmc_set_ios,
};
-static int au1xmmc_probe(struct device *dev)
+static int __devinit au1xmmc_probe(struct platform_device *pdev)
{
int i, ret = 0;
@@ -903,7 +903,7 @@ static int au1xmmc_probe(struct device *dev)
disable_irq(AU1100_SD_IRQ);
for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
- struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), dev);
+ struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
struct au1xmmc_host *host = 0;
if (!mmc) {
@@ -966,7 +966,7 @@ static int au1xmmc_probe(struct device *dev)
return 0;
}
-static int au1xmmc_remove(struct device *dev)
+static int __devexit au1xmmc_remove(struct platform_device *pdev)
{
int i;
@@ -996,23 +996,24 @@ static int au1xmmc_remove(struct device *dev)
return 0;
}
-static struct device_driver au1xmmc_driver = {
- .name = DRIVER_NAME,
- .bus = &platform_bus_type,
+static struct platform_driver au1xmmc_driver = {
.probe = au1xmmc_probe,
.remove = au1xmmc_remove,
.suspend = NULL,
- .resume = NULL
+ .resume = NULL,
+ .driver = {
+ .name = DRIVER_NAME,
+ },
};
static int __init au1xmmc_init(void)
{
- return driver_register(&au1xmmc_driver);
+ return platform_driver_register(&au1xmmc_driver);
}
static void __exit au1xmmc_exit(void)
{
- driver_unregister(&au1xmmc_driver);
+ platform_driver_unregister(&au1xmmc_driver);
}
module_init(au1xmmc_init);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index bfca5c176e88..1888060c5e0c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -211,7 +211,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
appcmd.opcode = MMC_APP_CMD;
appcmd.arg = rca << 16;
- appcmd.flags = MMC_RSP_R1;
+ appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
appcmd.retries = 0;
memset(appcmd.resp, 0, sizeof(appcmd.resp));
appcmd.data = NULL;
@@ -331,7 +331,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
cmd.opcode = MMC_SELECT_CARD;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
@@ -358,7 +358,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
struct mmc_command cmd;
cmd.opcode = SD_APP_SET_BUS_WIDTH;
cmd.arg = SD_BUS_WIDTH_4;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
CMD_RETRIES);
@@ -386,7 +386,7 @@ static void mmc_deselect_cards(struct mmc_host *host)
cmd.opcode = MMC_SELECT_CARD;
cmd.arg = 0;
- cmd.flags = MMC_RSP_NONE;
+ cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
mmc_wait_for_cmd(host, &cmd, 0);
}
@@ -677,7 +677,7 @@ static void mmc_idle_cards(struct mmc_host *host)
cmd.opcode = MMC_GO_IDLE_STATE;
cmd.arg = 0;
- cmd.flags = MMC_RSP_NONE;
+ cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
mmc_wait_for_cmd(host, &cmd, 0);
@@ -738,7 +738,7 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.opcode = MMC_SEND_OP_COND;
cmd.arg = ocr;
- cmd.flags = MMC_RSP_R3;
+ cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
err = mmc_wait_for_cmd(host, &cmd, 0);
@@ -766,7 +766,7 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.opcode = SD_APP_OP_COND;
cmd.arg = ocr;
- cmd.flags = MMC_RSP_R3;
+ cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
@@ -805,7 +805,7 @@ static void mmc_discover_cards(struct mmc_host *host)
cmd.opcode = MMC_ALL_SEND_CID;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R2;
+ cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err == MMC_ERR_TIMEOUT) {
@@ -835,7 +835,7 @@ static void mmc_discover_cards(struct mmc_host *host)
cmd.opcode = SD_SEND_RELATIVE_ADDR;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R6;
+ cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
@@ -856,7 +856,7 @@ static void mmc_discover_cards(struct mmc_host *host)
} else {
cmd.opcode = MMC_SET_RELATIVE_ADDR;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
@@ -878,7 +878,7 @@ static void mmc_read_csds(struct mmc_host *host)
cmd.opcode = MMC_SEND_CSD;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R2;
+ cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE) {
@@ -920,7 +920,7 @@ static void mmc_read_scrs(struct mmc_host *host)
cmd.opcode = MMC_APP_CMD;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, 0);
if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
@@ -932,7 +932,7 @@ static void mmc_read_scrs(struct mmc_host *host)
cmd.opcode = SD_APP_SEND_SCR;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
memset(&data, 0, sizeof(struct mmc_data));
@@ -1003,7 +1003,7 @@ static void mmc_check_cards(struct mmc_host *host)
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err == MMC_ERR_NONE)
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 5b014c370e80..8eb2a2ede64b 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -171,14 +171,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.mrq.data = &brq.data;
brq.cmd.arg = req->sector << 9;
- brq.cmd.flags = MMC_RSP_R1;
+ brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
brq.data.timeout_ns = card->csd.tacc_ns * 10;
brq.data.timeout_clks = card->csd.tacc_clks * 10;
brq.data.blksz_bits = md->block_bits;
brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
brq.stop.opcode = MMC_STOP_TRANSMISSION;
brq.stop.arg = 0;
- brq.stop.flags = MMC_RSP_R1B;
+ brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
if (rq_data_dir(req) == READ) {
brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
@@ -223,7 +223,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
if (err) {
printk(KERN_ERR "%s: error %d requesting status\n",
@@ -430,7 +430,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
mmc_card_claim_host(card);
cmd.opcode = MMC_SET_BLOCKLEN;
cmd.arg = 1 << md->block_bits;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
mmc_card_release_host(card);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 634ef53e85a5..9fef29d978b5 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -97,6 +97,13 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
if (data->flags & MMC_DATA_READ) {
datactrl |= MCI_DPSM_DIRECTION;
irqmask = MCI_RXFIFOHALFFULLMASK;
+
+ /*
+ * If we have less than a FIFOSIZE of bytes to transfer,
+ * trigger a PIO interrupt as soon as any data is available.
+ */
+ if (host->size < MCI_FIFOSIZE)
+ irqmask |= MCI_RXDATAAVLBLMASK;
} else {
/*
* We don't actually need to include "FIFO empty" here
@@ -124,15 +131,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
}
c |= cmd->opcode | MCI_CPSM_ENABLE;
- switch (cmd->flags & MMC_RSP_MASK) {
- case MMC_RSP_NONE:
- default:
- break;
- case MMC_RSP_LONG:
- c |= MCI_CPSM_LONGRSP;
- case MMC_RSP_SHORT:
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136)
+ c |= MCI_CPSM_LONGRSP;
c |= MCI_CPSM_RESPONSE;
- break;
}
if (/*interrupt*/0)
c |= MCI_CPSM_INTERRUPT;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index ee8f8a0420d1..285d7d068097 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -178,14 +178,15 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
if (cmd->flags & MMC_RSP_BUSY)
cmdat |= CMDAT_BUSY;
- switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) {
- case MMC_RSP_SHORT | MMC_RSP_CRC:
+#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
+ switch (RSP_TYPE(mmc_resp_type(cmd))) {
+ case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */
cmdat |= CMDAT_RESP_SHORT;
break;
- case MMC_RSP_SHORT:
+ case RSP_TYPE(MMC_RSP_R3):
cmdat |= CMDAT_RESP_R3;
break;
- case MMC_RSP_LONG | MMC_RSP_CRC:
+ case RSP_TYPE(MMC_RSP_R2):
cmdat |= CMDAT_RESP_R2;
break;
default:
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index f25757625361..3be397d436fa 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -459,7 +459,7 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
/*
* Do we expect a reply?
*/
- if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
+ if (cmd->flags & MMC_RSP_PRESENT) {
/*
* Read back status.
*/
@@ -476,10 +476,10 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
cmd->error = MMC_ERR_BADCRC;
/* All ok */
else {
- if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT)
- wbsd_get_short_reply(host, cmd);
- else
+ if (cmd->flags & MMC_RSP_136)
wbsd_get_long_reply(host, cmd);
+ else
+ wbsd_get_short_reply(host, cmd);
}
}
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index effa0d7a73ac..205bb7083335 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -301,7 +301,7 @@ config MTD_JEDEC
config MTD_XIP
bool "XIP aware MTD support"
- depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARM
+ depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
default y if XIP_KERNEL
help
This allows MTD support to work with flash memory which is also
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 69c04945591f..1c074d63ff3a 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -408,6 +408,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
cfi->chips[i].ref_point_counter = 0;
+ init_waitqueue_head(&(cfi->chips[i].wq));
}
map->fldrv = &cfi_intelext_chipdrv;
@@ -1019,8 +1020,8 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
INVALIDATE_CACHED_RANGE(map, from, size)
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
- UDELAY(map, chip, adr, usec)
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \
+ UDELAY(map, chip, cmd_adr, usec)
/*
* Extra notes:
@@ -1052,7 +1053,7 @@ do { \
spin_lock(chip->mutex); \
} while (0)
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \
do { \
spin_unlock(chip->mutex); \
INVALIDATE_CACHED_RANGE(map, adr, len); \
@@ -1284,7 +1285,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
map_write(map, datum, adr);
chip->state = mode;
- INVALIDATE_CACHE_UDELAY(map, chip,
+ INVALIDATE_CACHE_UDELAY(map, chip, adr,
adr, map_bankwidth(map),
chip->word_write_time);
@@ -1572,8 +1573,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
map_write(map, CMD(0xd0), cmd_adr);
chip->state = FL_WRITING;
- INVALIDATE_CACHE_UDELAY(map, chip,
- cmd_adr, len,
+ INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr,
+ adr, len,
chip->buffer_write_time);
timeo = jiffies + (HZ/2);
@@ -1744,7 +1745,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->state = FL_ERASING;
chip->erase_suspended = 0;
- INVALIDATE_CACHE_UDELAY(map, chip,
+ INVALIDATE_CACHE_UDELAY(map, chip, adr,
adr, len,
chip->erase_time*1000/2);
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 155737e7483f..a19480d07888 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -178,7 +178,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
* we're at a block boundary and need to erase the whole block.
*/
pageaddr = instr->addr / priv->page_size;
- do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize;
+ do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize;
pageaddr = pageaddr << priv->page_offset;
command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE;
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 7b7ca5ab5ae4..8815c8dbef2d 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -1,5 +1,5 @@
/*
- * $Id: redboot.c,v 1.18 2005/11/07 11:14:21 gleixner Exp $
+ * $Id: redboot.c,v 1.19 2005/12/01 10:03:51 dwmw2 Exp $
*
* Parse RedBoot-style Flash Image System (FIS) tables and
* produce a Linux partition array to match.
@@ -89,8 +89,32 @@ static int parse_redboot_partitions(struct mtd_info *master,
i = numslots;
break;
}
- if (!memcmp(buf[i].name, "FIS directory", 14))
+ if (!memcmp(buf[i].name, "FIS directory", 14)) {
+ /* This is apparently the FIS directory entry for the
+ * FIS directory itself. The FIS directory size is
+ * one erase block; if the buf[i].size field is
+ * swab32(erasesize) then we know we are looking at
+ * a byte swapped FIS directory - swap all the entries!
+ * (NOTE: this is 'size' not 'data_length'; size is
+ * the full size of the entry.)
+ */
+ if (swab32(buf[i].size) == master->erasesize) {
+ int j;
+ for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) {
+ /* The unsigned long fields were written with the
+ * wrong byte sex, name and pad have no byte sex.
+ */
+ swab32s(&buf[j].flash_base);
+ swab32s(&buf[j].mem_base);
+ swab32s(&buf[j].size);
+ swab32s(&buf[j].entry_point);
+ swab32s(&buf[j].data_length);
+ swab32s(&buf[j].desc_cksum);
+ swab32s(&buf[j].file_cksum);
+ }
+ }
break;
+ }
}
if (i == numslots) {
/* Didn't find it */
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index 824e430486c2..830528dce0ca 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -1574,6 +1574,7 @@ MODULE_LICENSE("GPL");
static int __init el3_init_module(void)
{
+ int ret = 0;
el3_cards = 0;
if (debug >= 0)
@@ -1589,14 +1590,16 @@ static int __init el3_init_module(void)
}
#ifdef CONFIG_EISA
- if (eisa_driver_register (&el3_eisa_driver) < 0) {
- eisa_driver_unregister (&el3_eisa_driver);
- }
+ ret = eisa_driver_register(&el3_eisa_driver);
#endif
#ifdef CONFIG_MCA
- mca_register_driver(&el3_mca_driver);
+ {
+ int err = mca_register_driver(&el3_mca_driver);
+ if (ret == 0)
+ ret = err;
+ }
#endif
- return 0;
+ return ret;
}
static void __exit el3_cleanup_module(void)
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index f822cd3025ff..dd410496aadb 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1118,13 +1118,18 @@ err_out:
return -ENOMEM;
}
+static void cp_init_rings_index (struct cp_private *cp)
+{
+ cp->rx_tail = 0;
+ cp->tx_head = cp->tx_tail = 0;
+}
+
static int cp_init_rings (struct cp_private *cp)
{
memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
cp->tx_ring[CP_TX_RING_SIZE - 1].opts1 = cpu_to_le32(RingEnd);
- cp->rx_tail = 0;
- cp->tx_head = cp->tx_tail = 0;
+ cp_init_rings_index(cp);
return cp_refill_rx (cp);
}
@@ -1886,30 +1891,30 @@ static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
spin_unlock_irqrestore (&cp->lock, flags);
- if (cp->pdev && cp->wol_enabled) {
- pci_save_state (cp->pdev);
- cp_set_d3_state (cp);
- }
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), cp->wol_enabled);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
static int cp_resume (struct pci_dev *pdev)
{
- struct net_device *dev;
- struct cp_private *cp;
+ struct net_device *dev = pci_get_drvdata (pdev);
+ struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
- dev = pci_get_drvdata (pdev);
- cp = netdev_priv(dev);
+ if (!netif_running(dev))
+ return 0;
netif_device_attach (dev);
-
- if (cp->pdev && cp->wol_enabled) {
- pci_set_power_state (cp->pdev, PCI_D0);
- pci_restore_state (cp->pdev);
- }
-
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+
+ /* FIXME: sh*t may happen if the Rx ring buffer is depleted */
+ cp_init_rings_index (cp);
cp_init_hw (cp);
netif_start_queue (dev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index adfba44dac5a..2beac55b57d6 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -586,6 +586,7 @@ struct rtl8139_private {
dma_addr_t tx_bufs_dma;
signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */
+ unsigned int watchdog_fired : 1;
unsigned int default_port : 4; /* Last dev->if_port value. */
unsigned int have_thread : 1;
spinlock_t lock;
@@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev);
static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
static void rtl8139_thread (void *_data);
+static void rtl8139_tx_timeout_task(void *_data);
static struct ethtool_ops rtl8139_ethtool_ops;
/* write MMIO register, with flush */
@@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data)
{
struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev);
- unsigned long thr_delay;
+ unsigned long thr_delay = next_tick;
- if (rtnl_shlock_nowait() == 0) {
+ if (tp->watchdog_fired) {
+ tp->watchdog_fired = 0;
+ rtl8139_tx_timeout_task(_data);
+ } else if (rtnl_shlock_nowait() == 0) {
rtl8139_thread_iter (dev, tp, tp->mmio_addr);
rtnl_unlock ();
-
- thr_delay = next_tick;
} else {
/* unlikely race. mitigate with fast poll. */
thr_delay = HZ / 2;
@@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp)
if (tp->have_thread) {
cancel_rearming_delayed_work(&tp->thread);
tp->have_thread = 0;
- }
+ } else
+ flush_scheduled_work();
}
static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
@@ -1642,14 +1646,13 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
}
-
-static void rtl8139_tx_timeout (struct net_device *dev)
+static void rtl8139_tx_timeout_task (void *_data)
{
+ struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
int i;
u8 tmp8;
- unsigned long flags;
printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
"media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
@@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev)
if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, CmdRxEnb);
- spin_lock(&tp->rx_lock);
+ spin_lock_bh(&tp->rx_lock);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */
- spin_lock_irqsave (&tp->lock, flags);
+ spin_lock_irq(&tp->lock);
rtl8139_tx_clear (tp);
- spin_unlock_irqrestore (&tp->lock, flags);
+ spin_unlock_irq(&tp->lock);
/* ...and finally, reset everything */
if (netif_running(dev)) {
rtl8139_hw_start (dev);
netif_wake_queue (dev);
}
- spin_unlock(&tp->rx_lock);
+ spin_unlock_bh(&tp->rx_lock);
}
+static void rtl8139_tx_timeout (struct net_device *dev)
+{
+ struct rtl8139_private *tp = netdev_priv(dev);
+
+ if (!tp->have_thread) {
+ INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
+ schedule_delayed_work(&tp->thread, next_tick);
+ } else
+ tp->watchdog_fired = 1;
+
+}
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6a6a08441804..aa633fa95e64 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -4,9 +4,9 @@
#
menu "Network device support"
+ depends on NET
config NETDEVICES
- depends on NET
default y if UML
bool "Network device support"
---help---
@@ -24,9 +24,6 @@ config NETDEVICES
If unsure, say Y.
-# All the following symbols are dependent on NETDEVICES - do not repeat
-# that for each of the symbols.
-if NETDEVICES
config IFB
tristate "Intermediate Functional Block support"
@@ -1090,7 +1087,8 @@ config NE2000
without a specific driver are compatible with NE2000.
If you have a PCI NE2000 card however, say N here and Y to "PCI
- NE2000 support", above. If you have a NE2000 card and are running on
+ NE2000 and clone support" under "EISA, VLB, PCI and on board
+ controllers" below. If you have a NE2000 card and are running on
an MCA system (a bus system used on some IBM PS/2 computers and
laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
below.
@@ -2023,8 +2021,8 @@ config SIS190
will be called sis190. This is recommended.
config SKGE
- tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ tristate "New SysKonnect GigaEthernet support"
+ depends on PCI
select CRC32
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
@@ -2085,7 +2083,6 @@ config SK98LIN
- Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
- Allied Telesyn AT-2971T Gigabit Ethernet Adapter
- Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
- - DGE-530T Gigabit Ethernet Adapter
- EG1032 v2 Instant Gigabit Network Adapter
- EG1064 v2 Instant Gigabit Network Adapter
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
@@ -2718,8 +2715,6 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
-endif #NETDEVICES
-
config NETPOLL
def_bool NETCONSOLE
diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h
index c68ba9c2ef46..fd2750b269c8 100644
--- a/drivers/net/appletalk/cops.h
+++ b/drivers/net/appletalk/cops.h
@@ -51,7 +51,7 @@
struct ltfirmware
{
unsigned int length;
- unsigned char * data;
+ const unsigned char *data;
};
#define DAYNA 1
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 4ff006c37626..bcf9f17daf0d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1145,7 +1145,8 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
}
#define BOND_INTERSECT_FEATURES \
- (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+ (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
+ NETIF_F_TSO|NETIF_F_UFO)
/*
* Compute the common dev->feature set available to all slaves. Some
@@ -1168,6 +1169,16 @@ static int bond_compute_features(struct bonding *bond)
NETIF_F_HW_CSUM)))
features &= ~NETIF_F_SG;
+ /*
+ * features will include NETIF_F_TSO (NETIF_F_UFO) iff all
+ * slave devices support NETIF_F_TSO (NETIF_F_UFO), which
+ * implies that all slaves also support scatter-gather
+ * (NETIF_F_SG), which implies that features also includes
+ * NETIF_F_SG. So no need to check whether we have an
+ * illegal combination of NETIF_F_{TSO,UFO} and
+ * !NETIF_F_SG
+ */
+
features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
bond_dev->features = features;
@@ -1570,6 +1581,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
printk(KERN_INFO DRV_NAME
": %s: %s not enslaved\n",
bond_dev->name, slave_dev->name);
+ write_unlock_bh(&bond->lock);
return -EINVAL;
}
@@ -4080,6 +4092,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
static struct ethtool_ops bond_ethtool_ops = {
.get_tx_csum = ethtool_op_get_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .get_ufo = ethtool_op_get_ufo,
.get_sg = ethtool_op_get_sg,
.get_drvinfo = bond_ethtool_get_drvinfo,
};
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 32d13da43a0b..041bcc583557 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -260,7 +260,7 @@ static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer,
char *ifname;
int i, res, found, ret = count;
struct slave *slave;
- struct net_device *dev = 0;
+ struct net_device *dev = NULL;
struct bonding *bond = to_bond(cd);
/* Quick sanity check -- is the bond interface up? */
@@ -995,7 +995,7 @@ static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, s
printk(KERN_INFO DRV_NAME
": %s: Setting primary slave to None.\n",
bond->dev->name);
- bond->primary_slave = 0;
+ bond->primary_slave = NULL;
bond_select_active_slave(bond);
} else {
printk(KERN_INFO DRV_NAME
@@ -1123,7 +1123,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b
printk(KERN_INFO DRV_NAME
": %s: Setting active slave to None.\n",
bond->dev->name);
- bond->primary_slave = 0;
+ bond->primary_slave = NULL;
bond_select_active_slave(bond);
} else {
printk(KERN_INFO DRV_NAME
diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c
index 230642571c92..e824acaf188a 100644
--- a/drivers/net/chelsio/espi.c
+++ b/drivers/net/chelsio/espi.c
@@ -296,9 +296,7 @@ void t1_espi_destroy(struct peespi *espi)
struct peespi *t1_espi_create(adapter_t *adapter)
{
- struct peespi *espi = kmalloc(sizeof(*espi), GFP_KERNEL);
-
- memset(espi, 0, sizeof(*espi));
+ struct peespi *espi = kzalloc(sizeof(*espi), GFP_KERNEL);
if (espi)
espi->adapter = adapter;
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 2c5b849b7ba4..30ff8ea1a402 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1021,7 +1021,7 @@ static void restart_tx_queues(struct sge *sge)
if (test_and_clear_bit(nd->if_port,
&sge->stopped_tx_queues) &&
netif_running(nd)) {
- sge->stats.cmdQ_restarted[3]++;
+ sge->stats.cmdQ_restarted[2]++;
netif_wake_queue(nd);
}
}
@@ -1350,7 +1350,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
if (unlikely(credits < count)) {
netif_stop_queue(dev);
set_bit(dev->if_port, &sge->stopped_tx_queues);
- sge->stats.cmdQ_full[3]++;
+ sge->stats.cmdQ_full[2]++;
spin_unlock(&q->lock);
if (!netif_queue_stopped(dev))
CH_ERR("%s: Tx ring full while queue awake!\n",
@@ -1358,7 +1358,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
return NETDEV_TX_BUSY;
}
if (unlikely(credits - count < q->stop_thres)) {
- sge->stats.cmdQ_full[3]++;
+ sge->stats.cmdQ_full[2]++;
netif_stop_queue(dev);
set_bit(dev->if_port, &sge->stopped_tx_queues);
}
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index 0069f5fa973a..22fc5b869a60 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -1012,7 +1012,7 @@ static int __init read_eeprom(struct net_device *dev)
#ifdef MODULE
static struct net_device *de620_dev;
-int init_module(void)
+int __init init_module(void)
{
de620_dev = de620_probe(-1);
if (IS_ERR(de620_dev))
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 430c628279b3..fb9dae302dcc 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -50,8 +50,8 @@
*/
#define DRV_NAME "D-Link DL2000-based linux driver"
-#define DRV_VERSION "v1.17a"
-#define DRV_RELDATE "2002/10/04"
+#define DRV_VERSION "v1.17b"
+#define DRV_RELDATE "2006/03/10"
#include "dl2k.h"
static char version[] __devinitdata =
@@ -765,7 +765,7 @@ rio_free_tx (struct net_device *dev, int irq)
break;
skb = np->tx_skbuff[entry];
pci_unmap_single (np->pdev,
- np->tx_ring[entry].fraginfo,
+ np->tx_ring[entry].fraginfo & 0xffffffffffff,
skb->len, PCI_DMA_TODEVICE);
if (irq)
dev_kfree_skb_irq (skb);
@@ -892,14 +892,16 @@ receive_packet (struct net_device *dev)
/* Small skbuffs for short packets */
if (pkt_len > copy_thresh) {
- pci_unmap_single (np->pdev, desc->fraginfo,
+ pci_unmap_single (np->pdev,
+ desc->fraginfo & 0xffffffffffff,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb_put (skb = np->rx_skbuff[entry], pkt_len);
np->rx_skbuff[entry] = NULL;
} else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) {
pci_dma_sync_single_for_cpu(np->pdev,
- desc->fraginfo,
+ desc->fraginfo &
+ 0xffffffffffff,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb->dev = dev;
@@ -910,7 +912,8 @@ receive_packet (struct net_device *dev)
pkt_len, 0);
skb_put (skb, pkt_len);
pci_dma_sync_single_for_device(np->pdev,
- desc->fraginfo,
+ desc->fraginfo &
+ 0xffffffffffff,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
}
@@ -1796,8 +1799,9 @@ rio_close (struct net_device *dev)
np->rx_ring[i].fraginfo = 0;
skb = np->rx_skbuff[i];
if (skb) {
- pci_unmap_single (np->pdev, np->rx_ring[i].fraginfo,
- skb->len, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(np->pdev,
+ np->rx_ring[i].fraginfo & 0xffffffffffff,
+ skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb (skb);
np->rx_skbuff[i] = NULL;
}
@@ -1805,8 +1809,9 @@ rio_close (struct net_device *dev)
for (i = 0; i < TX_RING_SIZE; i++) {
skb = np->tx_skbuff[i];
if (skb) {
- pci_unmap_single (np->pdev, np->tx_ring[i].fraginfo,
- skb->len, PCI_DMA_TODEVICE);
+ pci_unmap_single(np->pdev,
+ np->tx_ring[i].fraginfo & 0xffffffffffff,
+ skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb (skb);
np->tx_skbuff[i] = NULL;
}
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index bf1fd2b98bf8..f57a85feda3d 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2154,6 +2154,9 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
msleep(10);
+ pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
+ RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
skb->data, ETH_DATA_LEN))
err = -EAGAIN;
@@ -2161,8 +2164,8 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
err_loopback_none:
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
nic->loopback = lb_none;
- e100_hw_init(nic);
e100_clean_cbs(nic);
+ e100_hw_reset(nic);
err_clean_rx:
e100_rx_clean_list(nic);
return err;
@@ -2752,8 +2755,6 @@ static int e100_resume(struct pci_dev *pdev)
retval = pci_enable_wake(pdev, 0, 0);
if (retval)
DPRINTK(PROBE,ERR, "Error clearing wake events\n");
- if(e100_hw_init(nic))
- DPRINTK(HW, ERR, "e100_hw_init failed\n");
netif_device_attach(netdev);
if(netif_running(netdev))
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 27c77306193b..99baf0e099fc 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -225,9 +225,6 @@ struct e1000_rx_ring {
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *rx_skb_top;
- struct sk_buff *rx_skb_prev;
-
/* cpu for rx queue */
int cpu;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 31e332935e5a..84dcca3776ee 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -103,7 +103,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k4"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -1635,8 +1635,6 @@ setup_rx_desc_die:
rxdr->next_to_clean = 0;
rxdr->next_to_use = 0;
- rxdr->rx_skb_top = NULL;
- rxdr->rx_skb_prev = NULL;
return 0;
}
@@ -1713,8 +1711,23 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= adapter->rx_buffer_len << 0x11;
} else {
rctl &= ~E1000_RCTL_SZ_4096;
- rctl &= ~E1000_RCTL_BSEX;
- rctl |= E1000_RCTL_SZ_2048;
+ rctl |= E1000_RCTL_BSEX;
+ switch (adapter->rx_buffer_len) {
+ case E1000_RXBUFFER_2048:
+ default:
+ rctl |= E1000_RCTL_SZ_2048;
+ rctl &= ~E1000_RCTL_BSEX;
+ break;
+ case E1000_RXBUFFER_4096:
+ rctl |= E1000_RCTL_SZ_4096;
+ break;
+ case E1000_RXBUFFER_8192:
+ rctl |= E1000_RCTL_SZ_8192;
+ break;
+ case E1000_RXBUFFER_16384:
+ rctl |= E1000_RCTL_SZ_16384;
+ break;
+ }
}
#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
@@ -2107,16 +2120,6 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
}
}
- /* there also may be some cached data in our adapter */
- if (rx_ring->rx_skb_top) {
- dev_kfree_skb(rx_ring->rx_skb_top);
-
- /* rx_skb_prev will be wiped out by rx_skb_top */
- rx_ring->rx_skb_top = NULL;
- rx_ring->rx_skb_prev = NULL;
- }
-
-
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
size = sizeof(struct e1000_ps_page) * rx_ring->count;
@@ -2914,7 +2917,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (!__pskb_pull_tail(skb, pull_size)) {
printk(KERN_ERR "__pskb_pull_tail failed.\n");
dev_kfree_skb_any(skb);
- return -EFAULT;
+ return NETDEV_TX_OK;
}
len = skb->len - skb->data_len;
}
@@ -3106,24 +3109,27 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
break;
}
- /* since the driver code now supports splitting a packet across
- * multiple descriptors, most of the fifo related limitations on
- * jumbo frame traffic have gone away.
- * simply use 2k descriptors for everything.
- *
- * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
- * means we reserve 2 more, this pushes us to allocate from the next
- * larger slab size
- * i.e. RXBUFFER_2048 --> size-4096 slab */
-
- /* recent hardware supports 1KB granularity */
+
if (adapter->hw.mac_type > e1000_82547_rev_2) {
- adapter->rx_buffer_len =
- ((max_frame < E1000_RXBUFFER_2048) ?
- max_frame : E1000_RXBUFFER_2048);
+ adapter->rx_buffer_len = max_frame;
E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
- } else
- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ } else {
+ if(unlikely((adapter->hw.mac_type < e1000_82543) &&
+ (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+ "on 82542\n");
+ return -EINVAL;
+ } else {
+ if(max_frame <= E1000_RXBUFFER_2048)
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ else if(max_frame <= E1000_RXBUFFER_4096)
+ adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+ else if(max_frame <= E1000_RXBUFFER_8192)
+ adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+ else if(max_frame <= E1000_RXBUFFER_16384)
+ adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+ }
+ }
netdev->mtu = new_mtu;
@@ -3620,7 +3626,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
uint8_t last_byte;
unsigned int i;
int cleaned_count = 0;
- boolean_t cleaned = FALSE, multi_descriptor = FALSE;
+ boolean_t cleaned = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
@@ -3652,43 +3658,12 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
length = le16_to_cpu(rx_desc->length);
- skb_put(skb, length);
-
- if (!(status & E1000_RXD_STAT_EOP)) {
- if (!rx_ring->rx_skb_top) {
- rx_ring->rx_skb_top = skb;
- rx_ring->rx_skb_top->len = length;
- rx_ring->rx_skb_prev = skb;
- } else {
- if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) {
- rx_ring->rx_skb_prev->next = skb;
- skb->prev = rx_ring->rx_skb_prev;
- } else {
- skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb;
- }
- rx_ring->rx_skb_prev = skb;
- rx_ring->rx_skb_top->data_len += length;
- }
+ if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
+ /* All receives must fit into a single buffer */
+ E1000_DBG("%s: Receive packet consumed multiple"
+ " buffers\n", netdev->name);
+ dev_kfree_skb_irq(skb);
goto next_desc;
- } else {
- if (rx_ring->rx_skb_top) {
- if (skb_shinfo(rx_ring->rx_skb_top)
- ->frag_list) {
- rx_ring->rx_skb_prev->next = skb;
- skb->prev = rx_ring->rx_skb_prev;
- } else
- skb_shinfo(rx_ring->rx_skb_top)
- ->frag_list = skb;
-
- rx_ring->rx_skb_top->data_len += length;
- rx_ring->rx_skb_top->len +=
- rx_ring->rx_skb_top->data_len;
-
- skb = rx_ring->rx_skb_top;
- multi_descriptor = TRUE;
- rx_ring->rx_skb_top = NULL;
- rx_ring->rx_skb_prev = NULL;
- }
}
if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
@@ -3712,10 +3687,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
* performance for small packets with large amounts
* of reassembly being done in the stack */
#define E1000_CB_LENGTH 256
- if ((length < E1000_CB_LENGTH) &&
- !rx_ring->rx_skb_top &&
- /* or maybe (status & E1000_RXD_STAT_EOP) && */
- !multi_descriptor) {
+ if (length < E1000_CB_LENGTH) {
struct sk_buff *new_skb =
dev_alloc_skb(length + NET_IP_ALIGN);
if (new_skb) {
@@ -3729,7 +3701,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
skb = new_skb;
skb_put(skb, length);
}
- }
+ } else
+ skb_put(skb, length);
/* end copybreak code */
@@ -3737,7 +3710,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
e1000_rx_checksum(adapter,
(uint32_t)(status) |
((uint32_t)(rx_desc->errors) << 24),
- rx_desc->csum, skb);
+ le16_to_cpu(rx_desc->csum), skb);
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
@@ -3881,11 +3854,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
e1000_rx_checksum(adapter, staterr,
- rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+ le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
skb->protocol = eth_type_trans(skb, netdev);
if (likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP))
+ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
adapter->rx_hdr_split++;
#ifdef CONFIG_E1000_NAPI
if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
@@ -3911,7 +3884,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
#endif
next_desc:
- rx_desc->wb.middle.status_error &= ~0xFF;
+ rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
buffer_info->skb = NULL;
/* return some buffers to hardware, one at a time is too slow */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0c18dbd67d3b..0e8e3fcde9ff 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -199,8 +199,7 @@ static int gfar_probe(struct platform_device *pdev)
/* get a pointer to the register memory */
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->regs = (struct gfar *)
- ioremap(r->start, sizeof (struct gfar));
+ priv->regs = ioremap(r->start, sizeof (struct gfar));
if (NULL == priv->regs) {
err = -ENOMEM;
@@ -369,7 +368,7 @@ static int gfar_probe(struct platform_device *pdev)
return 0;
register_fail:
- iounmap((void *) priv->regs);
+ iounmap(priv->regs);
regs_fail:
free_netdev(dev);
return err;
@@ -382,7 +381,7 @@ static int gfar_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
- iounmap((void *) priv->regs);
+ iounmap(priv->regs);
free_netdev(dev);
return 0;
@@ -454,8 +453,7 @@ static void init_registers(struct net_device *dev)
/* Zero out the rmon mib registers if it has them */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- memset((void *) &(priv->regs->rmon), 0,
- sizeof (struct rmon_mib));
+ memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib));
/* Mask off the CAM interrupts */
gfar_write(&priv->regs->rmon.cam1, 0xffffffff);
@@ -477,7 +475,7 @@ static void init_registers(struct net_device *dev)
void gfar_halt(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
u32 tempval;
/* Mask all interrupts */
@@ -507,7 +505,7 @@ void gfar_halt(struct net_device *dev)
void stop_gfar(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
unsigned long flags;
phy_stop(priv->phydev);
@@ -590,7 +588,7 @@ static void free_skb_resources(struct gfar_private *priv)
void gfar_start(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
u32 tempval;
/* Enable Rx and Tx in MACCFG1 */
@@ -624,7 +622,7 @@ int startup_gfar(struct net_device *dev)
unsigned long vaddr;
int i;
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
int err = 0;
u32 rctrl = 0;
u32 attrs = 0;
@@ -1622,7 +1620,7 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void adjust_link(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
unsigned long flags;
struct phy_device *phydev = priv->phydev;
int new_state = 0;
@@ -1703,7 +1701,7 @@ static void gfar_set_multi(struct net_device *dev)
{
struct dev_mc_list *mc_ptr;
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
u32 tempval;
if(dev->flags & IFF_PROMISC) {
@@ -1842,7 +1840,7 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
int idx;
char tmpbuf[MAC_ADDR_LEN];
u32 tempval;
- u32 *macptr = &priv->regs->macstnaddr1;
+ u32 __iomem *macptr = &priv->regs->macstnaddr1;
macptr += num*2;
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index cb9d66ac3ab9..d37d5401be6e 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -682,8 +682,8 @@ struct gfar_private {
struct rxbd8 *cur_rx; /* Next free rx ring entry */
struct txbd8 *cur_tx; /* Next free ring entry */
struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
- struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
- u32 *hash_regs[16];
+ struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */
+ u32 __iomem *hash_regs[16];
int hash_width;
struct net_device_stats stats; /* linux network statistics */
struct gfar_extra_stats extra_stats;
@@ -718,14 +718,14 @@ struct gfar_private {
uint32_t msg_enable;
};
-static inline u32 gfar_read(volatile unsigned *addr)
+static inline u32 gfar_read(volatile unsigned __iomem *addr)
{
u32 val;
val = in_be32(addr);
return val;
}
-static inline void gfar_write(volatile unsigned *addr, u32 val)
+static inline void gfar_write(volatile unsigned __iomem *addr, u32 val)
{
out_be32(addr, val);
}
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 765e810620fe..5de7b2e259dc 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -144,11 +144,11 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 *extra = (u64 *) & priv->extra_stats;
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- u32 *rmon = (u32 *) & priv->regs->rmon;
+ u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon;
struct gfar_stats *stats = (struct gfar_stats *) buf;
for (i = 0; i < GFAR_RMON_LEN; i++)
- stats->rmon[i] = (u64) (rmon[i]);
+ stats->rmon[i] = (u64) gfar_read(&rmon[i]);
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
stats->extra[i] = extra[i];
@@ -221,11 +221,11 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi
{
int i;
struct gfar_private *priv = netdev_priv(dev);
- u32 *theregs = (u32 *) priv->regs;
+ u32 __iomem *theregs = (u32 __iomem *) priv->regs;
u32 *buf = (u32 *) regbuf;
for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
- buf[i] = theregs[i];
+ buf[i] = gfar_read(&theregs[i]);
}
/* Convert microseconds to ethernet clock ticks, which changes
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 74e52fcbf806..c6b725529af5 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -50,7 +50,7 @@
* All PHY configuration is done through the TSEC1 MIIM regs */
int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
{
- struct gfar_mii *regs = bus->priv;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
/* Set the PHY address and the register address we want to write */
gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@@ -70,7 +70,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
* configuration has to be done through the TSEC1 MIIM regs */
int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
- struct gfar_mii *regs = bus->priv;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
u16 value;
/* Set the PHY address and the register address we want to read */
@@ -94,7 +94,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
/* Reset the MIIM registers, and wait for the bus to free */
int gfar_mdio_reset(struct mii_bus *bus)
{
- struct gfar_mii *regs = bus->priv;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
unsigned int timeout = PHY_INIT_TIMEOUT;
spin_lock_bh(&bus->mdio_lock);
@@ -126,7 +126,7 @@ int gfar_mdio_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct gianfar_mdio_data *pdata;
- struct gfar_mii *regs;
+ struct gfar_mii __iomem *regs;
struct mii_bus *new_bus;
struct resource *r;
int err = 0;
@@ -155,15 +155,14 @@ int gfar_mdio_probe(struct device *dev)
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* Set the PHY base address */
- regs = (struct gfar_mii *) ioremap(r->start,
- sizeof (struct gfar_mii));
+ regs = ioremap(r->start, sizeof (struct gfar_mii));
if (NULL == regs) {
err = -ENOMEM;
goto reg_map_fail;
}
- new_bus->priv = regs;
+ new_bus->priv = (void __force *)regs;
new_bus->irq = pdata->irq;
@@ -181,7 +180,7 @@ int gfar_mdio_probe(struct device *dev)
return 0;
bus_register_fail:
- iounmap((void *) regs);
+ iounmap(regs);
reg_map_fail:
kfree(new_bus);
@@ -197,7 +196,7 @@ int gfar_mdio_remove(struct device *dev)
dev_set_drvdata(dev, NULL);
- iounmap((void *) (&bus->priv));
+ iounmap((void __iomem *)bus->priv);
bus->priv = NULL;
kfree(bus);
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 3b1bef1ee215..77411a00d1ee 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -86,7 +86,6 @@
#include <linux/bitops.h>
#include <linux/jiffies.h>
-#include <asm/bug.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 1b699259b4ec..31fb2d75dc44 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -57,7 +57,7 @@ struct ifb_private {
struct sk_buff_head tq;
};
-static int numifbs = 1;
+static int numifbs = 2;
static void ri_tasklet(unsigned long dev);
static int ifb_xmit(struct sk_buff *skb, struct net_device *dev);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index fa176ffb4ad5..8936058a3cce 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -108,6 +108,7 @@ static void irda_usb_close(struct irda_usb_cb *self);
static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void irda_usb_receive(struct urb *urb, struct pt_regs *regs);
+static void irda_usb_rx_defer_expired(unsigned long data);
static int irda_usb_net_open(struct net_device *dev);
static int irda_usb_net_close(struct net_device *dev);
static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -677,6 +678,12 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* on the interrupt pipe and hang the Rx URB only when an interrupt is
* received.
* Jean II
+ *
+ * Note : don't read the above as what we are currently doing, but as
+ * something we could do with KC dongle. Also don't forget that the
+ * interrupt pipe is not part of the original standard, so this would
+ * need to be optional...
+ * Jean II
*/
/*------------------------------------------------------------------*/
@@ -704,10 +711,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
/* Reinitialize URB */
usb_fill_bulk_urb(urb, self->usbdev,
usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep),
- skb->data, skb->truesize,
+ skb->data, IRDA_SKB_MAX_MTU,
irda_usb_receive, skb);
- /* Note : unlink *must* be synchronous because of the code in
- * irda_usb_net_close() -> free the skb - Jean II */
urb->status = 0;
/* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */
@@ -734,6 +739,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
struct irda_skb_cb *cb;
struct sk_buff *newskb;
struct sk_buff *dataskb;
+ struct urb *next_urb;
int docopy;
IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
@@ -755,20 +761,37 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
if (urb->status != 0) {
switch (urb->status) {
case -EILSEQ:
- self->stats.rx_errors++;
self->stats.rx_crc_errors++;
- break;
+ /* Also precursor to a hot-unplug on UHCI. */
+ /* Fallthrough... */
case -ECONNRESET: /* -104 */
- IRDA_DEBUG(0, "%s(), Connection Reset (-104), transfer_flags 0x%04X \n", __FUNCTION__, urb->transfer_flags);
+ /* Random error, if I remember correctly */
/* uhci_cleanup_unlink() is going to kill the Rx
* URB just after we return. No problem, at this
* point the URB will be idle ;-) - Jean II */
- break;
+ case -ESHUTDOWN: /* -108 */
+ /* That's usually a hot-unplug. Submit will fail... */
+ case -ETIMEDOUT: /* -110 */
+ /* Usually precursor to a hot-unplug on OHCI. */
default:
- IRDA_DEBUG(0, "%s(), RX status %d,transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
+ self->stats.rx_errors++;
+ IRDA_DEBUG(0, "%s(), RX status %d, transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
break;
}
- goto done;
+ /* If we received an error, we don't want to resubmit the
+ * Rx URB straight away but to give the USB layer a little
+ * bit of breathing room.
+ * We are in the USB thread context, therefore there is a
+ * danger of recursion (new URB we submit fails, we come
+ * back here).
+ * With recent USB stack (2.6.15+), I'm seeing that on
+ * hot unplug of the dongle...
+ * Lowest effective timer is 10ms...
+ * Jean II */
+ self->rx_defer_timer.function = &irda_usb_rx_defer_expired;
+ self->rx_defer_timer.data = (unsigned long) urb;
+ mod_timer(&self->rx_defer_timer, jiffies + (10 * HZ / 1000));
+ return;
}
/* Check for empty frames */
@@ -845,13 +868,45 @@ done:
* idle slot....
* Jean II */
/* Note : with this scheme, we could submit the idle URB before
- * processing the Rx URB. Another time... Jean II */
+ * processing the Rx URB. I don't think it would buy us anything as
+ * we are running in the USB thread context. Jean II */
+ next_urb = self->idle_rx_urb;
- /* Submit the idle URB to replace the URB we've just received */
- irda_usb_submit(self, skb, self->idle_rx_urb);
/* Recycle Rx URB : Now, the idle URB is the present one */
urb->context = NULL;
self->idle_rx_urb = urb;
+
+ /* Submit the idle URB to replace the URB we've just received.
+ * Do it last to avoid race conditions... Jean II */
+ irda_usb_submit(self, skb, next_urb);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * In case of errors, we want the USB layer to have time to recover.
+ * Now, it is time to resubmit ouur Rx URB...
+ */
+static void irda_usb_rx_defer_expired(unsigned long data)
+{
+ struct urb *urb = (struct urb *) data;
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
+ struct irda_usb_cb *self;
+ struct irda_skb_cb *cb;
+ struct urb *next_urb;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+ /* Find ourselves */
+ cb = (struct irda_skb_cb *) skb->cb;
+ IRDA_ASSERT(cb != NULL, return;);
+ self = (struct irda_usb_cb *) cb->context;
+ IRDA_ASSERT(self != NULL, return;);
+
+ /* Same stuff as when Rx is done, see above... */
+ next_urb = self->idle_rx_urb;
+ urb->context = NULL;
+ self->idle_rx_urb = urb;
+ irda_usb_submit(self, skb, next_urb);
}
/*------------------------------------------------------------------*/
@@ -990,6 +1045,9 @@ static int irda_usb_net_close(struct net_device *netdev)
/* Stop network Tx queue */
netif_stop_queue(netdev);
+ /* Kill defered Rx URB */
+ del_timer(&self->rx_defer_timer);
+
/* Deallocate all the Rx path buffers (URBs and skb) */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
struct urb *urb = self->rx_urb[i];
@@ -1365,6 +1423,7 @@ static int irda_usb_probe(struct usb_interface *intf,
self = net->priv;
self->netdev = net;
spin_lock_init(&self->lock);
+ init_timer(&self->rx_defer_timer);
/* Create all of the needed urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
@@ -1498,6 +1557,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
* This will stop/desactivate the Tx path. - Jean II */
self->present = 0;
+ /* Kill defered Rx URB */
+ del_timer(&self->rx_defer_timer);
+
/* We need to have irq enabled to unlink the URBs. That's OK,
* at this point the Tx path is gone - Jean II */
spin_unlock_irqrestore(&self->lock, flags);
@@ -1507,11 +1569,11 @@ static void irda_usb_disconnect(struct usb_interface *intf)
/* Accept no more transmissions */
/*netif_device_detach(self->netdev);*/
netif_stop_queue(self->netdev);
- /* Stop all the receive URBs */
+ /* Stop all the receive URBs. Must be synchronous. */
for (i = 0; i < IU_MAX_RX_URBS; i++)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
- * Toggle flags to make sure it's synchronous. */
+ * Make sure it's synchronous to avoid races. */
usb_kill_urb(self->tx_urb);
usb_kill_urb(self->speed_urb);
}
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index bd8f66542322..4026af42dd47 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -136,8 +136,6 @@ struct irda_usb_cb {
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
- wait_queue_head_t wait_q; /* for timeouts */
-
struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
@@ -147,17 +145,18 @@ struct irda_usb_cb {
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos;
- hashbin_t *tx_list; /* Queued transmit skb's */
char *speed_buff; /* Buffer for speed changes */
struct timeval stamp;
struct timeval now;
- spinlock_t lock; /* For serializing operations */
+ spinlock_t lock; /* For serializing Tx operations */
__u16 xbofs; /* Current xbofs setting */
__s16 new_xbofs; /* xbofs we need to set */
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
+
+ struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
};
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 7ef4b0434a3f..c0998ef938e0 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -32,6 +32,8 @@
*/
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 01ddfc8cce3f..aa5581369399 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -806,6 +806,7 @@ static struct pcmcia_device_id axnet_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
+ PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1),
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 1c6d328165bb..0245e40b51a1 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1610,6 +1610,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
}
else if (!pskb_may_pull(skb, skb->len))
goto err;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
if (len <= 0) {
@@ -1690,6 +1692,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
kfree_skb(skb);
} else {
skb_pull(skb, 2); /* chop off protocol */
+ skb_postpull_rcsum(skb, skb->data - 2, 2);
skb->dev = ppp->dev;
skb->protocol = htons(npindex_to_ethertype[npi]);
skb->mac.raw = skb->data;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 2e1bed153c39..8cc0d0bbdf50 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -287,6 +287,20 @@ enum RTL8169_register_content {
TxInterFrameGapShift = 24,
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
+ /* Config1 register p.24 */
+ PMEnable = (1 << 0), /* Power Management Enable */
+
+ /* Config3 register p.25 */
+ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
+ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
+
+ /* Config5 register p.27 */
+ BWF = (1 << 6), /* Accept Broadcast wakeup frame */
+ MWF = (1 << 5), /* Accept Multicast wakeup frame */
+ UWF = (1 << 4), /* Accept Unicast wakeup frame */
+ LanWake = (1 << 1), /* LanWake enable/disable */
+ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
+
/* TBICSR p.28 */
TBIReset = 0x80000000,
TBILoopback = 0x40000000,
@@ -433,6 +447,7 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
struct work_struct task;
+ unsigned wol_enabled : 1;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -484,13 +499,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
int i;
RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
- udelay(1000);
- for (i = 2000; i > 0; i--) {
+ for (i = 20; i > 0; i--) {
/* Check if the RTL8169 has completed writing to the specified MII register */
if (!(RTL_R32(PHYAR) & 0x80000000))
break;
- udelay(100);
+ udelay(25);
}
}
@@ -499,15 +513,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
int i, value = -1;
RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
- udelay(1000);
- for (i = 2000; i > 0; i--) {
+ for (i = 20; i > 0; i--) {
/* Check if the RTL8169 has completed retrieving data from the specified MII register */
if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break;
}
- udelay(100);
+ udelay(25);
}
return value;
}
@@ -609,6 +622,80 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
*duplex = p->duplex;
}
+static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u8 options;
+
+ wol->wolopts = 0;
+
+#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
+ wol->supported = WAKE_ANY;
+
+ spin_lock_irq(&tp->lock);
+
+ options = RTL_R8(Config1);
+ if (!(options & PMEnable))
+ goto out_unlock;
+
+ options = RTL_R8(Config3);
+ if (options & LinkUp)
+ wol->wolopts |= WAKE_PHY;
+ if (options & MagicPacket)
+ wol->wolopts |= WAKE_MAGIC;
+
+ options = RTL_R8(Config5);
+ if (options & UWF)
+ wol->wolopts |= WAKE_UCAST;
+ if (options & BWF)
+ wol->wolopts |= WAKE_BCAST;
+ if (options & MWF)
+ wol->wolopts |= WAKE_MCAST;
+
+out_unlock:
+ spin_unlock_irq(&tp->lock);
+}
+
+static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ int i;
+ static struct {
+ u32 opt;
+ u16 reg;
+ u8 mask;
+ } cfg[] = {
+ { WAKE_ANY, Config1, PMEnable },
+ { WAKE_PHY, Config3, LinkUp },
+ { WAKE_MAGIC, Config3, MagicPacket },
+ { WAKE_UCAST, Config5, UWF },
+ { WAKE_BCAST, Config5, BWF },
+ { WAKE_MCAST, Config5, MWF },
+ { WAKE_ANY, Config5, LanWake }
+ };
+
+ spin_lock_irq(&tp->lock);
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ for (i = 0; i < ARRAY_SIZE(cfg); i++) {
+ u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
+ if (wol->wolopts & cfg[i].opt)
+ options |= cfg[i].mask;
+ RTL_W8(cfg[i].reg, options);
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ tp->wol_enabled = (wol->wolopts) ? 1 : 0;
+
+ spin_unlock_irq(&tp->lock);
+
+ return 0;
+}
+
static void rtl8169_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -677,6 +764,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
if (duplex == DUPLEX_HALF)
auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
+
+ if (duplex == DUPLEX_FULL)
+ auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half);
}
tp->phy_auto_nego_reg = auto_nego;
@@ -1024,6 +1114,8 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
.get_regs = rtl8169_get_regs,
+ .get_wol = rtl8169_get_wol,
+ .set_wol = rtl8169_set_wol,
.get_strings = rtl8169_get_strings,
.get_stats_count = rtl8169_get_stats_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
@@ -1441,6 +1533,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
}
tp->chipset = i;
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+ RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
+ RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
*ioaddr_out = ioaddr;
*dev_out = dev;
out:
@@ -1611,49 +1708,6 @@ rtl8169_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-#ifdef CONFIG_PM
-
-static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- void __iomem *ioaddr = tp->mmio_addr;
- unsigned long flags;
-
- if (!netif_running(dev))
- return 0;
-
- netif_device_detach(dev);
- netif_stop_queue(dev);
- spin_lock_irqsave(&tp->lock, flags);
-
- /* Disable interrupts, stop Rx and Tx */
- RTL_W16(IntrMask, 0);
- RTL_W8(ChipCmd, 0);
-
- /* Update the error counts. */
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
- RTL_W32(RxMissed, 0);
- spin_unlock_irqrestore(&tp->lock, flags);
-
- return 0;
-}
-
-static int rtl8169_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
-
- if (!netif_running(dev))
- return 0;
-
- netif_device_attach(dev);
- rtl8169_hw_start(dev);
-
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
struct net_device *dev)
{
@@ -2699,6 +2753,56 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
return &tp->stats;
}
+#ifdef CONFIG_PM
+
+static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ if (!netif_running(dev))
+ goto out;
+
+ netif_device_detach(dev);
+ netif_stop_queue(dev);
+
+ spin_lock_irq(&tp->lock);
+
+ rtl8169_asic_down(ioaddr);
+
+ tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ RTL_W32(RxMissed, 0);
+
+ spin_unlock_irq(&tp->lock);
+
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+out:
+ return 0;
+}
+
+static int rtl8169_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (!netif_running(dev))
+ goto out;
+
+ netif_device_attach(dev);
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+
+ rtl8169_schedule_work(dev, rtl8169_reset_task);
+out:
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
static struct pci_driver rtl8169_pci_driver = {
.name = MODULENAME,
.id_table = rtl8169_pci_tbl,
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 49b597cbc19a..b7f00d6eb6a6 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -4092,6 +4092,7 @@ static void s2io_set_multicast(struct net_device *dev)
i++, mclist = mclist->next) {
memcpy(sp->usr_addrs[i].addr, mclist->dmi_addr,
ETH_ALEN);
+ mac_addr = 0;
for (j = 0; j < ETH_ALEN; j++) {
mac_addr |= mclist->dmi_addr[j];
mac_addr <<= 8;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b420182eec4b..ed4bc91638d2 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1791,6 +1791,8 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
goto out;
}
+ pci_set_drvdata(pdev, dev);
+
tp = netdev_priv(dev);
ioaddr = tp->mmio_addr;
@@ -1827,8 +1829,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
if (rc < 0)
goto err_remove_mii;
- pci_set_drvdata(pdev, dev);
-
net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
pci_name(pdev), sis_chip_info[ent->driver_data].name,
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 3d95fa20cd88..7a952fe60be2 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -540,7 +540,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
printk("%2.2x.\n", net_dev->dev_addr[i]);
/* Detect Wake on Lan support */
- ret = inl(CFGPMC & PMESP);
+ ret = (inl(net_dev->base_addr + CFGPMC) & PMESP) >> 27;
if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0)
printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name);
@@ -2040,7 +2040,7 @@ static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wo
if (wol->wolopts == 0) {
pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
- cfgpmcsr |= ~PME_EN;
+ cfgpmcsr &= ~PME_EN;
pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
outl(pmctrl_bits, pmctrl_addr);
if (netif_msg_wol(sis_priv))
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h
index 4233ea55670f..50323941e3c0 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/sis900.h
@@ -33,7 +33,6 @@ enum sis900_registers {
rxcfg=0x34, //Receive Configuration Register
flctrl=0x38, //Flow Control Register
rxlen=0x3c, //Receive Packet Length Register
- cfgpmcsr=0x44, //Configuration Power Management Control/Status Register
rfcr=0x48, //Receive Filter Control Register
rfdr=0x4C, //Receive Filter Data Register
pmctrl=0xB0, //Power Management Control Register
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index bf55a4cfb3d2..25e028b7ce48 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -879,13 +879,12 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
int i;
xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
- xm_read16(hw, port, XM_PHY_DATA);
+ *val = xm_read16(hw, port, XM_PHY_DATA);
- /* Need to wait for external PHY */
for (i = 0; i < PHY_RETRIES; i++) {
- udelay(1);
if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
goto ready;
+ udelay(1);
}
return -ETIMEDOUT;
@@ -918,7 +917,12 @@ static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
ready:
xm_write16(hw, port, XM_PHY_DATA, val);
- return 0;
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ return 0;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
}
static void genesis_init(struct skge_hw *hw)
@@ -1168,13 +1172,17 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
u32 r;
const u8 zero[6] = { 0 };
- /* Clear MIB counters */
- xm_write16(hw, port, XM_STAT_CMD,
- XM_SC_CLR_RXC | XM_SC_CLR_TXC);
- /* Clear two times according to Errata #3 */
- xm_write16(hw, port, XM_STAT_CMD,
- XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+ for (i = 0; i < 10; i++) {
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
+ MFF_SET_MAC_RST);
+ if (skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)
+ goto reset_ok;
+ udelay(1);
+ }
+ printk(KERN_WARNING PFX "%s: genesis reset failed\n", dev->name);
+
+ reset_ok:
/* Unreset the XMAC. */
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
@@ -1191,7 +1199,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
r |= GP_DIR_2|GP_IO_2;
skge_write32(hw, B2_GP_IO, r);
- skge_read32(hw, B2_GP_IO);
+
/* Enable GMII interface */
xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
@@ -1205,6 +1213,13 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
for (i = 1; i < 16; i++)
xm_outaddr(hw, port, XM_EXM(i), zero);
+ /* Clear MIB counters */
+ xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+ /* Clear two times according to Errata #3 */
+ xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
/* configure Rx High Water Mark (XM_RX_HI_WM) */
xm_write16(hw, port, XM_RX_HI_WM, 1450);
@@ -1697,6 +1712,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+
if (skge->autoneg == AUTONEG_DISABLE) {
reg = GM_GPCR_AU_ALL_DIS;
gma_write16(hw, port, GM_GP_CTRL,
@@ -1704,16 +1720,23 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
switch (skge->speed) {
case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
reg |= GM_GPCR_SPEED_1000;
- /* fallthru */
+ break;
case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
}
if (skge->duplex == DUPLEX_FULL)
reg |= GM_GPCR_DUP_FULL;
} else
reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+
switch (skge->flow_control) {
case FLOW_MODE_NONE:
skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -2162,8 +2185,10 @@ static int skge_up(struct net_device *dev)
skge->tx_avail = skge->tx_ring.count - 1;
/* Enable IRQ from port */
+ spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= portirqmask[port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
/* Initialize MAC */
spin_lock_bh(&hw->phy_lock);
@@ -2221,8 +2246,10 @@ static int skge_down(struct net_device *dev)
else
yukon_stop(skge);
+ spin_lock_irq(&hw->hw_lock);
hw->intr_mask &= ~portirqmask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
@@ -2670,8 +2697,7 @@ static int skge_poll(struct net_device *dev, int *budget)
/* restart receiver */
wmb();
- skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR),
- CSR_START | CSR_IRQ_CL_F);
+ skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START);
*budget -= work_done;
dev->quota -= work_done;
@@ -2679,10 +2705,11 @@ static int skge_poll(struct net_device *dev, int *budget)
if (work_done >= to_do)
return 1; /* not done */
- netif_rx_complete(dev);
- hw->intr_mask |= portirqmask[skge->port];
- skge_write32(hw, B0_IMSK, hw->intr_mask);
- skge_read32(hw, B0_IMSK);
+ spin_lock_irq(&hw->hw_lock);
+ __netif_rx_complete(dev);
+ hw->intr_mask |= portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
return 0;
}
@@ -2842,18 +2869,10 @@ static void skge_extirq(unsigned long data)
}
spin_unlock(&hw->phy_lock);
- local_irq_disable();
+ spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= IS_EXT_REG;
skge_write32(hw, B0_IMSK, hw->intr_mask);
- local_irq_enable();
-}
-
-static inline void skge_wakeup(struct net_device *dev)
-{
- struct skge_port *skge = netdev_priv(dev);
-
- prefetch(skge->rx_ring.to_clean);
- netif_rx_schedule(dev);
+ spin_unlock_irq(&hw->hw_lock);
}
static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2864,15 +2883,17 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
if (status == 0 || status == ~0) /* hotplug or shared irq */
return IRQ_NONE;
- status &= hw->intr_mask;
+ spin_lock(&hw->hw_lock);
if (status & IS_R1_F) {
+ skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
hw->intr_mask &= ~IS_R1_F;
- skge_wakeup(hw->dev[0]);
+ netif_rx_schedule(hw->dev[0]);
}
if (status & IS_R2_F) {
+ skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
hw->intr_mask &= ~IS_R2_F;
- skge_wakeup(hw->dev[1]);
+ netif_rx_schedule(hw->dev[1]);
}
if (status & IS_XA1_F)
@@ -2914,6 +2935,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
}
skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock(&hw->hw_lock);
return IRQ_HANDLED;
}
@@ -3282,6 +3304,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
hw->pdev = pdev;
spin_lock_init(&hw->phy_lock);
+ spin_lock_init(&hw->hw_lock);
tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 2efdacc290e5..941f12a333b6 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2402,6 +2402,7 @@ struct skge_hw {
struct tasklet_struct ext_tasklet;
spinlock_t phy_lock;
+ spinlock_t hw_lock;
};
enum {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f8b973a04b65..73260364cba3 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -23,12 +23,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/*
- * TOTEST
- * - speed setting
- * - suspend/resume
- */
-
#include <linux/config.h>
#include <linux/crc32.h>
#include <linux/kernel.h>
@@ -57,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "0.13"
+#define DRV_VERSION "0.15"
#define PFX DRV_NAME " "
/*
@@ -80,7 +74,7 @@
#define TX_RING_SIZE 512
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
#define TX_MIN_PENDING 64
-#define MAX_SKB_TX_LE (4 + 2*MAX_SKB_FRAGS)
+#define MAX_SKB_TX_LE (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS)
#define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */
#define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le))
@@ -197,11 +191,11 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
pr_debug("sky2_set_power_state %d\n", state);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
- vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+ power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_PMC);
+ vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
(power_control & PCI_PM_CAP_PME_D3cold);
- pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control);
+ power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL);
power_control |= PCI_PM_CTRL_PME_STATUS;
power_control &= ~(PCI_PM_CTRL_STATE_MASK);
@@ -225,7 +219,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
/* Turn off phy power saving */
- pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
/* looks like this XL is back asswards .. */
@@ -234,18 +228,28 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
if (hw->ports > 1)
reg1 |= PCI_Y2_PHY2_COMA;
}
- pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
+ reg1 &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
+ sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+ }
+
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+
break;
case PCI_D3hot:
case PCI_D3cold:
/* Turn on phy power saving */
- pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
else
reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
- pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
@@ -267,7 +271,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
ret = -1;
}
- pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control);
+ sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
return ret;
}
@@ -465,16 +469,31 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
}
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+ /* apply fixes in PHY AFE */
+ gm_phy_write(hw, port, 22, 255);
+ /* increase differential signal amplitude in 10BASE-T */
+ gm_phy_write(hw, port, 24, 0xaa99);
+ gm_phy_write(hw, port, 23, 0x2011);
- if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
- /* turn on 100 Mbps LED (LED_LINK100) */
- ledover |= PHY_M_LED_MO_100(MO_LED_ON);
- }
+ /* fix for IEEE A/B Symmetry failure in 1000BASE-T */
+ gm_phy_write(hw, port, 24, 0xa204);
+ gm_phy_write(hw, port, 23, 0x2002);
- if (ledover)
- gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ /* set page register to 0 */
+ gm_phy_write(hw, port, 22, 0);
+ } else {
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+ if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
+ /* turn on 100 Mbps LED (LED_LINK100) */
+ ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+
+ if (ledover)
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ }
/* Enable phy interrupt on auto-negotiation complete (or link up) */
if (sky2->autoneg == AUTONEG_ENABLE)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
@@ -522,10 +541,16 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
switch (sky2->speed) {
case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
reg |= GM_GPCR_SPEED_1000;
- /* fallthru */
+ break;
case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
}
if (sky2->duplex == DUPLEX_FULL)
@@ -597,8 +622,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
- sky2_write16(hw, SK_REG(port, RX_GMF_CTRL_T),
- GMF_RX_CTRL_DEF);
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+ GMF_OPER_ON | GMF_RX_F_FL_ON);
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@@ -949,6 +974,12 @@ static int sky2_rx_start(struct sky2_port *sky2)
sky2->rx_put = sky2->rx_next = 0;
sky2_qset(hw, rxq);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+ /* MAC Rx RAM Read is controlled by hardware */
+ sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+ }
+
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
rx_set_checksum(sky2);
@@ -964,6 +995,10 @@ static int sky2_rx_start(struct sky2_port *sky2)
sky2_rx_add(sky2, re->mapaddr);
}
+ /* Truncate oversize frames */
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8);
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+
/* Tell chip about available buffers */
sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX));
@@ -1031,9 +1066,10 @@ static int sky2_up(struct net_device *dev)
RB_RST_SET);
sky2_qset(hw, txqaddr[port]);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U)
- sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
+ /* Set almost empty threshold */
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == 1)
+ sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
TX_RING_SIZE - 1);
@@ -1043,8 +1079,10 @@ static int sky2_up(struct net_device *dev)
goto err_out;
/* Enable interrupts from phy/mac for port */
+ spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
return 0;
err_out:
@@ -1111,6 +1149,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
struct sky2_tx_le *le = NULL;
struct tx_ring_info *re;
unsigned i, len;
+ int avail;
dma_addr_t mapping;
u32 addr64;
u16 mss;
@@ -1253,12 +1292,16 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
re->idx = sky2->tx_prod;
le->ctrl |= EOP;
+ avail = tx_avail(sky2);
+ if (mss != 0 || avail < TX_MIN_PENDING) {
+ le->ctrl |= FRC_STAT;
+ if (avail <= MAX_SKB_TX_LE)
+ netif_stop_queue(dev);
+ }
+
sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod,
&sky2->tx_last_put, TX_RING_SIZE);
- if (tx_avail(sky2) <= MAX_SKB_TX_LE)
- netif_stop_queue(dev);
-
out_unlock:
spin_unlock(&sky2->tx_lock);
@@ -1344,10 +1387,10 @@ static int sky2_down(struct net_device *dev)
netif_stop_queue(dev);
/* Disable port IRQ */
- local_irq_disable();
+ spin_lock_irq(&hw->hw_lock);
hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
sky2_write32(hw, B0_IMSK, hw->intr_mask);
- local_irq_enable();
+ spin_unlock_irq(&hw->hw_lock);
flush_scheduled_work();
@@ -1448,6 +1491,29 @@ static void sky2_link_up(struct sky2_port *sky2)
sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
+ if (sky2->autoneg == AUTONEG_DISABLE) {
+ reg |= GM_GPCR_AU_ALL_DIS;
+
+ /* Is write/read necessary? Copied from sky2_mac_init */
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_read16(hw, port, GM_GP_CTRL);
+
+ switch (sky2->speed) {
+ case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
+ reg |= GM_GPCR_SPEED_1000;
+ break;
+ case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
+ reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
+ }
+ } else
+ reg &= ~GM_GPCR_AU_ALL_DIS;
+
if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE)
reg |= GM_GPCR_DUP_FULL;
@@ -1606,10 +1672,10 @@ static void sky2_phy_task(void *arg)
out:
up(&sky2->phy_sema);
- local_irq_disable();
+ spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
- local_irq_enable();
+ spin_unlock_irq(&hw->hw_lock);
}
@@ -1650,10 +1716,12 @@ static void sky2_tx_timeout(struct net_device *dev)
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
-/* Want receive buffer size to be multiple of 64 bits, and incl room for vlan */
+/* Want receive buffer size to be multiple of 64 bits
+ * and incl room for vlan and truncation
+ */
static inline unsigned sky2_buf_size(int mtu)
{
- return roundup(mtu + ETH_HLEN + 4, 8);
+ return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
}
static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -1736,7 +1804,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
if (!(status & GMR_FS_RX_OK))
goto resubmit;
- if ((status >> 16) != length || length > sky2->rx_bufsize)
+ if (length > sky2->netdev->mtu + ETH_HLEN)
goto oversize;
if (length < copybreak) {
@@ -1834,6 +1902,19 @@ static int sky2_poll(struct net_device *dev0, int *budget)
u16 hwidx;
u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+ /*
+ * Kick the STAT_LEV_TIMER_CTRL timer.
+ * This fixes my hangs on Yukon-EC (0xb6) rev 1.
+ * The if clause is there to start the timer only if it has been
+ * configured correctly and not been disabled via ethtool.
+ */
+ if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ }
+
hwidx = sky2_read16(hw, STAT_PUT_IDX);
BUG_ON(hwidx >= STATUS_RING_SIZE);
rmb();
@@ -1913,21 +1994,22 @@ static int sky2_poll(struct net_device *dev0, int *budget)
}
exit_loop:
- sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-
sky2_tx_check(hw, 0, tx_done[0]);
sky2_tx_check(hw, 1, tx_done[1]);
- if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) {
- /* need to restart TX timer */
- if (is_ec_a1(hw)) {
- sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
- sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
- }
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ }
+
+ if (likely(work_done < to_do)) {
+ spin_lock_irq(&hw->hw_lock);
+ __netif_rx_complete(dev0);
- netif_rx_complete(dev0);
hw->intr_mask |= Y2_IS_STAT_BMU;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
+
return 0;
} else {
*budget -= work_done;
@@ -1990,13 +2072,13 @@ static void sky2_hw_intr(struct sky2_hw *hw)
if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
u16 pci_err;
- pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
+ pci_err = sky2_pci_read16(hw, PCI_STATUS);
if (net_ratelimit())
printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
pci_name(hw->pdev), pci_err);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_write_config_word(hw->pdev, PCI_STATUS,
+ sky2_pci_write16(hw, PCI_STATUS,
pci_err | PCI_STATUS_ERROR_BITS);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
@@ -2005,7 +2087,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
/* PCI-Express uncorrectable Error occurred */
u32 pex_err;
- pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
+ pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT);
if (net_ratelimit())
printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
@@ -2013,7 +2095,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
/* clear the interrupt */
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+ sky2_pci_write32(hw, PEX_UNC_ERR_STAT,
0xffffffffUL);
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2059,6 +2141,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
schedule_work(&sky2->phy_task);
}
@@ -2072,6 +2155,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
if (status == 0 || status == ~0)
return IRQ_NONE;
+ spin_lock(&hw->hw_lock);
if (status & Y2_IS_HW_ERR)
sky2_hw_intr(hw);
@@ -2100,7 +2184,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
sky2_write32(hw, B0_Y2_SP_ICR, 2);
- sky2_read32(hw, B0_IMSK);
+ spin_unlock(&hw->hw_lock);
return IRQ_HANDLED;
}
@@ -2141,14 +2225,12 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
static int sky2_reset(struct sky2_hw *hw)
{
- u32 ctst;
u16 status;
u8 t8, pmd_type;
int i;
- ctst = sky2_read32(hw, B0_CTST);
-
sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
@@ -2156,12 +2238,6 @@ static int sky2_reset(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
- /* ring for status responses */
- hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
- &hw->st_dma);
- if (!hw->st_le)
- return -ENOMEM;
-
/* disable ASF */
if (hw->chip_id <= CHIP_ID_YUKON_EC) {
sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
@@ -2173,20 +2249,18 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_RST_CLR);
/* clear PCI errors, if any */
- pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+ status = sky2_pci_read16(hw, PCI_STATUS);
+
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_write_config_word(hw->pdev, PCI_STATUS,
- status | PCI_STATUS_ERROR_BITS);
+ sky2_pci_write16(hw, PCI_STATUS, status | PCI_STATUS_ERROR_BITS);
+
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
/* clear any PEX errors */
- if (is_pciex(hw)) {
- u16 lstat;
- pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
- 0xffffffffUL);
- pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat);
- }
+ if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+ sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL);
+
pmd_type = sky2_read8(hw, B2_PMD_TYP);
hw->copper = !(pmd_type == 'L' || pmd_type == 'S');
@@ -2285,8 +2359,7 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
- sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100));
- sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
+ sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7));
}
/* enable status unit */
@@ -2551,19 +2624,24 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev)
static int sky2_set_mac_address(struct net_device *dev, void *p)
{
struct sky2_port *sky2 = netdev_priv(dev);
- struct sockaddr *addr = p;
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ const struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
- memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
+ memcpy_toio(hw->regs + B2_MAC_1 + port * 8,
dev->dev_addr, ETH_ALEN);
- memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
+ memcpy_toio(hw->regs + B2_MAC_2 + port * 8,
dev->dev_addr, ETH_ALEN);
- if (netif_running(dev))
- sky2_phy_reinit(sky2);
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
return 0;
}
@@ -2815,11 +2893,11 @@ static int sky2_set_coalesce(struct net_device *dev,
(ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax))
return -EINVAL;
- if (ecmd->tx_max_coalesced_frames > 0xffff)
+ if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1)
return -EINVAL;
- if (ecmd->rx_max_coalesced_frames > 0xff)
+ if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING)
return -EINVAL;
- if (ecmd->rx_max_coalesced_frames_irq > 0xff)
+ if (ecmd->rx_max_coalesced_frames_irq >RX_MAX_PENDING)
return -EINVAL;
if (ecmd->tx_coalesce_usecs == 0)
@@ -2843,7 +2921,7 @@ static int sky2_set_coalesce(struct net_device *dev,
if (ecmd->rx_coalesce_usecs_irq == 0)
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
else {
- sky2_write32(hw, STAT_TX_TIMER_INI,
+ sky2_write32(hw, STAT_ISR_TIMER_INI,
sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
}
@@ -3106,17 +3184,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
}
}
-#ifdef __BIG_ENDIAN
- /* byte swap descriptors in hardware */
- {
- u32 reg;
-
- pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
- reg |= PCI_REV_DESC;
- pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
- }
-#endif
-
err = -ENOMEM;
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw) {
@@ -3134,6 +3201,24 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_hw;
}
hw->pm_cap = pm_cap;
+ spin_lock_init(&hw->hw_lock);
+
+#ifdef __BIG_ENDIAN
+ /* byte swap descriptors in hardware */
+ {
+ u32 reg;
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG2);
+ reg |= PCI_REV_DESC;
+ sky2_pci_write32(hw, PCI_DEV_REG2, reg);
+ }
+#endif
+
+ /* ring for status responses */
+ hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
+ &hw->st_dma);
+ if (!hw->st_le)
+ goto err_out_iounmap;
err = sky2_reset(hw);
if (err)
@@ -3263,25 +3348,33 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
static int sky2_resume(struct pci_dev *pdev)
{
struct sky2_hw *hw = pci_get_drvdata(pdev);
- int i;
+ int i, err;
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D0, 0);
- sky2_set_power_state(hw, PCI_D0);
+ err = sky2_set_power_state(hw, PCI_D0);
+ if (err)
+ goto out;
- sky2_reset(hw);
+ err = sky2_reset(hw);
+ if (err)
+ goto out;
for (i = 0; i < 2; i++) {
struct net_device *dev = hw->dev[i];
- if (dev) {
- if (netif_running(dev)) {
- netif_device_attach(dev);
- if (sky2_up(dev))
- dev_close(dev);
+ if (dev && netif_running(dev)) {
+ netif_device_attach(dev);
+ err = sky2_up(dev);
+ if (err) {
+ printk(KERN_ERR PFX "%s: could not up: %d\n",
+ dev->name, err);
+ dev_close(dev);
+ break;
}
}
}
- return 0;
+out:
+ return err;
}
#endif
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 95518921001c..dce955c76f3c 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -5,14 +5,22 @@
#define _SKY2_H
/* PCI config registers */
-#define PCI_DEV_REG1 0x40
-#define PCI_DEV_REG2 0x44
-#define PCI_DEV_STATUS 0x7c
-#define PCI_OS_PCI_X (1<<26)
+enum {
+ PCI_DEV_REG1 = 0x40,
+ PCI_DEV_REG2 = 0x44,
+ PCI_DEV_STATUS = 0x7c,
+ PCI_DEV_REG3 = 0x80,
+ PCI_DEV_REG4 = 0x84,
+ PCI_DEV_REG5 = 0x88,
+};
-#define PEX_LNK_STAT 0xf2
-#define PEX_UNC_ERR_STAT 0x104
-#define PEX_DEV_CTRL 0xe8
+enum {
+ PEX_DEV_CAP = 0xe4,
+ PEX_DEV_CTRL = 0xe8,
+ PEX_DEV_STA = 0xea,
+ PEX_LNK_STAT = 0xf2,
+ PEX_UNC_ERR_STAT= 0x104,
+};
/* Yukon-2 */
enum pci_dev_reg_1 {
@@ -37,6 +45,25 @@ enum pci_dev_reg_2 {
PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
};
+/* PCI_OUR_REG_4 32 bit Our Register 4 (Yukon-ECU only) */
+enum pci_dev_reg_4 {
+ /* (Link Training & Status State Machine) */
+ P_TIMER_VALUE_MSK = 0xffL<<16, /* Bit 23..16: Timer Value Mask */
+ /* (Active State Power Management) */
+ P_FORCE_ASPM_REQUEST = 1<<15, /* Force ASPM Request (A1 only) */
+ P_ASPM_GPHY_LINK_DOWN = 1<<14, /* GPHY Link Down (A1 only) */
+ P_ASPM_INT_FIFO_EMPTY = 1<<13, /* Internal FIFO Empty (A1 only) */
+ P_ASPM_CLKRUN_REQUEST = 1<<12, /* CLKRUN Request (A1 only) */
+
+ P_ASPM_FORCE_CLKREQ_ENA = 1<<4, /* Force CLKREQ Enable (A1b only) */
+ P_ASPM_CLKREQ_PAD_CTL = 1<<3, /* CLKREQ PAD Control (A1 only) */
+ P_ASPM_A1_MODE_SELECT = 1<<2, /* A1 Mode Select (A1 only) */
+ P_CLK_GATE_PEX_UNIT_ENA = 1<<1, /* Enable Gate PEX Unit Clock */
+ P_CLK_GATE_ROOT_COR_ENA = 1<<0, /* Enable Gate Root Core Clock */
+ P_ASPM_CONTROL_MSK = P_FORCE_ASPM_REQUEST | P_ASPM_GPHY_LINK_DOWN
+ | P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
+};
+
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -507,6 +534,16 @@ enum {
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+/* Q_F 32 bit Flag Register */
+enum {
+ F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
+ F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
+ F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
+ F_WM_REACHED = 1<<25, /* Watermark reached */
+ F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
+ F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
+ F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
enum {
@@ -909,10 +946,12 @@ enum {
PHY_BCOM_ID1_C0 = 0x6044,
PHY_BCOM_ID1_C5 = 0x6047,
- PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
+ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
- PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
- PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+ PHY_MARV_ID1_FE = 0x0C83, /* Yukon-FE (PHY 88E3082 Rev.A1) */
+ PHY_MARV_ID1_ECU= 0x0CB0, /* Yukon-ECU (PHY 88E1149 Rev.B2?) */
};
/* Advertisement register bits */
@@ -1837,8 +1876,9 @@ struct sky2_port {
struct sky2_hw {
void __iomem *regs;
struct pci_dev *pdev;
- u32 intr_mask;
struct net_device *dev[2];
+ spinlock_t hw_lock;
+ u32 intr_mask;
int pm_cap;
u8 chip_id;
@@ -1867,14 +1907,6 @@ static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg)
return readb(hw->regs + reg);
}
-/* This should probably go away, bus based tweeks suck */
-static inline int is_pciex(const struct sky2_hw *hw)
-{
- u32 status;
- pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status);
- return (status & PCI_OS_PCI_X) == 0;
-}
-
static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
{
writel(val, hw->regs + reg);
@@ -1919,4 +1951,25 @@ static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg,
gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
}
+
+/* PCI config space access */
+static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read32(hw, Y2_CFG_SPC + reg);
+}
+
+static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read16(hw, Y2_CFG_SPC + reg);
+}
+
+static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val)
+{
+ sky2_write32(hw, Y2_CFG_SPC + reg, val);
+}
+
+static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val)
+{
+ sky2_write16(hw, Y2_CFG_SPC + reg, val);
+}
#endif
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index e7dc653d5bd6..caf4102b54ce 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3532,9 +3532,23 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
(base + len + 8 < base));
}
+/* Test for DMA addresses > 40-bit */
+static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
+ int len)
+{
+#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+ return (((u64) mapping + len) > DMA_40BIT_MASK);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
-static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
+/* Workaround 4GB and 40-bit hardware DMA bugs. */
+static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
u32 last_plus_one, u32 *start,
u32 base_flags, u32 mss)
{
@@ -3742,6 +3756,9 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
+ if (tg3_40bit_overflow_test(tp, mapping, len))
+ would_hit_hwbug = 1;
+
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
tg3_set_txd(tp, entry, mapping, len,
base_flags, (i == last)|(mss << 1));
@@ -3763,7 +3780,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* If the workaround fails due to memory/mapping
* failure, silently drop this packet.
*/
- if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one,
+ if (tigon3_dma_hwbug_workaround(tp, skb, last_plus_one,
&start, base_flags, mss))
goto out_unlock;
@@ -9408,6 +9425,15 @@ static int __devinit tg3_is_sun_570X(struct tg3 *tp)
return 0;
if (venid == PCI_VENDOR_ID_SUN)
return 1;
+
+ /* TG3 chips onboard the SunBlade-2500 don't have the
+ * subsystem-vendor-id set to PCI_VENDOR_ID_SUN but they
+ * are distinguishable from non-Sun variants by being
+ * named "network" by the firmware. Non-Sun cards will
+ * show up as being named "ethernet".
+ */
+ if (!strcmp(pcp->prom_name, "network"))
+ return 1;
}
return 0;
}
@@ -9526,12 +9552,36 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
}
- /* Find msi capability. */
+ /* The EPB bridge inside 5714, 5715, and 5780 cannot support
+ * DMA addresses > 40-bit. This bridge may have other additional
+ * 57xx devices behind it in some 4-port NIC designs for example.
+ * Any tg3 device found behind the bridge will also need the 40-bit
+ * DMA workaround.
+ */
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
tp->tg3_flags2 |= TG3_FLG2_5780_CLASS;
+ tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG;
tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
}
+ else {
+ struct pci_dev *bridge = NULL;
+
+ do {
+ bridge = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_EPB,
+ bridge);
+ if (bridge && bridge->subordinate &&
+ (bridge->subordinate->number <=
+ tp->pdev->bus->number) &&
+ (bridge->subordinate->subordinate >=
+ tp->pdev->bus->number)) {
+ tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG;
+ pci_dev_put(bridge);
+ break;
+ }
+ } while (bridge);
+ }
/* Initialize misc host control in PCI block. */
tp->misc_host_ctrl |= (misc_ctrl_reg &
@@ -10277,7 +10327,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
- if (ccval == 0x6 || ccval == 0x7)
+ /* If the 5704 is behind the EPB bridge, we can
+ * do the less restrictive ONE_DMA workaround for
+ * better performance.
+ */
+ if ((tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tp->dma_rwctrl |= 0x8000;
+ else if (ccval == 0x6 || ccval == 0x7)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
/* Set bit 23 to enable PCIX hw bug fix */
@@ -10517,8 +10574,6 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
strcat(str, "66MHz");
else if (clock_ctrl == 6)
strcat(str, "100MHz");
- else if (clock_ctrl == 7)
- strcat(str, "133MHz");
} else {
strcpy(str, "PCI:");
if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED)
@@ -10599,8 +10654,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
unsigned long tg3reg_base, tg3reg_len;
struct net_device *dev;
struct tg3 *tp;
- int i, err, pci_using_dac, pm_cap;
+ int i, err, pm_cap;
char str[40];
+ u64 dma_mask, persist_dma_mask;
if (tg3_version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -10637,26 +10693,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_free_res;
}
- /* Configure DMA attributes. */
- err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
- if (!err) {
- pci_using_dac = 1;
- err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
- if (err < 0) {
- printk(KERN_ERR PFX "Unable to obtain 64 bit DMA "
- "for consistent allocations\n");
- goto err_out_free_res;
- }
- } else {
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (err) {
- printk(KERN_ERR PFX "No usable DMA configuration, "
- "aborting.\n");
- goto err_out_free_res;
- }
- pci_using_dac = 0;
- }
-
tg3reg_base = pci_resource_start(pdev, 0);
tg3reg_len = pci_resource_len(pdev, 0);
@@ -10670,8 +10706,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
- if (pci_using_dac)
- dev->features |= NETIF_F_HIGHDMA;
dev->features |= NETIF_F_LLTX;
#if TG3_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
@@ -10756,6 +10790,45 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
+ /* The EPB bridge inside 5714, 5715, and 5780 and any
+ * device behind the EPB cannot support DMA addresses > 40-bit.
+ * On 64-bit systems with IOMMU, use 40-bit dma_mask.
+ * On 64-bit systems without IOMMU, use 64-bit dma_mask and
+ * do DMA address check in tg3_start_xmit().
+ */
+ if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
+ persist_dma_mask = dma_mask = DMA_32BIT_MASK;
+ else if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) {
+ persist_dma_mask = dma_mask = DMA_40BIT_MASK;
+#ifdef CONFIG_HIGHMEM
+ dma_mask = DMA_64BIT_MASK;
+#endif
+ } else
+ persist_dma_mask = dma_mask = DMA_64BIT_MASK;
+
+ /* Configure DMA attributes. */
+ if (dma_mask > DMA_32BIT_MASK) {
+ err = pci_set_dma_mask(pdev, dma_mask);
+ if (!err) {
+ dev->features |= NETIF_F_HIGHDMA;
+ err = pci_set_consistent_dma_mask(pdev,
+ persist_dma_mask);
+ if (err < 0) {
+ printk(KERN_ERR PFX "Unable to obtain 64 bit "
+ "DMA for consistent allocations\n");
+ goto err_out_iounmap;
+ }
+ }
+ }
+ if (err || dma_mask == DMA_32BIT_MASK) {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX "No usable DMA configuration, "
+ "aborting.\n");
+ goto err_out_iounmap;
+ }
+ }
+
tg3_init_bufmgr_config(tp);
#if TG3_TSO_SUPPORT != 0
@@ -10824,9 +10897,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
} else
tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
- if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
- dev->features &= ~NETIF_F_HIGHDMA;
-
/* flow control autonegotiation is default behavior */
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
@@ -10870,8 +10940,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
- printk(KERN_INFO "%s: dma_rwctrl[%08x]\n",
- dev->name, tp->dma_rwctrl);
+ printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
+ dev->name, tp->dma_rwctrl,
+ (pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
+ (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
return 0;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 7f4b7f6ac40d..7e3b613afb29 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2163,6 +2163,7 @@ struct tg3 {
#define TG3_FLAG_10_100_ONLY 0x01000000
#define TG3_FLAG_PAUSE_AUTONEG 0x02000000
#define TG3_FLAG_IN_RESET_TASK 0x04000000
+#define TG3_FLAG_40BIT_DMA_BUG 0x08000000
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
#define TG3_FLAG_SPLIT_MODE 0x40000000
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index c2506b56a186..12076f8f942c 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -536,6 +536,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
u16 device_id;
int reg, rc = -ENODEV;
+#ifdef CONFIG_PCI
if (pdev) {
rc = pci_enable_device(pdev);
if (rc)
@@ -547,6 +548,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
goto err_out;
}
}
+#endif /* CONFIG_PCI */
dev = alloc_etherdev(sizeof(TLanPrivateInfo));
if (dev == NULL) {
diff --git a/drivers/net/tokenring/smctr.h b/drivers/net/tokenring/smctr.h
index b306c7e4c793..88dfa2e01d6e 100644
--- a/drivers/net/tokenring/smctr.h
+++ b/drivers/net/tokenring/smctr.h
@@ -1042,7 +1042,7 @@ typedef struct net_local {
__u16 functional_address[2];
__u16 bitwise_group_address[2];
- __u8 *ptr_ucode;
+ const __u8 *ptr_ucode;
__u8 cleanup;
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index d7fb3ffe06ac..2d0cfbceee22 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1362,7 +1362,6 @@ static int de_open (struct net_device *dev)
{
struct de_private *de = dev->priv;
int rc;
- unsigned long flags;
if (netif_msg_ifup(de))
printk(KERN_DEBUG "%s: enabling interface\n", dev->name);
@@ -1376,18 +1375,20 @@ static int de_open (struct net_device *dev)
return rc;
}
- rc = de_init_hw(de);
- if (rc) {
- printk(KERN_ERR "%s: h/w init failure, err=%d\n",
- dev->name, rc);
- goto err_out_free;
- }
+ dw32(IntrMask, 0);
rc = request_irq(dev->irq, de_interrupt, SA_SHIRQ, dev->name, dev);
if (rc) {
printk(KERN_ERR "%s: IRQ %d request failure, err=%d\n",
dev->name, dev->irq, rc);
- goto err_out_hw;
+ goto err_out_free;
+ }
+
+ rc = de_init_hw(de);
+ if (rc) {
+ printk(KERN_ERR "%s: h/w init failure, err=%d\n",
+ dev->name, rc);
+ goto err_out_free_irq;
}
netif_start_queue(dev);
@@ -1395,11 +1396,8 @@ static int de_open (struct net_device *dev)
return 0;
-err_out_hw:
- spin_lock_irqsave(&de->lock, flags);
- de_stop_hw(de);
- spin_unlock_irqrestore(&de->lock, flags);
-
+err_out_free_irq:
+ free_irq(dev->irq, dev);
err_out_free:
de_free_rings(de);
return rc;
@@ -1455,6 +1453,8 @@ static void de_tx_timeout (struct net_device *dev)
synchronize_irq(dev->irq);
de_clean_rings(de);
+ de_init_rings(de);
+
de_init_hw(de);
netif_wake_queue(dev);
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 983981666800..238e9c72cb3a 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -214,7 +214,7 @@ static u32 uli526x_cr6_user_set;
/* For module input parameter */
static int debug;
static u32 cr6set;
-static unsigned char mode = 8;
+static int mode = 8;
/* function declaration ------------------------------------- */
static int uli526x_open(struct net_device *);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 50b8c6754b1e..a1ed2d983740 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -249,8 +249,11 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
if (align)
skb_reserve(skb, align);
- if (memcpy_fromiovec(skb_put(skb, len), iv, len))
+ if (memcpy_fromiovec(skb_put(skb, len), iv, len)) {
+ tun->stats.rx_dropped++;
+ kfree_skb(skb);
return -EFAULT;
+ }
skb->dev = tun->dev;
switch (tun->flags & TUN_TYPE_MASK) {
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index c2d5907dc8e0..ed1f837c8fda 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1106,6 +1106,9 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
for (i = 0; i < vptr->options.numrx; i++) {
struct velocity_rd_info *rd_info = &(vptr->rd_info[i]);
+ struct rx_desc *rd = vptr->rd_ring + i;
+
+ memset(rd, 0, sizeof(*rd));
if (!rd_info->skb)
continue;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 2f61a47b4716..1ff5de076d21 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -1943,7 +1943,7 @@ static int dscc4_init_ring(struct net_device *dev)
(++i%TX_RING_SIZE)*sizeof(*tx_fd));
} while (i < TX_RING_SIZE);
- if (dscc4_init_dummy_skb(dpriv) < 0)
+ if (!dscc4_init_dummy_skb(dpriv))
goto err_free_dma_tx;
memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE);
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index 8dea07b47999..eba8e5cfacc2 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -29,7 +29,7 @@
#include <linux/netdevice.h>
#include <linux/hdlc.h>
#include <linux/pci.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include "hd64572.h"
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 9c1e10602f2b..9d3b51c3ef54 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -27,8 +27,8 @@
#include <linux/hdlc.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include <asm/io.h>
-#include <asm/delay.h>
#include "wanxl.h"
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 233a4f608084..ef85d76575a2 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -148,7 +148,7 @@ config IPW2100
In order to use this driver, you will need a firmware image for it.
You can obtain the firmware from
<http://ipw2100.sf.net/>. Once you have the firmware image, you
- will need to place it in /etc/firmware.
+ will need to place it in /lib/firmware.
You will also very likely need the Wireless Tools in order to
configure your card:
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 98a76f10a0f7..dfc24016ba81 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1872,7 +1872,7 @@ static int atmel_set_encodeext(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int idx, key_len;
+ int idx, key_len, alg = ext->alg, set_key = 1;
/* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX;
@@ -1883,39 +1883,42 @@ static int atmel_set_encodeext(struct net_device *dev,
} else
idx = priv->default_key;
- if ((encoding->flags & IW_ENCODE_DISABLED) ||
- ext->alg == IW_ENCODE_ALG_NONE) {
- priv->wep_is_on = 0;
- priv->encryption_level = 0;
- priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
- }
+ if (encoding->flags & IW_ENCODE_DISABLED)
+ alg = IW_ENCODE_ALG_NONE;
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
priv->default_key = idx;
+ set_key = ext->key_len > 0 ? 1 : 0;
+ }
- /* Set the requested key */
- switch (ext->alg) {
- case IW_ENCODE_ALG_NONE:
- break;
- case IW_ENCODE_ALG_WEP:
- if (ext->key_len > 5) {
- priv->wep_key_len[idx] = 13;
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
- priv->encryption_level = 2;
- } else if (ext->key_len > 0) {
- priv->wep_key_len[idx] = 5;
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
- priv->encryption_level = 1;
- } else {
+ if (set_key) {
+ /* Set the requested key first */
+ switch (alg) {
+ case IW_ENCODE_ALG_NONE:
+ priv->wep_is_on = 0;
+ priv->encryption_level = 0;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > 5) {
+ priv->wep_key_len[idx] = 13;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
+ priv->encryption_level = 2;
+ } else if (ext->key_len > 0) {
+ priv->wep_key_len[idx] = 5;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
+ priv->encryption_level = 1;
+ } else {
+ return -EINVAL;
+ }
+ priv->wep_is_on = 1;
+ memset(priv->wep_keys[idx], 0, 13);
+ key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
+ memcpy(priv->wep_keys[idx], ext->key, key_len);
+ break;
+ default:
return -EINVAL;
}
- priv->wep_is_on = 1;
- memset(priv->wep_keys[idx], 0, 13);
- key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
- memcpy(priv->wep_keys[idx], ext->key, key_len);
- break;
- default:
- return -EINVAL;
}
return -EINPROGRESS;
@@ -3061,17 +3064,26 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
+ int should_associate = 0;
/* WEP */
if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
return;
- if (trans_seq_no == 0x0002 &&
- auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
- send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
- return;
+ if (system == C80211_MGMT_AAN_OPENSYSTEM) {
+ if (trans_seq_no == 0x0002) {
+ should_associate = 1;
+ }
+ } else if (system == C80211_MGMT_AAN_SHAREDKEY) {
+ if (trans_seq_no == 0x0002 &&
+ auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
+ send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
+ return;
+ } else if (trans_seq_no == 0x0004) {
+ should_associate = 1;
+ }
}
- if (trans_seq_no == 0x0004) {
+ if (should_associate) {
if(priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
send_association_request(priv, 1);
@@ -3084,11 +3096,13 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
}
- if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
+ if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
/* Do opensystem first, then try sharedkey */
- if (system == C80211_MGMT_AAN_OPENSYSTEM) {
+ if (system == WLAN_AUTH_OPEN) {
priv->CurrentAuthentTransactionSeqNum = 0x001;
- send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
+ priv->exclude_unencrypted = 1;
+ send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0);
+ return;
} else if (priv->connect_to_any_BSS) {
int bss_index;
@@ -3439,10 +3453,13 @@ static void atmel_management_timer(u_long a)
priv->AuthenticationRequestRetryCnt = 0;
restart_search(priv);
} else {
+ int auth = C80211_MGMT_AAN_OPENSYSTEM;
priv->AuthenticationRequestRetryCnt++;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
- send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
+ if (priv->wep_is_on && priv->exclude_unencrypted)
+ auth = C80211_MGMT_AAN_SHAREDKEY;
+ send_authentication_request(priv, auth, NULL, 0);
}
break;
@@ -3541,12 +3558,15 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->station_was_associated = priv->station_is_associated;
atmel_enter_state(priv, STATION_STATE_READY);
} else {
+ int auth = C80211_MGMT_AAN_OPENSYSTEM;
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->CurrentAuthentTransactionSeqNum = 0x0001;
- send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
+ if (priv->wep_is_on && priv->exclude_unencrypted)
+ auth = C80211_MGMT_AAN_SHAREDKEY;
+ send_authentication_request(priv, auth, NULL, 0);
}
return;
}
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 8bc0b528548f..f8f4503475f9 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -877,7 +877,6 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777),
PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000),
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b),
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612),
@@ -891,6 +890,10 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
+ PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL",
+ 0x74c5e40d),
+ PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil",
+ 0x4b801a17),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
0x7a954bd9, 0x74be00c6),
PCMCIA_DEVICE_PROD_ID1234(
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 14beab4bc91c..287676ad80df 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4616,9 +4616,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
}
default:
- IPW_ERROR("Unknown notification: "
- "subtype=%d,flags=0x%2x,size=%d\n",
- notif->subtype, notif->flags, notif->size);
+ IPW_DEBUG_NOTIF("Unknown notification: "
+ "subtype=%d,flags=0x%2x,size=%d\n",
+ notif->subtype, notif->flags, notif->size);
}
}
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 3c128b692bce..ec6f2a48895b 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -590,6 +590,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
+ PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index c5cd61c7f927..e5bb9f5ae429 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -748,7 +748,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
if (essid->length) {
dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */
/* if it is to big, trunk it */
- dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length);
+ dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length);
} else {
dwrq->flags = 0;
dwrq->length = 0;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index cf373625fc70..98122f3a4bc2 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -950,16 +950,8 @@ wv_82593_cmd(struct net_device * dev,
static inline int
wv_diag(struct net_device * dev)
{
- int ret = FALSE;
-
- if(wv_82593_cmd(dev, "wv_diag(): diagnose",
- OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED))
- ret = TRUE;
-
-#ifdef DEBUG_CONFIG_ERRORS
- printk(KERN_INFO "wavelan_cs: i82593 Self Test failed!\n");
-#endif
- return(ret);
+ return(wv_82593_cmd(dev, "wv_diag(): diagnose",
+ OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED));
} /* wv_diag */
/*------------------------------------------------------------------*/
@@ -3604,8 +3596,8 @@ wv_82593_config(struct net_device * dev)
cfblk.lin_prio = 0; /* conform to 802.3 backoff algoritm */
cfblk.exp_prio = 5; /* conform to 802.3 backoff algoritm */
cfblk.bof_met = 1; /* conform to 802.3 backoff algoritm */
- cfblk.ifrm_spc = 0x20; /* 32 bit times interframe spacing */
- cfblk.slottim_low = 0x20; /* 32 bit times slot time */
+ cfblk.ifrm_spc = 0x20 >> 4; /* 32 bit times interframe spacing */
+ cfblk.slottim_low = 0x20 >> 5; /* 32 bit times slot time */
cfblk.slottim_hi = 0x0;
cfblk.max_retr = 15;
cfblk.prmisc = ((lp->promiscuous) ? TRUE: FALSE); /* Promiscuous mode */
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 9e0229f7e25f..93f8a8fa8890 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -40,6 +40,8 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/byteorder.h>
#include <asm/cache.h> /* for L1_CACHE_BYTES */
@@ -1019,62 +1021,33 @@ static struct hppa_dma_ops ccio_ops = {
};
#ifdef CONFIG_PROC_FS
-static int proc_append(char *src, int len, char **dst, off_t *offset, int *max)
-{
- if (len < *offset) {
- *offset -= len;
- return 0;
- }
- if (*offset > 0) {
- src += *offset;
- len -= *offset;
- *offset = 0;
- }
- if (len > *max) {
- len = *max;
- }
- memcpy(*dst, src, len);
- *dst += len;
- *max -= len;
- return (*max == 0);
-}
-
-static int ccio_proc_info(char *buf, char **start, off_t offset, int count,
- int *eof, void *data)
+static int ccio_proc_info(struct seq_file *m, void *p)
{
- int max = count;
- char tmp[80]; /* width of an ANSI-standard terminal */
+ int len = 0;
struct ioc *ioc = ioc_list;
while (ioc != NULL) {
unsigned int total_pages = ioc->res_size << 3;
unsigned long avg = 0, min, max;
- int j, len;
+ int j;
- len = sprintf(tmp, "%s\n", ioc->name);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "%s\n", ioc->name);
- len = sprintf(tmp, "Cujo 2.0 bug : %s\n",
- (ioc->cujo20_bug ? "yes" : "no"));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "Cujo 2.0 bug : %s\n",
+ (ioc->cujo20_bug ? "yes" : "no"));
- len = sprintf(tmp, "IO PDIR size : %d bytes (%d entries)\n",
- total_pages * 8, total_pages);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n",
+ total_pages * 8, total_pages);
+
#ifdef CCIO_MAP_STATS
- len = sprintf(tmp, "IO PDIR entries : %ld free %ld used (%d%%)\n",
- total_pages - ioc->used_pages, ioc->used_pages,
- (int)(ioc->used_pages * 100 / total_pages));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n",
+ total_pages - ioc->used_pages, ioc->used_pages,
+ (int)(ioc->used_pages * 100 / total_pages));
#endif
- len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n",
- ioc->res_size, total_pages);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+
+ len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n",
+ ioc->res_size, total_pages);
+
#ifdef CCIO_SEARCH_TIME
min = max = ioc->avg_search[0];
for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) {
@@ -1085,70 +1058,83 @@ static int ccio_proc_info(char *buf, char **start, off_t offset, int count,
min = ioc->avg_search[j];
}
avg /= CCIO_SEARCH_SAMPLE;
- len = sprintf(tmp, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
- min, avg, max);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+ min, avg, max);
#endif
#ifdef CCIO_MAP_STATS
- len = sprintf(tmp, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
- ioc->msingle_calls, ioc->msingle_pages,
- (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
-
+ len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
+ ioc->msingle_calls, ioc->msingle_pages,
+ (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
/* KLUGE - unmap_sg calls unmap_single for each mapped page */
min = ioc->usingle_calls - ioc->usg_calls;
max = ioc->usingle_pages - ioc->usg_pages;
- len = sprintf(tmp, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
- min, max, (int)((max * 1000)/min));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
+ min, max, (int)((max * 1000)/min));
- len = sprintf(tmp, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
- ioc->msg_calls, ioc->msg_pages,
- (int)((ioc->msg_pages * 1000)/ioc->msg_calls));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
- len = sprintf(tmp, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n",
- ioc->usg_calls, ioc->usg_pages,
- (int)((ioc->usg_pages * 1000)/ioc->usg_calls));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
+ ioc->msg_calls, ioc->msg_pages,
+ (int)((ioc->msg_pages * 1000)/ioc->msg_calls));
+
+ len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n",
+ ioc->usg_calls, ioc->usg_pages,
+ (int)((ioc->usg_pages * 1000)/ioc->usg_calls));
#endif /* CCIO_MAP_STATS */
+
ioc = ioc->next;
}
- if (count == 0) {
- *eof = 1;
- }
- return (max - count);
+ return 0;
+}
+
+static int ccio_proc_info_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, &ccio_proc_info, NULL);
}
-static int ccio_resource_map(char *buf, char **start, off_t offset, int len,
- int *eof, void *data)
+static struct file_operations ccio_proc_info_fops = {
+ .owner = THIS_MODULE,
+ .open = ccio_proc_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int ccio_proc_bitmap_info(struct seq_file *m, void *p)
{
+ int len = 0;
struct ioc *ioc = ioc_list;
- buf[0] = '\0';
while (ioc != NULL) {
u32 *res_ptr = (u32 *)ioc->res_map;
int j;
for (j = 0; j < (ioc->res_size / sizeof(u32)); j++) {
if ((j & 7) == 0)
- strcat(buf,"\n ");
- sprintf(buf, "%s %08x", buf, *res_ptr);
+ len += seq_puts(m, "\n ");
+ len += seq_printf(m, "%08x", *res_ptr);
res_ptr++;
}
- strcat(buf, "\n\n");
+ len += seq_puts(m, "\n\n");
ioc = ioc->next;
break; /* XXX - remove me */
}
- return strlen(buf);
+ return 0;
}
+
+static int ccio_proc_bitmap_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, &ccio_proc_bitmap_info, NULL);
+}
+
+static struct file_operations ccio_proc_bitmap_fops = {
+ .owner = THIS_MODULE,
+ .open = ccio_proc_bitmap_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif
/**
@@ -1423,7 +1409,7 @@ static void __init ccio_init_resources(struct ioc *ioc)
struct resource *res = ioc->mmio_region;
char *name = kmalloc(14, GFP_KERNEL);
- sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
+ snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path);
ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
@@ -1556,13 +1542,13 @@ static int ccio_probe(struct parisc_device *dev)
{
int i;
struct ioc *ioc, **ioc_p = &ioc_list;
+ struct proc_dir_entry *info_entry, *bitmap_entry;
- ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL);
+ ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
if (ioc == NULL) {
printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
return 1;
}
- memset(ioc, 0, sizeof(struct ioc));
ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
@@ -1578,19 +1564,20 @@ static int ccio_probe(struct parisc_device *dev)
ccio_ioc_init(ioc);
ccio_init_resources(ioc);
hppa_dma_ops = &ccio_ops;
- dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
+ dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
/* if this fails, no I/O cards will work, so may as well bug */
BUG_ON(dev->dev.platform_data == NULL);
HBA_DATA(dev->dev.platform_data)->iommu = ioc;
-
if (ioc_count == 0) {
- /* FIXME: Create separate entries for each ioc */
- create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root,
- ccio_proc_info, NULL);
- create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU,
- proc_runway_root, ccio_resource_map, NULL);
+ info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root);
+ if (info_entry)
+ info_entry->proc_fops = &ccio_proc_info_fops;
+
+ bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root);
+ if (bitmap_entry)
+ bitmap_entry->proc_fops = &ccio_proc_bitmap_fops;
}
ioc_count++;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 216d1d859326..3d1a7f98c676 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -989,14 +989,12 @@ static int __init dino_probe(struct parisc_device *dev)
*/
}
- dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL);
+ dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL);
if (!dino_dev) {
printk("dino_init_chip - couldn't alloc dino_device\n");
return 1;
}
- memset(dino_dev, 0, sizeof(struct dino_device));
-
dino_dev->hba.dev = dev;
dino_dev->hba.base_addr = ioremap(hpa, 4096);
dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 5edf93f80757..07dc2b6d4e93 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -60,12 +60,11 @@ static int hppb_probe(struct parisc_device *dev)
}
if(card->hpa) {
- card->next = kmalloc(sizeof(struct hppb_card), GFP_KERNEL);
+ card->next = kzalloc(sizeof(struct hppb_card), GFP_KERNEL);
if(!card->next) {
printk(KERN_ERR "HP-PB: Unable to allocate memory.\n");
return 1;
}
- memset(card->next, '\0', sizeof(struct hppb_card));
card = card->next;
}
printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 19657efa8dc3..8d7a36392eb8 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -873,28 +873,24 @@ void *iosapic_register(unsigned long hpa)
return NULL;
}
- isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+ isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
if (!isi) {
BUG();
return NULL;
}
- memset(isi, 0, sizeof(struct iosapic_info));
-
isi->addr = ioremap(hpa, 4096);
isi->isi_hpa = hpa;
isi->isi_version = iosapic_rd_version(isi);
isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
vip = isi->isi_vector = (struct vector_info *)
- kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
+ kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
if (vip == NULL) {
kfree(isi);
return NULL;
}
- memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
-
for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
vip->irqline = (unsigned char) cnt;
vip->iosapic = isi;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 2b3ba1dcf332..cb3d28176129 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -166,11 +166,12 @@ static void lasi_power_off(void)
int __init
lasi_init_chip(struct parisc_device *dev)
{
+ extern void (*chassis_power_off)(void);
struct gsc_asic *lasi;
struct gsc_irq gsc_irq;
int ret;
- lasi = kmalloc(sizeof(*lasi), GFP_KERNEL);
+ lasi = kzalloc(sizeof(*lasi), GFP_KERNEL);
if (!lasi)
return -ENOMEM;
@@ -222,7 +223,7 @@ lasi_init_chip(struct parisc_device *dev)
* ensure that only the first LASI (the one controlling the power off)
* should set the HPA here */
lasi_power_off_hpa = lasi->hpa;
- pm_power_off = lasi_power_off;
+ chassis_power_off = lasi_power_off;
return ret;
}
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index cbae8c8963fa..e8a2a4a852f5 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1565,7 +1565,7 @@ lba_driver_probe(struct parisc_device *dev)
} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
func_class &= 0xff;
version = kmalloc(6, GFP_KERNEL);
- sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf));
+ snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf));
/* We could use one printk for both Elroy and Mercury,
* but for the mask for func_class.
*/
@@ -1586,14 +1586,12 @@ lba_driver_probe(struct parisc_device *dev)
** have an IRT entry will get NULL back from iosapic code.
*/
- lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
+ lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL);
if (!lba_dev) {
printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
return(1);
}
- memset(lba_dev, 0, sizeof(struct lba_device));
-
/* ---------- First : initialize data we already have --------- */
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 42a3c54e8e6c..a28e17898fbd 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -1,7 +1,7 @@
/*
* Interfaces to retrieve and set PDC Stable options (firmware)
*
- * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (C) 2005-2006 Thibaut VARENE <varenet@parisc-linux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,11 +26,19 @@
*
* Since locations between 96 and 192 are the various paths, most (if not
* all) PA-RISC machines should have them. Anyway, for safety reasons, the
- * following code can deal with only 96 bytes of Stable Storage, and all
+ * following code can deal with just 96 bytes of Stable Storage, and all
* sizes between 96 and 192 bytes (provided they are multiple of struct
* device_path size, eg: 128, 160 and 192) to provide full information.
* The code makes no use of data above 192 bytes. One last word: there's one
* path we can always count on: the primary path.
+ *
+ * The current policy wrt file permissions is:
+ * - write: root only
+ * - read: (reading triggers PDC calls) ? root only : everyone
+ * The rationale is that PDC calls could hog (DoS) the machine.
+ *
+ * TODO:
+ * - timer/fastsize write calls
*/
#undef PDCS_DEBUG
@@ -50,13 +58,15 @@
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/spinlock.h>
#include <asm/pdc.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
-#define PDCS_VERSION "0.10"
+#define PDCS_VERSION "0.22"
+#define PDCS_PREFIX "PDC Stable Storage"
#define PDCS_ADDR_PPRI 0x00
#define PDCS_ADDR_OSID 0x40
@@ -70,10 +80,12 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
MODULE_LICENSE("GPL");
MODULE_VERSION(PDCS_VERSION);
+/* holds Stable Storage size. Initialized once and for all, no lock needed */
static unsigned long pdcs_size __read_mostly;
/* This struct defines what we need to deal with a parisc pdc path entry */
struct pdcspath_entry {
+ rwlock_t rw_lock; /* to protect path entry access */
short ready; /* entry record is valid if != 0 */
unsigned long addr; /* entry address in stable storage */
char *name; /* entry name */
@@ -121,6 +133,8 @@ struct pdcspath_attribute paths_attr_##_name = { \
* content of the stable storage WRT various paths in these structs. We read
* these structs when reading the files, and we will write to these structs when
* writing to the files, and only then write them back to the Stable Storage.
+ *
+ * This function expects to be called with @entry->rw_lock write-hold.
*/
static int
pdcspath_fetch(struct pdcspath_entry *entry)
@@ -160,14 +174,15 @@ pdcspath_fetch(struct pdcspath_entry *entry)
* pointer, from which it'll find out the corresponding hardware path.
* For now we do not handle the case where there's an error in writing to the
* Stable Storage area, so you'd better not mess up the data :P
+ *
+ * This function expects to be called with @entry->rw_lock write-hold.
*/
-static int
+static void
pdcspath_store(struct pdcspath_entry *entry)
{
struct device_path *devpath;
- if (!entry)
- return -EINVAL;
+ BUG_ON(!entry);
devpath = &entry->devpath;
@@ -176,10 +191,8 @@ pdcspath_store(struct pdcspath_entry *entry)
First case, we don't have a preset hwpath... */
if (!entry->ready) {
/* ...but we have a device, map it */
- if (entry->dev)
- device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
- else
- return -EINVAL;
+ BUG_ON(!entry->dev);
+ device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
}
/* else, we expect the provided hwpath to be valid. */
@@ -191,15 +204,13 @@ pdcspath_store(struct pdcspath_entry *entry)
printk(KERN_ERR "%s: an error occured when writing to PDC.\n"
"It is likely that the Stable Storage data has been corrupted.\n"
"Please check it carefully upon next reboot.\n", __func__);
- return -EIO;
+ WARN_ON(1);
}
/* kobject is already registered */
entry->ready = 2;
DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
-
- return 0;
}
/**
@@ -214,14 +225,17 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf)
{
char *out = buf;
struct device_path *devpath;
- unsigned short i;
+ short i;
if (!entry || !buf)
return -EINVAL;
+ read_lock(&entry->rw_lock);
devpath = &entry->devpath;
+ i = entry->ready;
+ read_unlock(&entry->rw_lock);
- if (!entry->ready)
+ if (!i) /* entry is not ready */
return -ENODATA;
for (i = 0; i < 6; i++) {
@@ -242,7 +256,7 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf)
*
* We will call this function to change the current hardware path.
* Hardware paths are to be given '/'-delimited, without brackets.
- * We take care to make sure that the provided path actually maps to an existing
+ * We make sure that the provided path actually maps to an existing
* device, BUT nothing would prevent some foolish user to set the path to some
* PCI bridge or even a CPU...
* A better work around would be to make sure we are at the end of a device tree
@@ -298,17 +312,19 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun
}
/* So far so good, let's get in deep */
+ write_lock(&entry->rw_lock);
entry->ready = 0;
entry->dev = dev;
/* Now, dive in. Write back to the hardware */
- WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */
+ pdcspath_store(entry);
/* Update the symlink to the real device */
sysfs_remove_link(&entry->kobj, "device");
sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ write_unlock(&entry->rw_lock);
- printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n",
+ printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n",
entry->name, buf);
return count;
@@ -326,14 +342,17 @@ pdcspath_layer_read(struct pdcspath_entry *entry, char *buf)
{
char *out = buf;
struct device_path *devpath;
- unsigned short i;
+ short i;
if (!entry || !buf)
return -EINVAL;
+ read_lock(&entry->rw_lock);
devpath = &entry->devpath;
+ i = entry->ready;
+ read_unlock(&entry->rw_lock);
- if (!entry->ready)
+ if (!i) /* entry is not ready */
return -ENODATA;
for (i = 0; devpath->layers[i] && (likely(i < 6)); i++)
@@ -388,15 +407,17 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count
}
/* So far so good, let's get in deep */
+ write_lock(&entry->rw_lock);
/* First, overwrite the current layers with the new ones, not touching
the hardware path. */
memcpy(&entry->devpath.layers, &layers, sizeof(layers));
/* Now, dive in. Write back to the hardware */
- WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */
+ pdcspath_store(entry);
+ write_unlock(&entry->rw_lock);
- printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n",
+ printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" layers to \"%s\"\n",
entry->name, buf);
return count;
@@ -415,9 +436,6 @@ pdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
ssize_t ret = 0;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
if (pdcs_attr->show)
ret = pdcs_attr->show(entry, buf);
@@ -454,8 +472,8 @@ static struct sysfs_ops pdcspath_attr_ops = {
};
/* These are the two attributes of any PDC path. */
-static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write);
-static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write);
+static PATHS_ATTR(hwpath, 0644, pdcspath_hwpath_read, pdcspath_hwpath_write);
+static PATHS_ATTR(layer, 0644, pdcspath_layer_read, pdcspath_layer_write);
static struct attribute *paths_subsys_attrs[] = {
&paths_attr_hwpath.attr,
@@ -484,36 +502,119 @@ static struct pdcspath_entry *pdcspath_entries[] = {
NULL,
};
+
+/* For more insight of what's going on here, refer to PDC Procedures doc,
+ * Section PDC_STABLE */
+
/**
- * pdcs_info_read - Pretty printing of the remaining useful data.
+ * pdcs_size_read - Stable Storage size output.
* @entry: An allocated and populated subsytem struct. We don't use it tho.
* @buf: The output buffer to write to.
- *
- * We will call this function to format the output of the 'info' attribute file.
- * Please refer to PDC Procedures documentation, section PDC_STABLE to get a
- * better insight of what we're doing here.
*/
static ssize_t
-pdcs_info_read(struct subsystem *entry, char *buf)
+pdcs_size_read(struct subsystem *entry, char *buf)
{
char *out = buf;
- __u32 result;
- struct device_path devpath;
- char *tmpstr = NULL;
if (!entry || !buf)
return -EINVAL;
/* show the size of the stable storage */
- out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size);
+ out += sprintf(out, "%ld\n", pdcs_size);
- /* deal with flags */
- if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK)
- return -EIO;
+ return out - buf;
+}
+
+/**
+ * pdcs_auto_read - Stable Storage autoboot/search flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
+ */
+static ssize_t
+pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
+{
+ char *out = buf;
+ struct pdcspath_entry *pathentry;
- out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off");
- out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off");
- out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0);
+ if (!entry || !buf)
+ return -EINVAL;
+
+ /* Current flags are stored in primary boot path entry */
+ pathentry = &pdcspath_entry_primary;
+
+ read_lock(&pathentry->rw_lock);
+ out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ?
+ "On" : "Off");
+ read_unlock(&pathentry->rw_lock);
+
+ return out - buf;
+}
+
+/**
+ * pdcs_autoboot_read - Stable Storage autoboot flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static inline ssize_t
+pdcs_autoboot_read(struct subsystem *entry, char *buf)
+{
+ return pdcs_auto_read(entry, buf, PF_AUTOBOOT);
+}
+
+/**
+ * pdcs_autosearch_read - Stable Storage autoboot flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static inline ssize_t
+pdcs_autosearch_read(struct subsystem *entry, char *buf)
+{
+ return pdcs_auto_read(entry, buf, PF_AUTOSEARCH);
+}
+
+/**
+ * pdcs_timer_read - Stable Storage timer count output (in seconds).
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * The value of the timer field correponds to a number of seconds in powers of 2.
+ */
+static ssize_t
+pdcs_timer_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ struct pdcspath_entry *pathentry;
+
+ if (!entry || !buf)
+ return -EINVAL;
+
+ /* Current flags are stored in primary boot path entry */
+ pathentry = &pdcspath_entry_primary;
+
+ /* print the timer value in seconds */
+ read_lock(&pathentry->rw_lock);
+ out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ?
+ (1 << (pathentry->devpath.flags & PF_TIMER)) : 0);
+ read_unlock(&pathentry->rw_lock);
+
+ return out - buf;
+}
+
+/**
+ * pdcs_osid_read - Stable Storage OS ID register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static ssize_t
+pdcs_osid_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ __u32 result;
+ char *tmpstr = NULL;
+
+ if (!entry || !buf)
+ return -EINVAL;
/* get OSID */
if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
@@ -529,13 +630,31 @@ pdcs_info_read(struct subsystem *entry, char *buf)
case 0x0005: tmpstr = "Novell Netware dependent data"; break;
default: tmpstr = "Unknown"; break;
}
- out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16));
+ out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16));
+
+ return out - buf;
+}
+
+/**
+ * pdcs_fastsize_read - Stable Storage FastSize register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * This register holds the amount of system RAM to be tested during boot sequence.
+ */
+static ssize_t
+pdcs_fastsize_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ __u32 result;
+
+ if (!entry || !buf)
+ return -EINVAL;
/* get fast-size */
if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK)
return -EIO;
- out += sprintf(out, "Memory tested: ");
if ((result & 0x0F) < 0x0E)
out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256);
else
@@ -546,22 +665,18 @@ pdcs_info_read(struct subsystem *entry, char *buf)
}
/**
- * pdcs_info_write - This function handles boot flag modifying.
+ * pdcs_auto_write - This function handles autoboot/search flag modifying.
* @entry: An allocated and populated subsytem struct. We don't use it tho.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
+ * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
*
- * We will call this function to change the current boot flags.
+ * We will call this function to change the current autoboot flag.
* We expect a precise syntax:
- * \"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch
- *
- * As of now there is no incentive on my side to provide more "knobs" to that
- * interface, since modifying the rest of the data is pretty meaningless when
- * the machine is running and for the expected use of that facility, such as
- * PALO setting up the boot disk when installing a Linux distribution...
+ * \"n\" (n == 0 or 1) to toggle AutoBoot Off or On
*/
static ssize_t
-pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob)
{
struct pdcspath_entry *pathentry;
unsigned char flags;
@@ -582,7 +697,9 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
pathentry = &pdcspath_entry_primary;
/* Be nice to the existing flag record */
+ read_lock(&pathentry->rw_lock);
flags = pathentry->devpath.flags;
+ read_unlock(&pathentry->rw_lock);
DPRINTK("%s: flags before: 0x%X\n", __func__, flags);
@@ -595,50 +712,85 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
if ((c != 0) && (c != 1))
goto parse_error;
if (c == 0)
- flags &= ~PF_AUTOBOOT;
+ flags &= ~knob;
else
- flags |= PF_AUTOBOOT;
-
- if (*temp++ != ' ')
- goto parse_error;
-
- c = *temp++ - '0';
- if ((c != 0) && (c != 1))
- goto parse_error;
- if (c == 0)
- flags &= ~PF_AUTOSEARCH;
- else
- flags |= PF_AUTOSEARCH;
+ flags |= knob;
DPRINTK("%s: flags after: 0x%X\n", __func__, flags);
/* So far so good, let's get in deep */
+ write_lock(&pathentry->rw_lock);
/* Change the path entry flags first */
pathentry->devpath.flags = flags;
/* Now, dive in. Write back to the hardware */
- WARN_ON(pdcspath_store(pathentry)); /* this warn should *NEVER* happen */
+ pdcspath_store(pathentry);
+ write_unlock(&pathentry->rw_lock);
- printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf);
+ printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" to \"%s\"\n",
+ (knob & PF_AUTOBOOT) ? "autoboot" : "autosearch",
+ (flags & knob) ? "On" : "Off");
return count;
parse_error:
- printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__);
+ printk(KERN_WARNING "%s: Parse error: expect \"n\" (n == 0 or 1)\n", __func__);
return -EINVAL;
}
-/* The last attribute (the 'root' one actually) with all remaining data. */
-static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write);
+/**
+ * pdcs_autoboot_write - This function handles autoboot flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On
+ */
+static inline ssize_t
+pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count)
+{
+ return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT);
+}
+
+/**
+ * pdcs_autosearch_write - This function handles autosearch flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On
+ */
+static inline ssize_t
+pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
+{
+ return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
+}
+
+/* The remaining attributes. */
+static PDCS_ATTR(size, 0444, pdcs_size_read, NULL);
+static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write);
+static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write);
+static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL);
+static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL);
+static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL);
static struct subsys_attribute *pdcs_subsys_attrs[] = {
- &pdcs_attr_info,
- NULL, /* maybe more in the future? */
+ &pdcs_attr_size,
+ &pdcs_attr_autoboot,
+ &pdcs_attr_autosearch,
+ &pdcs_attr_timer,
+ &pdcs_attr_osid,
+ &pdcs_attr_fastsize,
+ NULL,
};
static decl_subsys(paths, &ktype_pdcspath, NULL);
-static decl_subsys(pdc, NULL, NULL);
+static decl_subsys(stable, NULL, NULL);
/**
* pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage.
@@ -656,8 +808,16 @@ pdcs_register_pathentries(void)
struct pdcspath_entry *entry;
int err;
+ /* Initialize the entries rw_lock before anything else */
+ for (i = 0; (entry = pdcspath_entries[i]); i++)
+ rwlock_init(&entry->rw_lock);
+
for (i = 0; (entry = pdcspath_entries[i]); i++) {
- if (pdcspath_fetch(entry) < 0)
+ write_lock(&entry->rw_lock);
+ err = pdcspath_fetch(entry);
+ write_unlock(&entry->rw_lock);
+
+ if (err < 0)
continue;
if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
@@ -667,13 +827,14 @@ pdcs_register_pathentries(void)
return err;
/* kobject is now registered */
+ write_lock(&entry->rw_lock);
entry->ready = 2;
- if (!entry->dev)
- continue;
-
/* Add a nice symlink to the real device */
- sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ if (entry->dev)
+ sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+
+ write_unlock(&entry->rw_lock);
}
return 0;
@@ -688,14 +849,17 @@ pdcs_unregister_pathentries(void)
unsigned short i;
struct pdcspath_entry *entry;
- for (i = 0; (entry = pdcspath_entries[i]); i++)
+ for (i = 0; (entry = pdcspath_entries[i]); i++) {
+ read_lock(&entry->rw_lock);
if (entry->ready >= 2)
- kobject_unregister(&entry->kobj);
+ kobject_unregister(&entry->kobj);
+ read_unlock(&entry->rw_lock);
+ }
}
/*
- * For now we register the pdc subsystem with the firmware subsystem
- * and the paths subsystem with the pdc subsystem
+ * For now we register the stable subsystem with the firmware subsystem
+ * and the paths subsystem with the stable subsystem
*/
static int __init
pdc_stable_init(void)
@@ -707,19 +871,23 @@ pdc_stable_init(void)
if (pdc_stable_get_size(&pdcs_size) != PDC_OK)
return -ENODEV;
- printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION);
+ /* make sure we have enough data */
+ if (pdcs_size < 96)
+ return -ENODATA;
+
+ printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION);
- /* For now we'll register the pdc subsys within this driver */
- if ((rc = firmware_register(&pdc_subsys)))
+ /* For now we'll register the stable subsys within this driver */
+ if ((rc = firmware_register(&stable_subsys)))
goto fail_firmreg;
- /* Don't forget the info entry */
+ /* Don't forget the root entries */
for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
if (attr->show)
- error = subsys_create_file(&pdc_subsys, attr);
+ error = subsys_create_file(&stable_subsys, attr);
- /* register the paths subsys as a subsystem of pdc subsys */
- kset_set_kset_s(&paths_subsys, pdc_subsys);
+ /* register the paths subsys as a subsystem of stable subsys */
+ kset_set_kset_s(&paths_subsys, stable_subsys);
if ((rc= subsystem_register(&paths_subsys)))
goto fail_subsysreg;
@@ -734,10 +902,10 @@ fail_pdcsreg:
subsystem_unregister(&paths_subsys);
fail_subsysreg:
- firmware_unregister(&pdc_subsys);
+ firmware_unregister(&stable_subsys);
fail_firmreg:
- printk(KERN_INFO "PDC Stable Storage bailing out\n");
+ printk(KERN_INFO PDCS_PREFIX " bailing out\n");
return rc;
}
@@ -747,7 +915,7 @@ pdc_stable_exit(void)
pdcs_unregister_pathentries();
subsystem_unregister(&paths_subsys);
- firmware_unregister(&pdc_subsys);
+ firmware_unregister(&stable_subsys);
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index c85653f315aa..5d47c5965c51 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -37,6 +37,8 @@
#include <asm/hardware.h> /* for register_parisc_driver() stuff */
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
#include <asm/runway.h> /* for proc_runway_root */
#include <asm/pdc.h> /* for PDC_MODEL_* */
#include <asm/pdcpat.h> /* for is_pdc_pat() */
@@ -1892,46 +1894,43 @@ sba_common_init(struct sba_device *sba_dev)
}
#ifdef CONFIG_PROC_FS
-static int sba_proc_info(char *buf, char **start, off_t offset, int len)
+static int sba_proc_info(struct seq_file *m, void *p)
{
struct sba_device *sba_dev = sba_list;
struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */
int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
- unsigned long i;
#ifdef SBA_COLLECT_STATS
unsigned long avg = 0, min, max;
#endif
+ int i, len = 0;
- sprintf(buf, "%s rev %d.%d\n",
+ len += seq_printf(m, "%s rev %d.%d\n",
sba_dev->name,
(sba_dev->hw_rev & 0x7) + 1,
(sba_dev->hw_rev & 0x18) >> 3
);
- sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n",
- buf,
+ len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n",
(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */
total_pages);
- sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
- buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
+ len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n",
+ ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
- sprintf(buf, "%sLMMIO_BASE/MASK/ROUTE %08x %08x %08x\n",
- buf,
+ len += seq_printf(m, "LMMIO_BASE/MASK/ROUTE %08x %08x %08x\n",
READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_BASE),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_MASK),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_ROUTE)
);
for (i=0; i<4; i++)
- sprintf(buf, "%sDIR%ld_BASE/MASK/ROUTE %08x %08x %08x\n",
- buf, i,
+ len += seq_printf(m, "DIR%d_BASE/MASK/ROUTE %08x %08x %08x\n", i,
READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_BASE + i*0x18),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_MASK + i*0x18),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_ROUTE + i*0x18)
);
#ifdef SBA_COLLECT_STATS
- sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf,
+ len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n",
total_pages - ioc->used_pages, ioc->used_pages,
(int) (ioc->used_pages * 100 / total_pages));
@@ -1942,53 +1941,76 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len)
if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
}
avg /= SBA_SEARCH_SAMPLE;
- sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
- buf, min, avg, max);
+ len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+ min, avg, max);
- sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n",
- buf, ioc->msingle_calls, ioc->msingle_pages,
+ len += seq_printf(m, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n",
+ ioc->msingle_calls, ioc->msingle_pages,
(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
/* KLUGE - unmap_sg calls unmap_single for each mapped page */
min = ioc->usingle_calls;
max = ioc->usingle_pages - ioc->usg_pages;
- sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n",
- buf, min, max,
- (int) ((max * 1000)/min));
+ len += seq_printf(m, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n",
+ min, max, (int) ((max * 1000)/min));
- sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
- buf, ioc->msg_calls, ioc->msg_pages,
+ len += seq_printf(m, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
+ ioc->msg_calls, ioc->msg_pages,
(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
- sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
- buf, ioc->usg_calls, ioc->usg_pages,
+ len += seq_printf(m, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
+ ioc->usg_calls, ioc->usg_pages,
(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
#endif
- return strlen(buf);
+ return 0;
}
-#if 0
-/* XXX too much output - exceeds 4k limit and needs to be re-written */
static int
-sba_resource_map(char *buf, char **start, off_t offset, int len)
+sba_proc_open(struct inode *i, struct file *f)
+{
+ return single_open(f, &sba_proc_info, NULL);
+}
+
+static struct file_operations sba_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = sba_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int
+sba_proc_bitmap_info(struct seq_file *m, void *p)
{
struct sba_device *sba_dev = sba_list;
- struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Mutli-IOC suppoer! */
+ struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */
unsigned int *res_ptr = (unsigned int *)ioc->res_map;
- int i;
+ int i, len = 0;
- buf[0] = '\0';
- for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) {
+ for (i = 0; i < (ioc->res_size/sizeof(unsigned int)); ++i, ++res_ptr) {
if ((i & 7) == 0)
- strcat(buf,"\n ");
- sprintf(buf, "%s %08x", buf, *res_ptr);
+ len += seq_printf(m, "\n ");
+ len += seq_printf(m, " %08x", *res_ptr);
}
- strcat(buf, "\n");
+ len += seq_printf(m, "\n");
- return strlen(buf);
+ return 0;
}
-#endif /* 0 */
+
+static int
+sba_proc_bitmap_open(struct inode *i, struct file *f)
+{
+ return single_open(f, &sba_proc_bitmap_info, NULL);
+}
+
+static struct file_operations sba_proc_bitmap_fops = {
+ .owner = THIS_MODULE,
+ .open = sba_proc_bitmap_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif /* CONFIG_PROC_FS */
static struct parisc_device_id sba_tbl[] = {
@@ -2021,6 +2043,7 @@ sba_driver_callback(struct parisc_device *dev)
int i;
char *version;
void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
+ struct proc_dir_entry *info_entry, *bitmap_entry, *root;
sba_dump_ranges(sba_addr);
@@ -2064,14 +2087,13 @@ sba_driver_callback(struct parisc_device *dev)
printk(KERN_INFO "%s found %s at 0x%lx\n",
MODULE_NAME, version, dev->hpa.start);
- sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
+ sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL);
if (!sba_dev) {
printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
return -ENOMEM;
}
parisc_set_drvdata(dev, sba_dev);
- memset(sba_dev, 0, sizeof(struct sba_device));
for(i=0; i<MAX_IOC; i++)
spin_lock_init(&(sba_dev->ioc[i].res_lock));
@@ -2089,19 +2111,27 @@ sba_driver_callback(struct parisc_device *dev)
hppa_dma_ops = &sba_ops;
#ifdef CONFIG_PROC_FS
- if (IS_ASTRO(&dev->id)) {
- create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info);
- } else if (IS_IKE(&dev->id)) {
- create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info);
- } else if (IS_PLUTO(&dev->id)) {
- create_proc_info_entry("Pluto", 0, proc_mckinley_root, sba_proc_info);
- } else {
- create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info);
+ switch (dev->id.hversion) {
+ case PLUTO_MCKINLEY_PORT:
+ root = proc_mckinley_root;
+ break;
+ case ASTRO_RUNWAY_PORT:
+ case IKE_MERCED_PORT:
+ default:
+ root = proc_runway_root;
+ break;
}
-#if 0
- create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map);
-#endif
+
+ info_entry = create_proc_entry("sba_iommu", 0, root);
+ bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root);
+
+ if (info_entry)
+ info_entry->proc_fops = &sba_proc_fops;
+
+ if (bitmap_entry)
+ bitmap_entry->proc_fops = &sba_proc_bitmap_fops;
#endif
+
parisc_vmerge_boundary = IOVP_SIZE;
parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG;
parisc_has_iommu();
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index d14888e149bb..ba971fecd0d8 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -89,6 +89,9 @@ static struct superio_device sio_dev;
#define DBG_INIT(x...)
#endif
+#define SUPERIO "SuperIO"
+#define PFX SUPERIO ": "
+
static irqreturn_t
superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
{
@@ -117,7 +120,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
local_irq = results & 0x0f;
if (local_irq == 2 || local_irq > 7) {
- printk(KERN_ERR "SuperIO: slave interrupted!\n");
+ printk(KERN_ERR PFX "slave interrupted!\n");
return IRQ_HANDLED;
}
@@ -128,7 +131,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
outb(OCW3_ISR,IC_PIC1+0);
results = inb(IC_PIC1+0);
if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */
- printk(KERN_WARNING "SuperIO: spurious interrupt!\n");
+ printk(KERN_WARNING PFX "spurious interrupt!\n");
return IRQ_HANDLED;
}
}
@@ -163,27 +166,27 @@ superio_init(struct pci_dev *pcidev)
/* ...then properly fixup the USB to point at suckyio PIC */
sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
- printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
+ printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
pci_name(pdev), pdev->irq);
pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
sio->sp1_base &= ~1;
- printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base);
+ printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base);
pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base);
sio->sp2_base &= ~1;
- printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base);
+ printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base);
pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base);
sio->pp_base &= ~1;
- printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base);
+ printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base);
pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base);
sio->fdc_base &= ~1;
- printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base);
+ printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base);
pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base);
sio->acpi_base &= ~1;
- printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base);
+ printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base);
request_region (IC_PIC1, 0x1f, "pic1");
request_region (IC_PIC2, 0x1f, "pic2");
@@ -263,14 +266,14 @@ superio_init(struct pci_dev *pcidev)
/* Setup USB power regulation */
outb(1, sio->acpi_base + USB_REG_CR);
if (inb(sio->acpi_base + USB_REG_CR) & 1)
- printk(KERN_INFO "SuperIO: USB regulator enabled\n");
+ printk(KERN_INFO PFX "USB regulator enabled\n");
else
- printk(KERN_ERR "USB regulator not initialized!\n");
+ printk(KERN_ERR PFX "USB regulator not initialized!\n");
if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT,
- "SuperIO", (void *)sio)) {
+ SUPERIO, (void *)sio)) {
- printk(KERN_ERR "SuperIO: could not get irq\n");
+ printk(KERN_ERR PFX "could not get irq\n");
BUG();
return;
}
@@ -284,7 +287,7 @@ static void superio_disable_irq(unsigned int irq)
u8 r8;
if ((irq < 1) || (irq == 2) || (irq > 7)) {
- printk(KERN_ERR "SuperIO: Illegal irq number.\n");
+ printk(KERN_ERR PFX "Illegal irq number.\n");
BUG();
return;
}
@@ -301,7 +304,7 @@ static void superio_enable_irq(unsigned int irq)
u8 r8;
if ((irq < 1) || (irq == 2) || (irq > 7)) {
- printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq);
+ printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq);
BUG();
return;
}
@@ -319,7 +322,7 @@ static unsigned int superio_startup_irq(unsigned int irq)
}
static struct hw_interrupt_type superio_interrupt_type = {
- .typename = "SuperIO",
+ .typename = SUPERIO,
.startup = superio_startup_irq,
.shutdown = superio_disable_irq,
.enable = superio_enable_irq,
@@ -413,7 +416,7 @@ static void __devinit superio_serial_init(void)
retval = early_serial_setup(&serial[0]);
if (retval < 0) {
- printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n");
+ printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
return;
}
@@ -423,7 +426,7 @@ static void __devinit superio_serial_init(void)
retval = early_serial_setup(&serial[1]);
if (retval < 0)
- printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n");
+ printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
#endif /* CONFIG_SERIAL_8250 */
}
@@ -437,7 +440,7 @@ static void __devinit superio_parport_init(void)
PARPORT_DMA_NONE /* dma */,
NULL /*struct pci_dev* */) )
- printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n");
+ printk(KERN_WARNING PFX "Probing parallel port failed.\n");
#endif /* CONFIG_PARPORT_PC */
}
@@ -499,7 +502,7 @@ static struct pci_device_id superio_tbl[] = {
};
static struct pci_driver superio_driver = {
- .name = "SuperIO",
+ .name = SUPERIO,
.id_table = superio_tbl,
.probe = superio_probe,
};
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index 17dce2adf7fe..813c2c24ab1e 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -76,7 +76,7 @@ wax_init_chip(struct parisc_device *dev)
struct gsc_irq gsc_irq;
int ret;
- wax = kmalloc(sizeof(*wax), GFP_KERNEL);
+ wax = kzalloc(sizeof(*wax), GFP_KERNEL);
if (!wax)
return -ENOMEM;
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index fde29a75f888..1de52d9febf9 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -249,7 +249,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
struct parport tmp;
struct parport *p = &tmp;
- priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
+ priv = kzalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
if (!priv) {
printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
return NULL;
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 166de3507780..10845253c9e0 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -312,8 +312,7 @@ static int __devinit parport_register (struct pci_dev *dev,
{
struct parport_pc_pci *card;
struct parport_serial_private *priv = pci_get_drvdata (dev);
- int i = id->driver_data, n;
- int success = 0;
+ int n, success = 0;
priv->par = cards[id->driver_data];
card = &priv->par;
@@ -344,10 +343,8 @@ static int __devinit parport_register (struct pci_dev *dev,
"hi" as an offset (see SYBA
def.) */
/* TODO: test if sharing interrupts works */
- printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
- "I/O at %#lx(%#lx)\n",
- parport_serial_pci_tbl[i].vendor,
- parport_serial_pci_tbl[i].device, io_lo, io_hi);
+ dev_dbg(&dev->dev, "PCI parallel port detected: I/O at "
+ "%#lx(%#lx)\n", io_lo, io_hi);
port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
PARPORT_DMA_NONE, dev);
if (port) {
@@ -359,7 +356,7 @@ static int __devinit parport_register (struct pci_dev *dev,
if (card->postinit_hook)
card->postinit_hook (dev, card, !success);
- return success ? 0 : 1;
+ return 0;
}
static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0a424a4e8187..bb96ce1db08c 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -352,11 +352,20 @@ static void pcmcia_release_dev(struct device *dev)
kfree(p_dev);
}
+static void pcmcia_add_pseudo_device(struct pcmcia_socket *s)
+{
+ if (!s->pcmcia_state.device_add_pending) {
+ s->pcmcia_state.device_add_pending = 1;
+ schedule_work(&s->device_add);
+ }
+ return;
+}
static int pcmcia_device_probe(struct device * dev)
{
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
+ struct pcmcia_device_id *did;
struct pcmcia_socket *s;
int ret = 0;
@@ -392,6 +401,19 @@ static int pcmcia_device_probe(struct device * dev)
}
ret = p_drv->probe(p_dev);
+ if (ret)
+ goto put_module;
+
+ /* handle pseudo multifunction devices:
+ * there are at most two pseudo multifunction devices.
+ * if we're matching against the first, schedule a
+ * call which will then check whether there are two
+ * pseudo devices, and if not, add the second one.
+ */
+ did = (struct pcmcia_device_id *) p_dev->dev.driver_data;
+ if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+ (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
+ pcmcia_add_pseudo_device(p_dev->socket);
put_module:
if (ret)
@@ -660,15 +682,6 @@ static void pcmcia_delayed_add_pseudo_device(void *data)
s->pcmcia_state.device_add_pending = 0;
}
-static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s)
-{
- if (!s->pcmcia_state.device_add_pending) {
- s->pcmcia_state.device_add_pending = 1;
- schedule_work(&s->device_add);
- }
- return;
-}
-
static int pcmcia_requery(struct device *dev, void * _data)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -755,15 +768,6 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
- /* handle pseudo multifunction devices:
- * there are at most two pseudo multifunction devices.
- * if we're matching against the first, schedule a
- * call which will then check whether there are two
- * pseudo devices, and if not, add the second one.
- */
- if (dev->device_no == 0)
- pcmcia_add_pseudo_device(dev->socket);
-
if (dev->device_no != did->device_no)
return 0;
}
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index aaa568a3806e..b68eef251614 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -303,13 +303,11 @@ found:
down_write(&dev->dev.bus->subsys.rwsem);
dev->card_link = clink;
dev->dev.driver = &drv->link.driver;
- if (drv->link.driver.probe) {
- if (drv->link.driver.probe(&dev->dev)) {
- dev->dev.driver = NULL;
- dev->card_link = NULL;
- up_write(&dev->dev.bus->subsys.rwsem);
- return NULL;
- }
+ if (pnp_bus_type.probe(&dev->dev)) {
+ dev->dev.driver = NULL;
+ dev->card_link = NULL;
+ up_write(&dev->dev.bus->subsys.rwsem);
+ return NULL;
}
device_bind_driver(&dev->dev);
up_write(&dev->dev.bus->subsys.rwsem);
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6912399d0937..6f50cc9323d9 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -55,21 +55,13 @@ config DASD_DIAG
Disks under VM. If you are not running under VM or unsure what it is,
say "N".
-config DASD_EER
- tristate "Extended error reporting (EER)"
- depends on DASD
- help
- This driver provides a character device interface to the
- DASD extended error reporting. This is only needed if you want to
- use applications written for the EER facility.
-
config DASD_CMB
tristate "Compatibility interface for DASD channel measurement blocks"
depends on DASD
help
- This driver provides an additional interface to the channel
- measurement facility, which is normally accessed though sysfs, with
- a set of ioctl functions specific to the dasd driver.
+ This driver provides an additional interface to the channel measurement
+ facility, which is normally accessed though sysfs, with a set of
+ ioctl functions specific to the dasd driver.
This is only needed if you want to use applications written for
linux-2.4 dasd channel measurement facility interface.
diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile
index 0c0d871e8f51..58c6780134f7 100644
--- a/drivers/s390/block/Makefile
+++ b/drivers/s390/block/Makefile
@@ -5,7 +5,6 @@
dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o
dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o
dasd_diag_mod-objs := dasd_diag.o
-dasd_eer_mod-objs := dasd_eer.o
dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \
dasd_genhd.o dasd_erp.o
@@ -14,6 +13,5 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o
obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o
obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o
obj-$(CONFIG_DASD_CMB) += dasd_cmb.o
-obj-$(CONFIG_DASD_EER) += dasd_eer.o
obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
obj-$(CONFIG_DCSSBLK) += dcssblk.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 08c88fcd8963..33157c84d1d3 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/buffer_head.h>
#include <linux/hdreg.h>
-#include <linux/notifier.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -58,7 +57,6 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
static void dasd_flush_ccw_queue(struct dasd_device *, int);
static void dasd_tasklet(struct dasd_device *);
static void do_kick_device(void *data);
-static void dasd_disable_eer(struct dasd_device *device);
/*
* SECTION: Operations on the device structure.
@@ -153,10 +151,13 @@ dasd_state_new_to_known(struct dasd_device *device)
static inline void
dasd_state_known_to_new(struct dasd_device * device)
{
- /* disable extended error reporting for this device */
- dasd_disable_eer(device);
/* Forget the discipline information. */
+ if (device->discipline)
+ module_put(device->discipline->owner);
device->discipline = NULL;
+ if (device->base_discipline)
+ module_put(device->base_discipline->owner);
+ device->base_discipline = NULL;
device->state = DASD_STATE_NEW;
dasd_free_queue(device);
@@ -214,9 +215,10 @@ dasd_state_basic_to_known(struct dasd_device * device)
* interrupt for this detection ccw uses the kernel event daemon to
* trigger the call to dasd_change_state. All this is done in the
* discipline code, see dasd_eckd.c.
- * After the analysis ccw is done (do_analysis returned 0 or error)
- * the block device is setup. Either a fake disk is added to allow
- * formatting or a proper device request queue is created.
+ * After the analysis ccw is done (do_analysis returned 0) the block
+ * device is setup.
+ * In case the analysis returns an error, the device setup is stopped
+ * (a fake disk was already added to allow formatting).
*/
static inline int
dasd_state_basic_to_ready(struct dasd_device * device)
@@ -226,13 +228,19 @@ dasd_state_basic_to_ready(struct dasd_device * device)
rc = 0;
if (device->discipline->do_analysis != NULL)
rc = device->discipline->do_analysis(device);
- if (rc)
+ if (rc) {
+ if (rc != -EAGAIN)
+ device->state = DASD_STATE_UNFMT;
return rc;
+ }
+ /* make disk known with correct capacity */
dasd_setup_queue(device);
+ set_capacity(device->gdp, device->blocks << device->s2b_shift);
device->state = DASD_STATE_READY;
- if (dasd_scan_partitions(device) != 0)
+ rc = dasd_scan_partitions(device);
+ if (rc)
device->state = DASD_STATE_BASIC;
- return 0;
+ return rc;
}
/*
@@ -253,6 +261,15 @@ dasd_state_ready_to_basic(struct dasd_device * device)
}
/*
+ * Back to basic.
+ */
+static inline void
+dasd_state_unfmt_to_basic(struct dasd_device * device)
+{
+ device->state = DASD_STATE_BASIC;
+}
+
+/*
* Make the device online and schedule the bottom half to start
* the requeueing of requests from the linux request queue to the
* ccw queue.
@@ -318,8 +335,12 @@ dasd_decrease_state(struct dasd_device *device)
if (device->state == DASD_STATE_READY &&
device->target <= DASD_STATE_BASIC)
dasd_state_ready_to_basic(device);
-
- if (device->state == DASD_STATE_BASIC &&
+
+ if (device->state == DASD_STATE_UNFMT &&
+ device->target <= DASD_STATE_BASIC)
+ dasd_state_unfmt_to_basic(device);
+
+ if (device->state == DASD_STATE_BASIC &&
device->target <= DASD_STATE_KNOWN)
dasd_state_basic_to_known(device);
@@ -871,9 +892,6 @@ dasd_handle_state_change_pending(struct dasd_device *device)
struct dasd_ccw_req *cqr;
struct list_head *l, *n;
- /* first of all call extended error reporting */
- dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL);
-
device->stopped &= ~DASD_STOPPED_PENDING;
/* restart all 'running' IO on queue */
@@ -1093,19 +1111,6 @@ restart:
}
goto restart;
}
-
- /* first of all call extended error reporting */
- if (device->eer && cqr->status == DASD_CQR_FAILED) {
- dasd_write_eer_trigger(DASD_EER_FATALERROR,
- device, cqr);
-
- /* restart request */
- cqr->status = DASD_CQR_QUEUED;
- cqr->retries = 255;
- device->stopped |= DASD_STOPPED_QUIESCE;
- goto restart;
- }
-
/* Process finished ERP request. */
if (cqr->refers) {
__dasd_process_erp(device, cqr);
@@ -1243,8 +1248,7 @@ __dasd_start_head(struct dasd_device * device)
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
/* check FAILFAST */
if (device->stopped & ~DASD_STOPPED_PENDING &&
- test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
- (!device->eer)) {
+ test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
cqr->status = DASD_CQR_FAILED;
dasd_schedule_bh(device);
}
@@ -1738,7 +1742,7 @@ dasd_open(struct inode *inp, struct file *filp)
goto out;
}
- if (device->state < DASD_STATE_BASIC) {
+ if (device->state <= DASD_STATE_BASIC) {
DBF_DEV_EVENT(DBF_ERR, device, " %s",
" Cannot open unrecognized device");
rc = -ENODEV;
@@ -1880,9 +1884,10 @@ dasd_generic_remove (struct ccw_device *cdev)
*/
int
dasd_generic_set_online (struct ccw_device *cdev,
- struct dasd_discipline *discipline)
+ struct dasd_discipline *base_discipline)
{
+ struct dasd_discipline *discipline;
struct dasd_device *device;
int rc;
@@ -1890,6 +1895,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
if (IS_ERR(device))
return PTR_ERR(device);
+ discipline = base_discipline;
if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
@@ -1901,6 +1907,16 @@ dasd_generic_set_online (struct ccw_device *cdev,
}
discipline = dasd_diag_discipline_pointer;
}
+ if (!try_module_get(base_discipline->owner)) {
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ if (!try_module_get(discipline->owner)) {
+ module_put(base_discipline->owner);
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ device->base_discipline = base_discipline;
device->discipline = discipline;
rc = discipline->check_device(device);
@@ -1909,6 +1925,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
"dasd_generic couldn't online device %s "
"with discipline %s rc=%i\n",
cdev->dev.bus_id, discipline->name, rc);
+ module_put(discipline->owner);
+ module_put(base_discipline->owner);
dasd_delete_device(device);
return rc;
}
@@ -1986,9 +2004,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
switch (event) {
case CIO_GONE:
case CIO_NO_PATH:
- /* first of all call extended error reporting */
- dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL);
-
if (device->state < DASD_STATE_BASIC)
break;
/* Device is active. We want to keep it. */
@@ -2046,51 +2061,6 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
put_driver(drv);
}
-/*
- * notifications for extended error reports
- */
-static struct notifier_block *dasd_eer_chain;
-
-int
-dasd_register_eer_notifier(struct notifier_block *nb)
-{
- return notifier_chain_register(&dasd_eer_chain, nb);
-}
-
-int
-dasd_unregister_eer_notifier(struct notifier_block *nb)
-{
- return notifier_chain_unregister(&dasd_eer_chain, nb);
-}
-
-/*
- * Notify the registered error reporting module of a problem
- */
-void
-dasd_write_eer_trigger(unsigned int id, struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- if (device->eer) {
- struct dasd_eer_trigger temp;
- temp.id = id;
- temp.device = device;
- temp.cqr = cqr;
- notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER,
- (void *)&temp);
- }
-}
-
-/*
- * Tell the registered error reporting module to disable error reporting for
- * a given device and to cleanup any private data structures on that device.
- */
-static void
-dasd_disable_eer(struct dasd_device *device)
-{
- notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device);
-}
-
-
static int __init
dasd_init(void)
{
@@ -2172,11 +2142,6 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online);
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
-EXPORT_SYMBOL(dasd_register_eer_notifier);
-EXPORT_SYMBOL(dasd_unregister_eer_notifier);
-EXPORT_SYMBOL(dasd_write_eer_trigger);
-
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index c811380b9079..4ee0f934e325 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1108,9 +1108,6 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
case 0x0B:
DEV_MESSAGE(KERN_WARNING, device, "%s",
"FORMAT F - Volume is suspended duplex");
- /* call extended error reporting (EER) */
- dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device,
- erp->refers);
break;
case 0x0C:
DEV_MESSAGE(KERN_WARNING, device, "%s",
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index e15dd7978050..bc3823d35223 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -29,7 +29,6 @@
#define DASD_ECKD_CCW_PSF 0x27
#define DASD_ECKD_CCW_RSSD 0x3e
#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
-#define DASD_ECKD_CCW_SNSS 0x54
#define DASD_ECKD_CCW_DEFINE_EXTENT 0x63
#define DASD_ECKD_CCW_WRITE_MT 0x85
#define DASD_ECKD_CCW_READ_MT 0x86
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
deleted file mode 100644
index f70cd7716b24..000000000000
--- a/drivers/s390/block/dasd_eer.c
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- * character device driver for extended error reporting
- *
- *
- * Copyright (C) 2005 IBM Corporation
- * extended error reporting for DASD ECKD devices
- * Author(s): Stefan Weinhuber <wein@de.ibm.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <linux/notifier.h>
-
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-#include <asm/atomic.h>
-#include <asm/ebcdic.h>
-
-#include "dasd_int.h"
-#include "dasd_eckd.h"
-
-
-MODULE_LICENSE("GPL");
-
-MODULE_AUTHOR("Stefan Weinhuber <wein@de.ibm.com>");
-MODULE_DESCRIPTION("DASD extended error reporting module");
-
-
-#ifdef PRINTK_HEADER
-#undef PRINTK_HEADER
-#endif /* PRINTK_HEADER */
-#define PRINTK_HEADER "dasd(eer):"
-
-
-
-
-
-/*****************************************************************************/
-/* the internal buffer */
-/*****************************************************************************/
-
-/*
- * The internal buffer is meant to store obaque blobs of data, so it doesn't
- * know of higher level concepts like triggers.
- * It consists of a number of pages that are used as a ringbuffer. Each data
- * blob is stored in a simple record that consists of an integer, which
- * contains the size of the following data, and the data bytes themselfes.
- *
- * To allow for multiple independent readers we create one internal buffer
- * each time the device is opened and destroy the buffer when the file is
- * closed again.
- *
- * One record can be written to a buffer by using the functions
- * - dasd_eer_start_record (one time per record to write the size to the buffer
- * and reserve the space for the data)
- * - dasd_eer_write_buffer (one or more times per record to write the data)
- * The data can be written in several steps but you will have to compute
- * the total size up front for the invocation of dasd_eer_start_record.
- * If the ringbuffer is full, dasd_eer_start_record will remove the required
- * number of old records.
- *
- * A record is typically read in two steps, first read the integer that
- * specifies the size of the following data, then read the data.
- * Both can be done by
- * - dasd_eer_read_buffer
- *
- * For all mentioned functions you need to get the bufferlock first and keep it
- * until a complete record is written or read.
- */
-
-
-/*
- * Alle information necessary to keep track of an internal buffer is kept in
- * a struct eerbuffer. The buffer specific to a file pointer is strored in
- * the private_data field of that file. To be able to write data to all
- * existing buffers, each buffer is also added to the bufferlist.
- * If the user doesn't want to read a complete record in one go, we have to
- * keep track of the rest of the record. residual stores the number of bytes
- * that are still to deliver. If the rest of the record is invalidated between
- * two reads then residual will be set to -1 so that the next read will fail.
- * All entries in the eerbuffer structure are protected with the bufferlock.
- * To avoid races between writing to a buffer on the one side and creating
- * and destroying buffers on the other side, the bufferlock must also be used
- * to protect the bufferlist.
- */
-
-struct eerbuffer {
- struct list_head list;
- char **buffer;
- int buffersize;
- int buffer_page_count;
- int head;
- int tail;
- int residual;
-};
-
-LIST_HEAD(bufferlist);
-
-static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED;
-
-DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
-
-/*
- * How many free bytes are available on the buffer.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_get_free_bytes(struct eerbuffer *eerb)
-{
- if (eerb->head < eerb->tail) {
- return eerb->tail - eerb->head - 1;
- } else
- return eerb->buffersize - eerb->head + eerb->tail -1;
-}
-
-/*
- * How many bytes of buffer space are used.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_get_filled_bytes(struct eerbuffer *eerb)
-{
-
- if (eerb->head >= eerb->tail) {
- return eerb->head - eerb->tail;
- } else
- return eerb->buffersize - eerb->tail + eerb->head;
-}
-
-/*
- * The dasd_eer_write_buffer function just copies count bytes of data
- * to the buffer. Make sure to call dasd_eer_start_record first, to
- * make sure that enough free space is available.
- * needs to be called with bufferlock held
- */
-static void
-dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data)
-{
-
- unsigned long headindex,localhead;
- unsigned long rest, len;
- char *nextdata;
-
- nextdata = data;
- rest = count;
- while (rest > 0) {
- headindex = eerb->head / PAGE_SIZE;
- localhead = eerb->head % PAGE_SIZE;
- len = min(rest, (PAGE_SIZE - localhead));
- memcpy(eerb->buffer[headindex]+localhead, nextdata, len);
- nextdata += len;
- rest -= len;
- eerb->head += len;
- if ( eerb->head == eerb->buffersize )
- eerb->head = 0; /* wrap around */
- if (eerb->head > eerb->buffersize) {
- MESSAGE(KERN_ERR, "%s", "runaway buffer head.");
- BUG();
- }
- }
-}
-
-/*
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data)
-{
-
- unsigned long tailindex,localtail;
- unsigned long rest, len, finalcount;
- char *nextdata;
-
- finalcount = min(count, dasd_eer_get_filled_bytes(eerb));
- nextdata = data;
- rest = finalcount;
- while (rest > 0) {
- tailindex = eerb->tail / PAGE_SIZE;
- localtail = eerb->tail % PAGE_SIZE;
- len = min(rest, (PAGE_SIZE - localtail));
- memcpy(nextdata, eerb->buffer[tailindex]+localtail, len);
- nextdata += len;
- rest -= len;
- eerb->tail += len;
- if ( eerb->tail == eerb->buffersize )
- eerb->tail = 0; /* wrap around */
- if (eerb->tail > eerb->buffersize) {
- MESSAGE(KERN_ERR, "%s", "runaway buffer tail.");
- BUG();
- }
- }
- return finalcount;
-}
-
-/*
- * Whenever you want to write a blob of data to the internal buffer you
- * have to start by using this function first. It will write the number
- * of bytes that will be written to the buffer. If necessary it will remove
- * old records to make room for the new one.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_start_record(struct eerbuffer *eerb, int count)
-{
- int tailcount;
- if (count + sizeof(count) > eerb->buffersize)
- return -ENOMEM;
- while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) {
- if (eerb->residual > 0) {
- eerb->tail += eerb->residual;
- if (eerb->tail >= eerb->buffersize)
- eerb->tail -= eerb->buffersize;
- eerb->residual = -1;
- }
- dasd_eer_read_buffer(eerb, sizeof(tailcount),
- (char*)(&tailcount));
- eerb->tail += tailcount;
- if (eerb->tail >= eerb->buffersize)
- eerb->tail -= eerb->buffersize;
- }
- dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count));
-
- return 0;
-};
-
-/*
- * release pages that are not used anymore
- */
-static void
-dasd_eer_free_buffer_pages(char **buf, int no_pages)
-{
- int i;
-
- for (i = 0; i < no_pages; ++i) {
- free_page((unsigned long)buf[i]);
- }
-}
-
-/*
- * allocate a new set of memory pages
- */
-static int
-dasd_eer_allocate_buffer_pages(char **buf, int no_pages)
-{
- int i;
-
- for (i = 0; i < no_pages; ++i) {
- buf[i] = (char *) get_zeroed_page(GFP_KERNEL);
- if (!buf[i]) {
- dasd_eer_free_buffer_pages(buf, i);
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-/*
- * empty the buffer by resetting head and tail
- * In case there is a half read data blob in the buffer, we set residual
- * to -1 to indicate that the remainder of the blob is lost.
- */
-static void
-dasd_eer_purge_buffer(struct eerbuffer *eerb)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&bufferlock, flags);
- if (eerb->residual > 0)
- eerb->residual = -1;
- eerb->tail=0;
- eerb->head=0;
- spin_unlock_irqrestore(&bufferlock, flags);
-}
-
-/*
- * set the size of the buffer, newsize is the new number of pages to be used
- * we don't try to copy any data back an forth, so any resize will also purge
- * the buffer
- */
-static int
-dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize)
-{
- int i, oldcount, reuse;
- char **new;
- char **old;
- unsigned long flags;
-
- if (newsize < 1)
- return -EINVAL;
- if (eerb->buffer_page_count == newsize) {
- /* documented behaviour is that any successfull invocation
- * will purge all records */
- dasd_eer_purge_buffer(eerb);
- return 0;
- }
- new = kmalloc(newsize*sizeof(char*), GFP_KERNEL);
- if (!new)
- return -ENOMEM;
-
- reuse=min(eerb->buffer_page_count, newsize);
- for (i = 0; i < reuse; ++i) {
- new[i] = eerb->buffer[i];
- }
- if (eerb->buffer_page_count < newsize) {
- if (dasd_eer_allocate_buffer_pages(
- &new[eerb->buffer_page_count],
- newsize - eerb->buffer_page_count)) {
- kfree(new);
- return -ENOMEM;
- }
- }
-
- spin_lock_irqsave(&bufferlock, flags);
- old = eerb->buffer;
- eerb->buffer = new;
- if (eerb->residual > 0)
- eerb->residual = -1;
- eerb->tail = 0;
- eerb->head = 0;
- oldcount = eerb->buffer_page_count;
- eerb->buffer_page_count = newsize;
- spin_unlock_irqrestore(&bufferlock, flags);
-
- if (oldcount > newsize) {
- for (i = newsize; i < oldcount; ++i) {
- free_page((unsigned long)old[i]);
- }
- }
- kfree(old);
-
- return 0;
-}
-
-
-/*****************************************************************************/
-/* The extended error reporting functionality */
-/*****************************************************************************/
-
-/*
- * When a DASD device driver wants to report an error, it calls the
- * function dasd_eer_write_trigger (via a notifier mechanism) and gives the
- * respective trigger ID as parameter.
- * Currently there are four kinds of triggers:
- *
- * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems
- * DASD_EER_PPRCSUSPEND: PPRC was suspended
- * DASD_EER_NOPATH: There is no path to the device left.
- * DASD_EER_STATECHANGE: The state of the device has changed.
- *
- * For the first three triggers all required information can be supplied by
- * the caller. For these triggers a record is written by the function
- * dasd_eer_write_standard_trigger.
- *
- * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE
- * trigger, we have to gather the necessary sense data first. We cannot queue
- * the necessary SNSS (sense subsystem status) request immediatly, since we
- * are likely to run in a deadlock situation. Instead, we schedule a
- * work_struct that calls the function dasd_eer_sense_subsystem_status to
- * create and start an SNSS request asynchronously.
- *
- * To avoid memory allocations at runtime, the necessary memory is allocated
- * when the extended error reporting is enabled for a device (by
- * dasd_eer_probe). There is one private eer data structure for each eer
- * enabled DASD device. It contains memory for the work_struct, one SNSS cqr
- * and a flags field that is used to coordinate the use of the cqr. The call
- * to write a state change trigger can come in at any time, so we have one flag
- * CQR_IN_USE that protects the cqr itself. When this flag indicates that the
- * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a
- * second request but sets the SNSS_REQUESTED flag instead.
- *
- * When the request is finished, the callback function dasd_eer_SNSS_cb
- * is called. This function will invoke the function
- * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also
- * check the SNSS_REQUESTED flag and if it is set it will call
- * dasd_eer_sense_subsystem_status again.
- *
- * To avoid race conditions during the handling of the lock, the flags must
- * be protected by the snsslock.
- */
-
-struct dasd_eer_private {
- struct dasd_ccw_req *cqr;
- unsigned long flags;
- struct work_struct worker;
-};
-
-static void dasd_eer_destroy(struct dasd_device *device,
- struct dasd_eer_private *eer);
-static int
-dasd_eer_write_trigger(struct dasd_eer_trigger *trigger);
-static void dasd_eer_sense_subsystem_status(void *data);
-static int dasd_eer_notify(struct notifier_block *self,
- unsigned long action, void *data);
-
-struct workqueue_struct *dasd_eer_workqueue;
-
-#define SNSS_DATA_SIZE 44
-static spinlock_t snsslock = SPIN_LOCK_UNLOCKED;
-
-#define DASD_EER_BUSID_SIZE 10
-struct dasd_eer_header {
- __u32 total_size;
- __u32 trigger;
- __u64 tv_sec;
- __u64 tv_usec;
- char busid[DASD_EER_BUSID_SIZE];
-} __attribute__ ((packed));
-
-static struct notifier_block dasd_eer_nb = {
- .notifier_call = dasd_eer_notify,
-};
-
-/*
- * flags for use with dasd_eer_private
- */
-#define CQR_IN_USE 0
-#define SNSS_REQUESTED 1
-
-/*
- * This function checks if extended error reporting is available for a given
- * dasd_device. If yes, then it creates and returns a struct dasd_eer,
- * otherwise it returns an -EPERM error pointer.
- */
-struct dasd_eer_private *
-dasd_eer_probe(struct dasd_device *device)
-{
- struct dasd_eer_private *private;
-
- if (!(device && device->discipline
- && !strcmp(device->discipline->name, "ECKD"))) {
- return ERR_PTR(-EPERM);
- }
- /* allocate the private data structure */
- private = (struct dasd_eer_private *)kmalloc(
- sizeof(struct dasd_eer_private), GFP_KERNEL);
- if (!private) {
- return ERR_PTR(-ENOMEM);
- }
- INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status,
- (void *)device);
- private->cqr = dasd_kmalloc_request("ECKD",
- 1 /* SNSS */ ,
- SNSS_DATA_SIZE ,
- device);
- if (!private->cqr) {
- kfree(private);
- return ERR_PTR(-ENOMEM);
- }
- private->flags = 0;
- return private;
-};
-
-/*
- * If our private SNSS request is queued, remove it from the
- * dasd ccw queue so we can free the requests memory.
- */
-static void
-dasd_eer_dequeue_SNSS_request(struct dasd_device *device,
- struct dasd_eer_private *eer)
-{
- struct list_head *lst, *nxt;
- struct dasd_ccw_req *cqr, *erpcqr;
- dasd_erp_fn_t erp_fn;
-
- spin_lock_irq(get_ccwdev_lock(device->cdev));
- list_for_each_safe(lst, nxt, &device->ccw_queue) {
- cqr = list_entry(lst, struct dasd_ccw_req, list);
- /* we are looking for two kinds or requests */
- /* first kind: our SNSS request: */
- if (cqr == eer->cqr) {
- if (cqr->status == DASD_CQR_IN_IO)
- device->discipline->term_IO(cqr);
- list_del(&cqr->list);
- break;
- }
- /* second kind: ERP requests for our SNSS request */
- if (cqr->refers) {
- /* If this erp request chain ends in our cqr, then */
- /* cal the erp_postaction to clean it up */
- erpcqr = cqr;
- while (erpcqr->refers) {
- erpcqr = erpcqr->refers;
- }
- if (erpcqr == eer->cqr) {
- erp_fn = device->discipline->erp_postaction(
- cqr);
- erp_fn(cqr);
- }
- continue;
- }
- }
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
-}
-
-/*
- * This function dismantles a struct dasd_eer that was created by
- * dasd_eer_probe. Since we want to free our private data structure,
- * we must make sure that the memory is not in use anymore.
- * We have to flush the work queue and remove a possible SNSS request
- * from the dasd queue.
- */
-static void
-dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer)
-{
- flush_workqueue(dasd_eer_workqueue);
- dasd_eer_dequeue_SNSS_request(device, eer);
- dasd_kfree_request(eer->cqr, device);
- kfree(eer);
-};
-
-/*
- * enable the extended error reporting for a particular device
- */
-static int
-dasd_eer_enable_on_device(struct dasd_device *device)
-{
- void *eer;
- if (!device)
- return -ENODEV;
- if (device->eer)
- return 0;
- if (!try_module_get(THIS_MODULE)) {
- return -EINVAL;
- }
- eer = (void *)dasd_eer_probe(device);
- if (IS_ERR(eer)) {
- module_put(THIS_MODULE);
- return PTR_ERR(eer);
- }
- device->eer = eer;
- return 0;
-}
-
-/*
- * enable the extended error reporting for a particular device
- */
-static int
-dasd_eer_disable_on_device(struct dasd_device *device)
-{
- struct dasd_eer_private *eer = device->eer;
-
- if (!device)
- return -ENODEV;
- if (!device->eer)
- return 0;
- device->eer = NULL;
- dasd_eer_destroy(device,eer);
- module_put(THIS_MODULE);
-
- return 0;
-}
-
-/*
- * Set extended error reporting (eer)
- * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
- */
-static int
-dasd_ioctl_set_eer(struct block_device *bdev, int no, long args)
-{
- struct dasd_device *device;
- int intval;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (bdev != bdev->bd_contains)
- /* Error-reporting is not allowed for partitions */
- return -EINVAL;
- if (get_user(intval, (int __user *) args))
- return -EFAULT;
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
-
- intval = (intval != 0);
- DEV_MESSAGE (KERN_DEBUG, device,
- "set eer on device to %d", intval);
- if (intval)
- return dasd_eer_enable_on_device(device);
- else
- return dasd_eer_disable_on_device(device);
-}
-
-/*
- * Get value of extended error reporting.
- * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
- */
-static int
-dasd_ioctl_get_eer(struct block_device *bdev, int no, long args)
-{
- struct dasd_device *device;
-
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
- return put_user((device->eer != NULL), (int __user *) args);
-}
-
-/*
- * The following function can be used for those triggers that have
- * all necessary data available when the function is called.
- * If the parameter cqr is not NULL, the chain of requests will be searched
- * for valid sense data, and all valid sense data sets will be added to
- * the triggers data.
- */
-static int
-dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- struct dasd_ccw_req *temp_cqr;
- int data_size;
- struct timeval tv;
- struct dasd_eer_header header;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- /* go through cqr chain and count the valid sense data sets */
- temp_cqr = cqr;
- data_size = 0;
- while (temp_cqr) {
- if (temp_cqr->irb.esw.esw0.erw.cons)
- data_size += 32;
- temp_cqr = temp_cqr->refers;
- }
-
- header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
- header.trigger = trigger;
- do_gettimeofday(&tv);
- header.tv_sec = tv.tv_sec;
- header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
-
- spin_lock_irqsave(&bufferlock, flags);
- list_for_each_entry(eerb, &bufferlist, list) {
- dasd_eer_start_record(eerb, header.total_size);
- dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header));
- temp_cqr = cqr;
- while (temp_cqr) {
- if (temp_cqr->irb.esw.esw0.erw.cons)
- dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw);
- temp_cqr = temp_cqr->refers;
- }
- dasd_eer_write_buffer(eerb, 4,"EOR");
- }
- spin_unlock_irqrestore(&bufferlock, flags);
-
- wake_up_interruptible(&dasd_eer_read_wait_queue);
-
- return 0;
-}
-
-/*
- * This function writes a DASD_EER_STATECHANGE trigger.
- */
-static void
-dasd_eer_write_SNSS_trigger(struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- int data_size;
- int snss_rc;
- struct timeval tv;
- struct dasd_eer_header header;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
- if (snss_rc)
- data_size = 0;
- else
- data_size = SNSS_DATA_SIZE;
-
- header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
- header.trigger = DASD_EER_STATECHANGE;
- do_gettimeofday(&tv);
- header.tv_sec = tv.tv_sec;
- header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
-
- spin_lock_irqsave(&bufferlock, flags);
- list_for_each_entry(eerb, &bufferlist, list) {
- dasd_eer_start_record(eerb, header.total_size);
- dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header));
- if (!snss_rc)
- dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data);
- dasd_eer_write_buffer(eerb, 4,"EOR");
- }
- spin_unlock_irqrestore(&bufferlock, flags);
-
- wake_up_interruptible(&dasd_eer_read_wait_queue);
-}
-
-/*
- * callback function for use with SNSS request
- */
-static void
-dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data)
-{
- struct dasd_device *device;
- struct dasd_eer_private *private;
- unsigned long irqflags;
-
- device = (struct dasd_device *)data;
- private = (struct dasd_eer_private *)device->eer;
- dasd_eer_write_SNSS_trigger(device, cqr);
- spin_lock_irqsave(&snsslock, irqflags);
- if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) {
- clear_bit(CQR_IN_USE, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- return;
- };
- clear_bit(CQR_IN_USE, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- dasd_eer_sense_subsystem_status(device);
- return;
-}
-
-/*
- * clean a used cqr before using it again
- */
-static void
-dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr)
-{
- struct ccw1 *cpaddr = cqr->cpaddr;
- void *data = cqr->data;
-
- memset(cqr, 0, sizeof(struct dasd_ccw_req));
- memset(cpaddr, 0, sizeof(struct ccw1));
- memset(data, 0, SNSS_DATA_SIZE);
- cqr->cpaddr = cpaddr;
- cqr->data = data;
- strncpy((char *) &cqr->magic, "ECKD", 4);
- ASCEBC((char *) &cqr->magic, 4);
- set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
-}
-
-/*
- * build and start an SNSS request
- * This function is called from a work queue so we have to
- * pass the dasd_device pointer as a void pointer.
- */
-static void
-dasd_eer_sense_subsystem_status(void *data)
-{
- struct dasd_device *device;
- struct dasd_eer_private *private;
- struct dasd_ccw_req *cqr;
- struct ccw1 *ccw;
- unsigned long irqflags;
-
- device = (struct dasd_device *)data;
- private = (struct dasd_eer_private *)device->eer;
- if (!private) /* device not eer enabled any more */
- return;
- cqr = private->cqr;
- spin_lock_irqsave(&snsslock, irqflags);
- if(test_and_set_bit(CQR_IN_USE, &private->flags)) {
- set_bit(SNSS_REQUESTED, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- return;
- };
- spin_unlock_irqrestore(&snsslock, irqflags);
- dasd_eer_clean_SNSS_request(cqr);
- cqr->device = device;
- cqr->retries = 255;
- cqr->expires = 10 * HZ;
-
- ccw = cqr->cpaddr;
- ccw->cmd_code = DASD_ECKD_CCW_SNSS;
- ccw->count = SNSS_DATA_SIZE;
- ccw->flags = 0;
- ccw->cda = (__u32)(addr_t)cqr->data;
-
- cqr->buildclk = get_clock();
- cqr->status = DASD_CQR_FILLED;
- cqr->callback = dasd_eer_SNSS_cb;
- cqr->callback_data = (void *)device;
- dasd_add_request_head(cqr);
-
- return;
-}
-
-/*
- * This function is called for all triggers. It calls the appropriate
- * function that writes the actual trigger records.
- */
-static int
-dasd_eer_write_trigger(struct dasd_eer_trigger *trigger)
-{
- int rc;
- struct dasd_eer_private *private = trigger->device->eer;
-
- switch (trigger->id) {
- case DASD_EER_FATALERROR:
- case DASD_EER_PPRCSUSPEND:
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, trigger->cqr);
- break;
- case DASD_EER_NOPATH:
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, NULL);
- break;
- case DASD_EER_STATECHANGE:
- if (queue_work(dasd_eer_workqueue, &private->worker)) {
- rc=0;
- } else {
- /* If the work_struct was already queued, it can't
- * be queued again. But this is OK since we don't
- * need to have it queued twice.
- */
- rc = -EBUSY;
- }
- break;
- default: /* unknown trigger, so we write it without any sense data */
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, NULL);
- break;
- }
- return rc;
-}
-
-/*
- * This function is registered with the dasd device driver and gets called
- * for all dasd eer notifications.
- */
-static int dasd_eer_notify(struct notifier_block *self,
- unsigned long action, void *data)
-{
- switch (action) {
- case DASD_EER_DISABLE:
- dasd_eer_disable_on_device((struct dasd_device *)data);
- break;
- case DASD_EER_TRIGGER:
- dasd_eer_write_trigger((struct dasd_eer_trigger *)data);
- break;
- }
- return NOTIFY_OK;
-}
-
-
-/*****************************************************************************/
-/* the device operations */
-/*****************************************************************************/
-
-/*
- * On the one side we need a lock to access our internal buffer, on the
- * other side a copy_to_user can sleep. So we need to copy the data we have
- * to transfer in a readbuffer, which is protected by the readbuffer_mutex.
- */
-static char readbuffer[PAGE_SIZE];
-DECLARE_MUTEX(readbuffer_mutex);
-
-
-static int
-dasd_eer_open(struct inode *inp, struct file *filp)
-{
- struct eerbuffer *eerb;
- unsigned long flags;
-
- eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL);
- eerb->head = 0;
- eerb->tail = 0;
- eerb->residual = 0;
- eerb->buffer_page_count = 1;
- eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
- eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*),
- GFP_KERNEL);
- if (!eerb->buffer)
- return -ENOMEM;
- if (dasd_eer_allocate_buffer_pages(eerb->buffer,
- eerb->buffer_page_count)) {
- kfree(eerb->buffer);
- return -ENOMEM;
- }
- filp->private_data = eerb;
- spin_lock_irqsave(&bufferlock, flags);
- list_add(&eerb->list, &bufferlist);
- spin_unlock_irqrestore(&bufferlock, flags);
-
- return nonseekable_open(inp,filp);
-}
-
-static int
-dasd_eer_close(struct inode *inp, struct file *filp)
-{
- struct eerbuffer *eerb;
- unsigned long flags;
-
- eerb = (struct eerbuffer *)filp->private_data;
- spin_lock_irqsave(&bufferlock, flags);
- list_del(&eerb->list);
- spin_unlock_irqrestore(&bufferlock, flags);
- dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count);
- kfree(eerb->buffer);
- kfree(eerb);
-
- return 0;
-}
-
-static long
-dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int intval;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- switch (cmd) {
- case DASD_EER_PURGE:
- dasd_eer_purge_buffer(eerb);
- return 0;
- case DASD_EER_SETBUFSIZE:
- if (get_user(intval, (int __user *)arg))
- return -EFAULT;
- return dasd_eer_resize_buffer(eerb, intval);
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-static ssize_t
-dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
- int tc,rc;
- int tailcount,effective_count;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- if(down_interruptible(&readbuffer_mutex))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&bufferlock, flags);
-
- if (eerb->residual < 0) { /* the remainder of this record */
- /* has been deleted */
- eerb->residual = 0;
- spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
- return -EIO;
- } else if (eerb->residual > 0) {
- /* OK we still have a second half of a record to deliver */
- effective_count = min(eerb->residual, (int)count);
- eerb->residual -= effective_count;
- } else {
- tc = 0;
- while (!tc) {
- tc = dasd_eer_read_buffer(eerb,
- sizeof(tailcount), (char*)(&tailcount));
- if (!tc) {
- /* no data available */
- spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- rc = wait_event_interruptible(
- dasd_eer_read_wait_queue,
- eerb->head != eerb->tail);
- if (rc) {
- return rc;
- }
- if(down_interruptible(&readbuffer_mutex))
- return -ERESTARTSYS;
- spin_lock_irqsave(&bufferlock, flags);
- }
- }
- WARN_ON(tc != sizeof(tailcount));
- effective_count = min(tailcount,(int)count);
- eerb->residual = tailcount - effective_count;
- }
-
- tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer);
- WARN_ON(tc != effective_count);
-
- spin_unlock_irqrestore(&bufferlock, flags);
-
- if (copy_to_user(buf, readbuffer, effective_count)) {
- up(&readbuffer_mutex);
- return -EFAULT;
- }
-
- up(&readbuffer_mutex);
- return effective_count;
-}
-
-static unsigned int
-dasd_eer_poll (struct file *filp, poll_table *ptable)
-{
- unsigned int mask;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- poll_wait(filp, &dasd_eer_read_wait_queue, ptable);
- spin_lock_irqsave(&bufferlock, flags);
- if (eerb->head != eerb->tail)
- mask = POLLIN | POLLRDNORM ;
- else
- mask = 0;
- spin_unlock_irqrestore(&bufferlock, flags);
- return mask;
-}
-
-static struct file_operations dasd_eer_fops = {
- .open = &dasd_eer_open,
- .release = &dasd_eer_close,
- .unlocked_ioctl = &dasd_eer_ioctl,
- .compat_ioctl = &dasd_eer_ioctl,
- .read = &dasd_eer_read,
- .poll = &dasd_eer_poll,
- .owner = THIS_MODULE,
-};
-
-static struct miscdevice dasd_eer_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "dasd_eer",
- .fops = &dasd_eer_fops,
-};
-
-
-/*****************************************************************************/
-/* Init and exit */
-/*****************************************************************************/
-
-static int
-__init dasd_eer_init(void)
-{
- int rc;
-
- dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer");
- if (!dasd_eer_workqueue) {
- MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not "
- "create workqueue \n");
- rc = -ENOMEM;
- goto out;
- }
-
- rc = dasd_register_eer_notifier(&dasd_eer_nb);
- if (rc) {
- MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
- "register error reporting");
- goto queue;
- }
-
- dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer);
- dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer);
-
- /* we don't need our own character device,
- * so we just register as misc device */
- rc = misc_register(&dasd_eer_dev);
- if (rc) {
- MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
- "register misc device");
- goto unregister;
- }
-
- return 0;
-
-unregister:
- dasd_unregister_eer_notifier(&dasd_eer_nb);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
- dasd_ioctl_set_eer);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
- dasd_ioctl_get_eer);
-queue:
- destroy_workqueue(dasd_eer_workqueue);
-out:
- return rc;
-
-}
-module_init(dasd_eer_init);
-
-static void
-__exit dasd_eer_exit(void)
-{
- dasd_unregister_eer_notifier(&dasd_eer_nb);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
- dasd_ioctl_set_eer);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
- dasd_ioctl_get_eer);
- destroy_workqueue(dasd_eer_workqueue);
-
- WARN_ON(misc_deregister(&dasd_eer_dev) != 0);
-}
-module_exit(dasd_eer_exit);
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 65dc844b975c..fce2835e7d19 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -100,8 +100,6 @@ dasd_scan_partitions(struct dasd_device * device)
{
struct block_device *bdev;
- /* Make the disk known. */
- set_capacity(device->gdp, device->blocks << device->s2b_shift);
bdev = bdget_disk(device->gdp, 0);
if (!bdev || blkdev_get(bdev, FMODE_READ, 1) < 0)
return -ENODEV;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1b08fa13fd2..7cb0b9e78a6a 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -26,7 +26,7 @@
* new: the dasd_device structure is allocated.
* known: the discipline for the device is identified.
* basic: the device can do basic i/o.
- * accept: the device is analysed (format is known).
+ * unfmt: the device could not be analyzed (format is unknown).
* ready: partition detection is done and the device is can do block io.
* online: the device accepts requests from the block device queue.
*
@@ -47,8 +47,9 @@
#define DASD_STATE_NEW 0
#define DASD_STATE_KNOWN 1
#define DASD_STATE_BASIC 2
-#define DASD_STATE_READY 3
-#define DASD_STATE_ONLINE 4
+#define DASD_STATE_UNFMT 3
+#define DASD_STATE_READY 4
+#define DASD_STATE_ONLINE 5
#include <linux/module.h>
#include <linux/wait.h>
@@ -275,34 +276,6 @@ struct dasd_discipline {
extern struct dasd_discipline *dasd_diag_discipline_pointer;
-
-/*
- * Notification numbers for extended error reporting notifications:
- * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
- * eer pointer) is freed. The error reporting module needs to do all necessary
- * cleanup steps.
- * The DASD_EER_TRIGGER notification sends the actual error reports (triggers).
- */
-#define DASD_EER_DISABLE 0
-#define DASD_EER_TRIGGER 1
-
-/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */
-#define DASD_EER_FATALERROR 1
-#define DASD_EER_NOPATH 2
-#define DASD_EER_STATECHANGE 3
-#define DASD_EER_PPRCSUSPEND 4
-
-/*
- * The dasd_eer_trigger structure contains all data that we need to send
- * along with an DASD_EER_TRIGGER notification.
- */
-struct dasd_eer_trigger {
- unsigned int id;
- struct dasd_device *device;
- struct dasd_ccw_req *cqr;
-};
-
-
struct dasd_device {
/* Block device stuff. */
struct gendisk *gdp;
@@ -316,11 +289,9 @@ struct dasd_device {
unsigned long flags; /* per device flags */
unsigned short features; /* copy of devmap-features (read-only!) */
- /* extended error reporting stuff (eer) */
- void *eer;
-
/* Device discipline stuff. */
struct dasd_discipline *discipline;
+ struct dasd_discipline *base_discipline;
char *private;
/* Device state and target state. */
@@ -519,12 +490,6 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
int dasd_generic_set_offline (struct ccw_device *cdev);
int dasd_generic_notify(struct ccw_device *, int);
void dasd_generic_auto_online (struct ccw_driver *);
-int dasd_register_eer_notifier(struct notifier_block *);
-int dasd_unregister_eer_notifier(struct notifier_block *);
-void dasd_write_eer_trigger(unsigned int , struct dasd_device *,
- struct dasd_ccw_req *);
-
-
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 2d5da3c75ca7..1aa3c261718a 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -93,6 +93,9 @@ dasd_devices_show(struct seq_file *m, void *v)
case DASD_STATE_BASIC:
seq_printf(m, "basic");
break;
+ case DASD_STATE_UNFMT:
+ seq_printf(m, "unformatted");
+ break;
case DASD_STATE_READY:
case DASD_STATE_ONLINE:
seq_printf(m, "active ");
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index ceb0e474fde4..4138564402b8 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -85,11 +85,10 @@ static volatile enum sclp_mask_state_t {
/* Maximum retry counts */
#define SCLP_INIT_RETRY 3
#define SCLP_MASK_RETRY 3
-#define SCLP_REQUEST_RETRY 3
/* Timeout intervals in seconds.*/
-#define SCLP_BUSY_INTERVAL 2
-#define SCLP_RETRY_INTERVAL 5
+#define SCLP_BUSY_INTERVAL 10
+#define SCLP_RETRY_INTERVAL 15
static void sclp_process_queue(void);
static int sclp_init_mask(int calculate);
@@ -153,11 +152,9 @@ __sclp_start_request(struct sclp_req *req)
if (sclp_running_state != sclp_running_state_idle)
return 0;
del_timer(&sclp_request_timer);
- if (req->start_count <= SCLP_REQUEST_RETRY) {
- rc = service_call(req->command, req->sccb);
- req->start_count++;
- } else
- rc = -EIO;
+ rc = service_call(req->command, req->sccb);
+ req->start_count++;
+
if (rc == 0) {
/* Sucessfully started request */
req->status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 92be75d99a56..f4183d660258 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -232,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
return 0;
mask = 0x80 >> j;
- spin_lock(&sch->lock);
+ spin_lock_irq(&sch->lock);
stsch(sch->schid, &schib);
if (!schib.pmcw.dnv)
@@ -281,10 +281,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
out_unlock:
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
out_unreg:
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
sch->lpm = 0;
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
@@ -652,7 +652,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (!sch)
/* Check if the subchannel is now available. */
return __chp_add_new_sch(schid);
- spin_lock(&sch->lock);
+ spin_lock_irq(&sch->lock);
for (i=0; i<8; i++)
if (sch->schib.pmcw.chpid[i] == chp->id) {
if (stsch(sch->schid, &sch->schib) != 0) {
@@ -674,7 +674,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
put_device(&sch->dev);
return 0;
}
@@ -1115,6 +1115,9 @@ chsc_enable_facility(int operation_code)
goto out;
}
switch (sda_area->response.code) {
+ case 0x0001: /* everything ok */
+ ret = 0;
+ break;
case 0x0003: /* invalid request block */
case 0x0007:
ret = -EINVAL;
@@ -1123,6 +1126,8 @@ chsc_enable_facility(int operation_code)
case 0x0101: /* facility not provided */
ret = -EOPNOTSUPP;
break;
+ default: /* something went wrong */
+ ret = -EIO;
}
out:
free_page((unsigned long)sda_area);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 1bbf231f8aaf..3c77d65960db 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -409,6 +409,9 @@ __init_channel_subsystem(struct subchannel_id schid, void *data)
/* -ENXIO: no more subchannels. */
case -ENXIO:
return ret;
+ /* -EIO: this subchannel set not supported. */
+ case -EIO:
+ return ret;
default:
return 0;
}
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 062fb100d94c..afc4e88551ad 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -359,7 +359,7 @@ ccw_device_set_online(struct ccw_device *cdev)
else
pr_debug("ccw_device_offline returned %d, device %s\n",
ret, cdev->dev.bus_id);
- return (ret = 0) ? -ENODEV : ret;
+ return (ret == 0) ? -ENODEV : ret;
}
static ssize_t
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index d2a5b04d7cba..85b1020a1fcc 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -405,7 +405,7 @@ __ccw_device_disband_start(struct ccw_device *cdev)
cdev->private->iretry = 5;
cdev->private->imask >>= 1;
}
- ccw_device_verify_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
+ ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
}
/*
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index dad4dd9887c9..6c762b43f921 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -317,7 +317,6 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
/*
* We have ending status but no sense information. Do a basic sense.
*/
- sch = to_subchannel(cdev->dev.parent);
sch->sense_ccw.cmd_code = CCW_CMD_BASIC_SENSE;
sch->sense_ccw.cda = (__u32) __pa(cdev->private->irb.ecw);
sch->sense_ccw.count = SENSE_MAX_COUNT;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 45ce032772f4..9ed37dc9a1b0 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -165,8 +165,13 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"eqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT2(1,trace,"eqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
@@ -195,8 +200,13 @@ qdio_do_sqbs(struct qdio_q *q, unsigned char state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"sqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT3(1,trace,"sqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
@@ -1187,8 +1197,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used)
return 1;
-
- if (!q->siga_sync)
+ if (!q->siga_sync && !irq->is_qebsm)
/* we'll check for more primed buffers in qeth_stop_polling */
return 0;
if (irq->is_qebsm) {
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 6229ba4995ad..9cf88d7201d3 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -98,9 +98,9 @@ lcs_register_debug_facility(void)
return -ENOMEM;
}
debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
- debug_set_level(lcs_dbf_setup, 4);
+ debug_set_level(lcs_dbf_setup, 2);
debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
- debug_set_level(lcs_dbf_trace, 4);
+ debug_set_level(lcs_dbf_trace, 2);
return 0;
}
@@ -1292,9 +1292,8 @@ lcs_set_multicast_list(struct net_device *dev)
LCS_DBF_TEXT(4, trace, "setmulti");
card = (struct lcs_card *) dev->priv;
- if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) {
+ if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
schedule_work(&card->kernel_thread_starter);
- }
}
#endif /* CONFIG_IP_MULTICAST */
@@ -1459,6 +1458,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
lcs_release_buffer(channel, buffer);
card = (struct lcs_card *)
((char *) channel - offsetof(struct lcs_card, write));
+ if (netif_queue_stopped(card->dev))
+ netif_wake_queue(card->dev);
spin_lock(&card->lock);
card->tx_emitted--;
if (card->tx_emitted <= 0 && card->tx_buffer != NULL)
@@ -1478,6 +1479,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
struct net_device *dev)
{
struct lcs_header *header;
+ int rc = 0;
LCS_DBF_TEXT(5, trace, "hardxmit");
if (skb == NULL) {
@@ -1492,10 +1494,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->stats.tx_carrier_errors++;
return 0;
}
- if (netif_queue_stopped(dev) ) {
- card->stats.tx_dropped++;
- return -EBUSY;
- }
+ netif_stop_queue(card->dev);
+ spin_lock(&card->lock);
if (card->tx_buffer != NULL &&
card->tx_buffer->count + sizeof(struct lcs_header) +
skb->len + sizeof(u16) > LCS_IOBUFFERSIZE)
@@ -1506,7 +1506,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->tx_buffer = lcs_get_buffer(&card->write);
if (card->tx_buffer == NULL) {
card->stats.tx_dropped++;
- return -EBUSY;
+ rc = -EBUSY;
+ goto out;
}
card->tx_buffer->callback = lcs_txbuffer_cb;
card->tx_buffer->count = 0;
@@ -1518,13 +1519,18 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
header->type = card->lan_type;
header->slot = card->portno;
memcpy(header + 1, skb->data, skb->len);
+ spin_unlock(&card->lock);
card->stats.tx_bytes += skb->len;
card->stats.tx_packets++;
dev_kfree_skb(skb);
- if (card->tx_emitted <= 0)
+ netif_wake_queue(card->dev);
+ spin_lock(&card->lock);
+ if (card->tx_emitted <= 0 && card->tx_buffer != NULL)
/* If this is the first tx buffer emit it immediately. */
__lcs_emit_txbuffer(card);
- return 0;
+out:
+ spin_unlock(&card->lock);
+ return rc;
}
static int
@@ -1535,9 +1541,7 @@ lcs_start_xmit(struct sk_buff *skb, struct net_device *dev)
LCS_DBF_TEXT(5, trace, "pktxmit");
card = (struct lcs_card *) dev->priv;
- spin_lock(&card->lock);
rc = __lcs_start_xmit(card, skb, dev);
- spin_unlock(&card->lock);
return rc;
}
@@ -2319,7 +2323,6 @@ __init lcs_init_module(void)
PRINT_ERR("Initialization failed\n");
return rc;
}
-
return 0;
}
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 08e60ad43916..2fad5e40c2e4 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -95,7 +95,7 @@ do { \
*/
#define LCS_ILLEGAL_OFFSET 0xffff
#define LCS_IOBUFFERSIZE 0x5000
-#define LCS_NUM_BUFFS 8 /* needs to be power of 2 */
+#define LCS_NUM_BUFFS 32 /* needs to be power of 2 */
#define LCS_MAC_LENGTH 6
#define LCS_INVALID_PORT_NO -1
#define LCS_LANCMD_TIMEOUT_DEFAULT 5
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 9a064d4727ad..4df0fcd7b10b 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -1076,16 +1076,6 @@ qeth_get_qdio_q_format(struct qeth_card *card)
}
static inline int
-qeth_isdigit(char * buf)
-{
- while (*buf) {
- if (!isdigit(*buf++))
- return 0;
- }
- return 1;
-}
-
-static inline int
qeth_isxdigit(char * buf)
{
while (*buf) {
@@ -1104,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
static inline int
qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
{
- const char *start, *end;
- char abuf[4];
- char *tmp;
- int len;
- int i;
-
- start = buf;
- for (i = 0; i < 4; i++) {
- if (i == 3) {
- end = strchr(start,0xa);
- if (end)
- len = end - start;
- else
- len = strlen(start);
- }
- else {
- end = strchr(start, '.');
- len = end - start;
- }
- if ((len <= 0) || (len > 3))
- return -EINVAL;
- memset(abuf, 0, 4);
- strncpy(abuf, start, len);
- if (!qeth_isdigit(abuf))
+ int count = 0, rc = 0;
+ int in[4];
+
+ rc = sscanf(buf, "%d.%d.%d.%d%n",
+ &in[0], &in[1], &in[2], &in[3], &count);
+ if (rc != 4 || count)
+ return -EINVAL;
+ for (count = 0; count < 4; count++) {
+ if (in[count] > 255)
return -EINVAL;
- addr[i] = simple_strtoul(abuf, &tmp, 10);
- start = end + 1;
+ addr[count] = in[count];
}
return 0;
}
@@ -1149,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
static inline int
qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
{
- const char *start, *end;
- u16 *tmp_addr;
- char abuf[5];
- char *tmp;
- int len;
- int i;
-
- tmp_addr = (u16 *)addr;
- start = buf;
- for (i = 0; i < 8; i++) {
- if (i == 7) {
- end = strchr(start,0xa);
- if (end)
- len = end - start;
- else
- len = strlen(start);
- }
- else {
- end = strchr(start, ':');
- len = end - start;
+ char *end, *start;
+ __u16 *in;
+ char num[5];
+ int num2, cnt, out, found, save_cnt;
+ unsigned short in_tmp[8] = {0, };
+
+ cnt = out = found = save_cnt = num2 = 0;
+ end = start = (char *) buf;
+ in = (__u16 *) addr;
+ memset(in, 0, 16);
+ while (end) {
+ end = strchr(end,':');
+ if (end == NULL) {
+ end = (char *)buf + (strlen(buf));
+ out = 1;
+ }
+ if ((end - start)) {
+ memset(num, 0, 5);
+ memcpy(num, start, end - start);
+ if (!qeth_isxdigit(num))
+ return -EINVAL;
+ sscanf(start, "%x", &num2);
+ if (found)
+ in_tmp[save_cnt++] = num2;
+ else
+ in[cnt++] = num2;
+ if (out)
+ break;
+ } else {
+ if (found)
+ return -EINVAL;
+ found = 1;
}
- if ((len <= 0) || (len > 4))
- return -EINVAL;
- memset(abuf, 0, 5);
- strncpy(abuf, start, len);
- if (!qeth_isxdigit(abuf))
- return -EINVAL;
- tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
- start = end + 1;
- }
+ start = ++end;
+ }
+ cnt = 7;
+ while (save_cnt)
+ in[cnt--] = in_tmp[--save_cnt];
return 0;
}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index b02313127780..82cb4af2f0e7 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -59,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx)
for (i = 0; i < ctx->num_pages; ++i)
free_page((unsigned long)ctx->pages[i]);
kfree(ctx->pages);
- if (ctx->elements != NULL)
- kfree(ctx->elements);
+ kfree(ctx->elements);
kfree(ctx);
}
@@ -413,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
QETH_DBF_TEXT(trace, 5, "eddpftcp");
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ eddp->skb_offset += sizeof(struct ethhdr);
+#ifdef CONFIG_QETH_VLAN
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+ eddp->skb_offset += VLAN_HLEN;
+#endif /* CONFIG_QETH_VLAN */
+ }
tcph = eddp->skb->h.th;
while (eddp->skb_offset < eddp->skb->len) {
data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
@@ -483,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
return -ENOMEM;
}
if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr);
memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
#ifdef CONFIG_QETH_VLAN
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 410abeada6c4..dba7f7f02e79 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -516,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
QETH_DBF_TEXT(setup, 3, "setoffl");
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
- netif_carrier_off(card->dev);
+ if (card->dev && netif_carrier_ok(card->dev))
+ netif_carrier_off(card->dev);
recover_flag = card->state;
if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
PRINT_WARN("Stopping card %s interrupted by user!\n",
@@ -1679,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data)
spin_unlock_irqrestore(&reply->card->lock, flags);
}
+
static struct qeth_ipa_cmd *
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
@@ -1699,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
QETH_CARD_IFNAME(card),
card->info.chpid);
card->lan_online = 0;
- netif_carrier_off(card->dev);
+ if (card->dev && netif_carrier_ok(card->dev))
+ netif_carrier_off(card->dev);
return NULL;
case IPA_CMD_STARTLAN:
PRINT_INFO("Link reestablished on %s "
@@ -5562,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
return ;
- QETH_DBF_TEXT(trace,3,"setmulti");
+ QETH_DBF_TEXT(trace, 3, "setmulti");
qeth_delete_mc_addresses(card);
if (card->options.layer2) {
qeth_layer2_add_multicast(card);
@@ -5579,7 +5582,6 @@ out:
return;
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
schedule_work(&card->kernel_thread_starter);
-
}
static int
@@ -7452,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card)
card->lan_online = 1;
if (card->info.type==QETH_CARD_TYPE_OSN)
goto out;
+ qeth_set_large_send(card, card->options.large_send);
if (card->options.layer2) {
card->dev->features |=
NETIF_F_HW_VLAN_FILTER |
@@ -7468,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card)
#endif
goto out;
}
- if ((card->options.large_send == QETH_LARGE_SEND_EDDP) ||
- (card->options.large_send == QETH_LARGE_SEND_TSO))
- card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
- else
- card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
-
if ((rc = qeth_setadapter_parms(card)))
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
if ((rc = qeth_start_ipassists(card)))
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index d6469baa7e16..72118ee68954 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -168,7 +168,7 @@ smsg_init(void)
driver_unregister(&smsg_driver);
return -EIO; /* better errno ? */
}
- rc = iucv_connect (&smsg_pathid, 1, 0, "*MSG ", 0, 0, 0, 0,
+ rc = iucv_connect (&smsg_pathid, 255, 0, "*MSG ", 0, 0, 0, 0,
smsg_handle, 0);
if (rc) {
printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 4d7d47cf2394..a5f2ba9a8fdb 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -710,10 +710,9 @@ static inline void
_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req)
+ struct zfcp_fsf_req *fsf_req,
+ struct zfcp_fsf_req *old_fsf_req)
{
- struct zfcp_fsf_req *fsf_req =
- (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
unsigned long flags;
@@ -727,19 +726,20 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
if (offset == 0) {
strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
- if (scsi_cmnd->device) {
- rec->scsi_id = scsi_cmnd->device->id;
- rec->scsi_lun = scsi_cmnd->device->lun;
+ if (scsi_cmnd != NULL) {
+ if (scsi_cmnd->device) {
+ rec->scsi_id = scsi_cmnd->device->id;
+ rec->scsi_lun = scsi_cmnd->device->lun;
+ }
+ rec->scsi_result = scsi_cmnd->result;
+ rec->scsi_cmnd = (unsigned long)scsi_cmnd;
+ rec->scsi_serial = scsi_cmnd->serial_number;
+ memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ min((int)scsi_cmnd->cmd_len,
+ ZFCP_DBF_SCSI_OPCODE));
+ rec->scsi_retries = scsi_cmnd->retries;
+ rec->scsi_allowed = scsi_cmnd->allowed;
}
- rec->scsi_result = scsi_cmnd->result;
- rec->scsi_cmnd = (unsigned long)scsi_cmnd;
- rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode,
- &scsi_cmnd->cmnd,
- min((int)scsi_cmnd->cmd_len,
- ZFCP_DBF_SCSI_OPCODE));
- rec->scsi_retries = scsi_cmnd->retries;
- rec->scsi_allowed = scsi_cmnd->allowed;
if (fsf_req != NULL) {
fcp_rsp = (struct fcp_rsp_iu *)
&(fsf_req->qtcb->bottom.io.fcp_rsp);
@@ -772,15 +772,8 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
rec->fsf_seqno = fsf_req->seq_no;
rec->fsf_issued = fsf_req->issued;
}
- if (new_fsf_req != NULL) {
- rec->type.new_fsf_req.fsf_reqid =
- (unsigned long)
- new_fsf_req;
- rec->type.new_fsf_req.fsf_seqno =
- new_fsf_req->seq_no;
- rec->type.new_fsf_req.fsf_issued =
- new_fsf_req->issued;
- }
+ rec->type.old_fsf_reqid =
+ (unsigned long) old_fsf_req;
} else {
strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
dump->total_size = buflen;
@@ -801,19 +794,21 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
inline void
zfcp_scsi_dbf_event_result(const char *tag, int level,
struct zfcp_adapter *adapter,
- struct scsi_cmnd *scsi_cmnd)
+ struct scsi_cmnd *scsi_cmnd,
+ struct zfcp_fsf_req *fsf_req)
{
- _zfcp_scsi_dbf_event_common("rslt",
- tag, level, adapter, scsi_cmnd, NULL);
+ _zfcp_scsi_dbf_event_common("rslt", tag, level,
+ adapter, scsi_cmnd, fsf_req, NULL);
}
inline void
zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req)
+ struct zfcp_fsf_req *new_fsf_req,
+ struct zfcp_fsf_req *old_fsf_req)
{
- _zfcp_scsi_dbf_event_common("abrt",
- tag, 1, adapter, scsi_cmnd, new_fsf_req);
+ _zfcp_scsi_dbf_event_common("abrt", tag, 1,
+ adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
}
inline void
@@ -823,7 +818,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
struct zfcp_adapter *adapter = unit->port->adapter;
_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
- tag, 1, adapter, scsi_cmnd, NULL);
+ tag, 1, adapter, scsi_cmnd, NULL, NULL);
}
static int
@@ -856,6 +851,10 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
rec->scsi_retries);
len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
rec->scsi_allowed);
+ if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
+ rec->type.old_fsf_reqid);
+ }
len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
rec->fsf_reqid);
len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
@@ -883,21 +882,6 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
min((int)rec->type.fcp.sns_info_len,
ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
rec->type.fcp.sns_info_len);
- } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
- len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
- rec->type.new_fsf_req.fsf_reqid);
- len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
- rec->type.new_fsf_req.fsf_seqno);
- len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
- rec->type.new_fsf_req.fsf_issued);
- } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
- (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
- len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
- rec->type.new_fsf_req.fsf_reqid);
- len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
- rec->type.new_fsf_req.fsf_seqno);
- len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
- rec->type.new_fsf_req.fsf_issued);
}
len += sprintf(out_buf + len, "\n");
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index e260d19fa717..6eba56cd89ba 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -152,11 +152,6 @@ typedef u32 scsi_lun_t;
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
-/* Retry 5 times every 2 second, then every minute */
-#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5
-#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200
-#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000
-
/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
@@ -429,11 +424,7 @@ struct zfcp_scsi_dbf_record {
u32 fsf_seqno;
u64 fsf_issued;
union {
- struct {
- u64 fsf_reqid;
- u32 fsf_seqno;
- u64 fsf_issued;
- } new_fsf_req;
+ u64 old_fsf_reqid;
struct {
u8 rsp_validity;
u8 rsp_scsi_status;
@@ -673,6 +664,7 @@ do { \
#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
+#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
@@ -915,8 +907,6 @@ struct zfcp_adapter {
wwn_t peer_wwnn; /* P2P peer WWNN */
wwn_t peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
- wwn_t physical_wwpn; /* WWPN of physical port */
- u32 physical_s_id; /* local FC port ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u8 fc_service_class;
u32 hydra_version; /* Hydra version */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index da947e662031..57cb628a05aa 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
int retval;
- if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &erp_action->adapter->status)) &&
- (erp_action->adapter->adapter_features &
- FSF_FEATURE_HBAAPI_MANAGEMENT)) {
- zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
- atomic_set(&erp_action->adapter->erp_counter, 0);
- return ZFCP_ERP_FAILED;
- }
-
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
if (retval == ZFCP_ERP_FAILED)
return ZFCP_ERP_FAILED;
@@ -2266,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
@@ -2350,48 +2334,40 @@ static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{
int ret;
- int retries;
- int sleep;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_adapter *adapter;
+ adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
- retries = 0;
- do {
- write_lock(&adapter->erp_lock);
- zfcp_erp_action_to_running(erp_action);
- write_unlock(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
- ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
- if (ret == -EOPNOTSUPP) {
- debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
- return ZFCP_ERP_SUCCEEDED;
- } else if (ret) {
- debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
- return ZFCP_ERP_FAILED;
- }
- debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
+ write_lock(&adapter->erp_lock);
+ zfcp_erp_action_to_running(erp_action);
+ write_unlock(&adapter->erp_lock);
- down(&adapter->erp_ready_sem);
- if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
- ZFCP_LOG_INFO("error: exchange of port data "
- "for adapter %s timed out\n",
- zfcp_get_busid_by_adapter(adapter));
- break;
- }
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status))
- break;
+ zfcp_erp_timeout_init(erp_action);
+ ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+ if (ret == -EOPNOTSUPP) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+ return ZFCP_ERP_SUCCEEDED;
+ } else if (ret) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+ return ZFCP_ERP_FAILED;
+ }
+ debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
- if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
- sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
- retries++;
- } else
- sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
- schedule_timeout(sleep);
- } while (1);
+ ret = ZFCP_ERP_SUCCEEDED;
+ down(&adapter->erp_ready_sem);
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
+ "%s)\n", zfcp_get_busid_by_adapter(adapter));
+ ret = ZFCP_ERP_FAILED;
+ }
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) {
+ ZFCP_LOG_INFO("error: exchange port data failed (adapter "
+ "%s\n", zfcp_get_busid_by_adapter(adapter));
+ ret = ZFCP_ERP_FAILED;
+ }
- return ZFCP_ERP_SUCCEEDED;
+ return ret;
}
/*
@@ -3415,10 +3391,13 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
&unit->status))
&& !unit->device
- && port->rport)
- scsi_add_device(port->adapter->scsi_host, 0,
- port->rport->scsi_target_id,
- unit->scsi_lun);
+ && port->rport) {
+ atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
+ &unit->status);
+ scsi_scan_target(&port->rport->dev, 0,
+ port->rport->scsi_target_id,
+ unit->scsi_lun, 0);
+ }
zfcp_unit_put(unit);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -3439,6 +3418,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
"(adapter %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port),
port->wwpn);
+ else
+ scsi_flush_work(adapter->scsi_host);
}
zfcp_port_put(port);
break;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index c1ba7cf1b496..700f5402a978 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -194,9 +194,10 @@ extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
- struct scsi_cmnd *);
+ struct scsi_cmnd *,
+ struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
- struct scsi_cmnd *,
+ struct scsi_cmnd *, struct zfcp_fsf_req *,
struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
struct scsi_cmnd *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9f0cb3d820c0..662ec571d73b 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
case FSF_PROT_LINK_DOWN:
zfcp_fsf_link_down_info_eval(adapter,
&prot_status_qual->link_down_info);
+ zfcp_erp_adapter_reopen(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -558,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
- if (link_down == NULL) {
- zfcp_erp_adapter_reopen(adapter, 0);
- return;
- }
+ if (link_down == NULL)
+ goto out;
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
@@ -643,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
link_down->explanation_code,
link_down->vendor_specific_code);
- switch (link_down->error_code) {
- case FSF_PSQ_LINK_NO_LIGHT:
- case FSF_PSQ_LINK_WRAP_PLUG:
- case FSF_PSQ_LINK_NO_FCP:
- case FSF_PSQ_LINK_FIRMWARE_UPDATE:
- zfcp_erp_adapter_reopen(adapter, 0);
- break;
- default:
- zfcp_erp_adapter_failed(adapter);
- }
+ out:
+ zfcp_erp_adapter_failed(adapter);
}
/*
@@ -2304,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
return retval;
}
+/**
+ * zfcp_fsf_exchange_port_evaluate
+ * @fsf_req: fsf_req which belongs to xchg port data request
+ * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1)
+ */
+static void
+zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+{
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb *qtcb;
+ struct fsf_qtcb_bottom_port *bottom, *data;
+ struct Scsi_Host *shost;
+
+ adapter = fsf_req->adapter;
+ qtcb = fsf_req->qtcb;
+ bottom = &qtcb->bottom.port;
+ shost = adapter->scsi_host;
+
+ data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
+ if (data)
+ memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
+
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ fc_host_permanent_port_name(shost) = bottom->wwpn;
+ else
+ fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
+ fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ fc_host_supported_speeds(shost) = bottom->supported_speed;
+}
/**
* zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
@@ -2312,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
static void
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
{
- struct zfcp_adapter *adapter = fsf_req->adapter;
- struct Scsi_Host *shost = adapter->scsi_host;
- struct fsf_qtcb *qtcb = fsf_req->qtcb;
- struct fsf_qtcb_bottom_port *bottom, *data;
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb *qtcb;
+
+ adapter = fsf_req->adapter;
+ qtcb = fsf_req->qtcb;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 1);
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
- bottom = &qtcb->bottom.port;
- data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
- if (data)
- memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
- fc_host_permanent_port_name(shost) = bottom->wwpn;
- else
- fc_host_permanent_port_name(shost) =
- fc_host_port_name(shost);
- fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
- fc_host_supported_speeds(shost) = bottom->supported_speed;
break;
-
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
zfcp_fsf_link_down_info_eval(adapter,
&qtcb->header.fsf_status_qual.link_down_info);
break;
-
default:
debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
debug_event(adapter->erp_dbf, 0,
@@ -4203,11 +4211,11 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
if (scpnt->result != 0)
- zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req);
else if (scpnt->retries > 0)
- zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req);
else
- zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req);
/* cleanup pointer (need this especially for abort) */
scpnt->host_scribble = NULL;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e0803757c0fa..9e6d07d7b3c8 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -68,7 +68,7 @@ struct zfcp_data zfcp_data = {
eh_host_reset_handler: zfcp_scsi_eh_host_reset_handler,
/* FIXME(openfcp): Tune */
can_queue: 4096,
- this_id: 0,
+ this_id: -1,
/*
* FIXME:
* one less? can zfcp_create_sbale cope with it?
@@ -183,7 +183,8 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp)
read_lock_irqsave(&zfcp_data.config_lock, flags);
unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun);
- if (unit) {
+ if (unit && atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED,
+ &unit->status)) {
sdp->hostdata = unit;
unit->device = sdp;
zfcp_unit_get(unit);
@@ -208,6 +209,7 @@ zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
if (unit) {
+ atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
sdpnt->hostdata = NULL;
unit->device = NULL;
zfcp_unit_put(unit);
@@ -242,7 +244,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
zfcp_scsi_dbf_event_result("fail", 4,
(struct zfcp_adapter*) scpnt->device->host->hostdata[0],
- scpnt);
+ scpnt, NULL);
/* return directly */
scpnt->scsi_done(scpnt);
}
@@ -291,7 +293,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
"on port 0x%016Lx in recovery\n",
zfcp_get_busid_by_unit(unit),
unit->fcp_lun, unit->port->wwpn);
- retval = SCSI_MLQUEUE_DEVICE_BUSY;
+ zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT);
goto out;
}
@@ -446,7 +448,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
if (!old_fsf_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
retval = SUCCESS;
goto out;
}
@@ -460,6 +462,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
adapter, unit, 0);
if (!new_fsf_req) {
ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
+ zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
+ old_fsf_req);
retval = FAILED;
goto out;
}
@@ -470,13 +474,16 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* status should be valid since signals were not permitted */
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
- zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
+ NULL);
retval = SUCCESS;
} else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
- zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
+ NULL);
retval = SUCCESS;
} else {
- zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
+ NULL);
retval = FAILED;
}
zfcp_fsf_req_free(new_fsf_req);
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index dfc07370f412..b29ac25e07f3 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -55,8 +55,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
-ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
-ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
@@ -241,8 +239,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_peer_wwnn.attr,
&dev_attr_peer_wwpn.attr,
&dev_attr_peer_d_id.attr,
- &dev_attr_physical_wwpn.attr,
- &dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.attr,
&dev_attr_status.attr,
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 31c497542272..d9152d02088c 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -61,6 +61,7 @@
Add support for embedded firmware error strings.
2.26.02.003 - Correctly handle single sgl's with use_sg=1.
2.26.02.004 - Add support for 9550SX controllers.
+ 2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
*/
#include <linux/module.h>
@@ -84,7 +85,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.004"
+#define TW_DRIVER_VERSION "2.26.02.005"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -1408,7 +1409,7 @@ static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int requ
dma_addr_t mapping;
struct scsi_cmnd *cmd = tw_dev->srb[request_id];
struct pci_dev *pdev = tw_dev->tw_pci_dev;
- int retval = 0;
+ dma_addr_t retval = 0;
if (cmd->request_bufflen == 0) {
retval = 0;
@@ -1798,7 +1799,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
int i, sg_count;
struct scsi_cmnd *srb = NULL;
struct scatterlist *sglist = NULL;
- u32 buffaddr = 0x0;
+ dma_addr_t buffaddr = 0x0;
int retval = 1;
if (tw_dev->srb[request_id]) {
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 7139659dd952..a16f8ded8f1d 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -173,10 +173,10 @@ int aac_get_config_status(struct aac_dev *dev)
int status = 0;
struct fib * fibptr;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
{
struct aac_get_config_status *dinfo;
dinfo = (struct aac_get_config_status *) fib_data(fibptr);
@@ -186,7 +186,7 @@ int aac_get_config_status(struct aac_dev *dev)
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));
}
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_get_config_status),
FsaNormal,
@@ -209,30 +209,30 @@ int aac_get_config_status(struct aac_dev *dev)
status = -EINVAL;
}
}
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
if (status >= 0) {
if (commit == 1) {
struct aac_commit_config * dinfo;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_commit_config *) fib_data(fibptr);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_commit_config),
FsaNormal,
1, 1,
NULL, NULL);
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
} else if (commit == 0) {
printk(KERN_WARNING
"aac_get_config_status: Foreign device configurations are being ignored\n");
}
}
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return status;
}
@@ -255,15 +255,15 @@ int aac_get_containers(struct aac_dev *dev)
instance = dev->scsi_host_ptr->unique_id;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_get_container_count *) fib_data(fibptr);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_get_container_count),
FsaNormal,
@@ -272,7 +272,7 @@ int aac_get_containers(struct aac_dev *dev)
if (status >= 0) {
dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
}
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
@@ -280,7 +280,7 @@ int aac_get_containers(struct aac_dev *dev)
fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
if (!fsa_dev_ptr) {
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return -ENOMEM;
}
memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
@@ -294,14 +294,14 @@ int aac_get_containers(struct aac_dev *dev)
fsa_dev_ptr[index].devname[0] = '\0';
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_query_mount *) fib_data(fibptr);
dinfo->command = cpu_to_le32(VM_NameServe);
dinfo->count = cpu_to_le32(index);
dinfo->type = cpu_to_le32(FT_FILESYS);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_query_mount),
FsaNormal,
@@ -319,7 +319,7 @@ int aac_get_containers(struct aac_dev *dev)
dinfo->count = cpu_to_le32(index);
dinfo->type = cpu_to_le32(FT_FILESYS);
- if (fib_send(ContainerCommand,
+ if (aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
@@ -347,7 +347,7 @@ int aac_get_containers(struct aac_dev *dev)
if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
fsa_dev_ptr[index].ro = 1;
}
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
/*
* If there are no more containers, then stop asking.
*/
@@ -355,7 +355,7 @@ int aac_get_containers(struct aac_dev *dev)
break;
}
}
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return status;
}
@@ -413,8 +413,8 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@@ -430,10 +430,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- if (!(cmd_fibcontext = fib_alloc(dev)))
+ if (!(cmd_fibcontext = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
@@ -441,7 +441,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
dinfo->cid = cpu_to_le32(cid);
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
sizeof (struct aac_get_name),
FsaNormal,
@@ -455,14 +455,14 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
if (status == -EINPROGRESS)
return 0;
- printk(KERN_WARNING "aac_get_container_name: fib_send failed with status: %d.\n", status);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return -1;
}
/**
- * probe_container - query a logical volume
+ * aac_probe_container - query a logical volume
* @dev: device to query
* @cid: container identifier
*
@@ -470,7 +470,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
* is updated in the struct fsa_dev_info structure rather than returned.
*/
-int probe_container(struct aac_dev *dev, int cid)
+int aac_probe_container(struct aac_dev *dev, int cid)
{
struct fsa_dev_info *fsa_dev_ptr;
int status;
@@ -482,10 +482,10 @@ int probe_container(struct aac_dev *dev, int cid)
fsa_dev_ptr = dev->fsa_dev;
instance = dev->scsi_host_ptr->unique_id;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_query_mount *)fib_data(fibptr);
@@ -493,14 +493,14 @@ int probe_container(struct aac_dev *dev, int cid)
dinfo->count = cpu_to_le32(cid);
dinfo->type = cpu_to_le32(FT_FILESYS);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
1, 1,
NULL, NULL);
if (status < 0) {
- printk(KERN_WARNING "aacraid: probe_container query failed.\n");
+ printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
goto error;
}
@@ -512,7 +512,7 @@ int probe_container(struct aac_dev *dev, int cid)
dinfo->count = cpu_to_le32(cid);
dinfo->type = cpu_to_le32(FT_FILESYS);
- if (fib_send(ContainerCommand,
+ if (aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
@@ -535,8 +535,8 @@ int probe_container(struct aac_dev *dev, int cid)
}
error:
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
return status;
}
@@ -700,14 +700,14 @@ int aac_get_adapter_info(struct aac_dev* dev)
struct aac_bus_info *command;
struct aac_bus_info_response *bus_info;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
info = (struct aac_adapter_info *) fib_data(fibptr);
memset(info,0,sizeof(*info));
- rcode = fib_send(RequestAdapterInfo,
+ rcode = aac_fib_send(RequestAdapterInfo,
fibptr,
sizeof(*info),
FsaNormal,
@@ -716,8 +716,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
NULL);
if (rcode < 0) {
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
return rcode;
}
memcpy(&dev->adapter_info, info, sizeof(*info));
@@ -725,13 +725,13 @@ int aac_get_adapter_info(struct aac_dev* dev)
if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
struct aac_supplement_adapter_info * info;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
memset(info,0,sizeof(*info));
- rcode = fib_send(RequestSupplementAdapterInfo,
+ rcode = aac_fib_send(RequestSupplementAdapterInfo,
fibptr,
sizeof(*info),
FsaNormal,
@@ -748,7 +748,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
* GetBusInfo
*/
- fib_init(fibptr);
+ aac_fib_init(fibptr);
bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
@@ -761,7 +761,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
command->MethodId = cpu_to_le32(1);
command->CtlCmd = cpu_to_le32(GetBusInfo);
- rcode = fib_send(ContainerCommand,
+ rcode = aac_fib_send(ContainerCommand,
fibptr,
sizeof (*bus_info),
FsaNormal,
@@ -891,8 +891,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
}
}
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
return rcode;
}
@@ -976,8 +976,8 @@ static void io_callback(void *context, struct fib * fibptr)
? sizeof(scsicmd->sense_buffer)
: sizeof(dev->fsa_dev[cid].sense_data));
}
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@@ -1062,11 +1062,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Alocate and initialize a Fib
*/
- if (!(cmd_fibcontext = fib_alloc(dev))) {
+ if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
return -1;
}
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
if (dev->raw_io_interface) {
struct aac_raw_io *readcmd;
@@ -1086,7 +1086,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerRawIo,
+ status = aac_fib_send(ContainerRawIo,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1112,7 +1112,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand64,
+ status = aac_fib_send(ContainerCommand64,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1136,7 +1136,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1153,14 +1153,14 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
if (status == -EINPROGRESS)
return 0;
- printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
+ printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
/*
* For some reason, the Fib didn't queue, return QUEUE_FULL
*/
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
scsicmd->scsi_done(scsicmd);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return 0;
}
@@ -1228,12 +1228,12 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
- if (!(cmd_fibcontext = fib_alloc(dev))) {
+ if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
scsicmd->result = DID_ERROR << 16;
scsicmd->scsi_done(scsicmd);
return 0;
}
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
if (dev->raw_io_interface) {
struct aac_raw_io *writecmd;
@@ -1253,7 +1253,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerRawIo,
+ status = aac_fib_send(ContainerRawIo,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1279,7 +1279,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand64,
+ status = aac_fib_send(ContainerCommand64,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1305,7 +1305,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1322,15 +1322,15 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
return 0;
}
- printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);
+ printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
/*
* For some reason, the Fib didn't queue, return QUEUE_FULL
*/
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
scsicmd->scsi_done(scsicmd);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return 0;
}
@@ -1369,8 +1369,8 @@ static void synchronize_callback(void *context, struct fib *fibptr)
sizeof(cmd->sense_buffer)));
}
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
cmd->scsi_done(cmd);
}
@@ -1407,10 +1407,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
* Allocate and initialize a Fib
*/
if (!(cmd_fibcontext =
- fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
+ aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
return SCSI_MLQUEUE_HOST_BUSY;
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
synchronizecmd = fib_data(cmd_fibcontext);
synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
@@ -1422,7 +1422,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
sizeof(struct aac_synchronize),
FsaNormal,
@@ -1437,9 +1437,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
return 0;
printk(KERN_WARNING
- "aac_synchronize: fib_send failed with status: %d.\n", status);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ "aac_synchronize: aac_fib_send failed with status: %d.\n", status);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return SCSI_MLQUEUE_HOST_BUSY;
}
@@ -1465,7 +1465,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* itself.
*/
if (scmd_id(scsicmd) != host->this_id) {
- if ((scsicmd->device->channel == 0) ){
+ if ((scsicmd->device->channel == CONTAINER_CHANNEL)) {
if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
@@ -1488,7 +1488,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case READ_CAPACITY:
case TEST_UNIT_READY:
spin_unlock_irq(host->host_lock);
- probe_container(dev, cid);
+ aac_probe_container(dev, cid);
if ((fsa_dev_ptr[cid].valid & 1) == 0)
fsa_dev_ptr[cid].valid = 0;
spin_lock_irq(host->host_lock);
@@ -1935,33 +1935,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
case SRB_STATUS_ERROR_RECOVERY:
case SRB_STATUS_PENDING:
case SRB_STATUS_SUCCESS:
- if(scsicmd->cmnd[0] == INQUIRY ){
- u8 b;
- u8 b1;
- /* We can't expose disk devices because we can't tell whether they
- * are the raw container drives or stand alone drives. If they have
- * the removable bit set then we should expose them though.
- */
- b = (*(u8*)scsicmd->buffer)&0x1f;
- b1 = ((u8*)scsicmd->buffer)[1];
- if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
- || (b==TYPE_DISK && (b1&0x80)) ){
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- /*
- * We will allow disk devices if in RAID/SCSI mode and
- * the channel is 2
- */
- } else if ((dev->raid_scsi_mode) &&
- (scmd_channel(scsicmd) == 2)) {
- scsicmd->result = DID_OK << 16 |
- COMMAND_COMPLETE << 8;
- } else {
- scsicmd->result = DID_NO_CONNECT << 16 |
- COMMAND_COMPLETE << 8;
- }
- } else {
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- }
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break;
case SRB_STATUS_DATA_OVERRUN:
switch(scsicmd->cmnd[0]){
@@ -1981,28 +1955,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
break;
case INQUIRY: {
- u8 b;
- u8 b1;
- /* We can't expose disk devices because we can't tell whether they
- * are the raw container drives or stand alone drives
- */
- b = (*(u8*)scsicmd->buffer)&0x0f;
- b1 = ((u8*)scsicmd->buffer)[1];
- if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
- || (b==TYPE_DISK && (b1&0x80)) ){
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- /*
- * We will allow disk devices if in RAID/SCSI mode and
- * the channel is 2
- */
- } else if ((dev->raid_scsi_mode) &&
- (scmd_channel(scsicmd) == 2)) {
- scsicmd->result = DID_OK << 16 |
- COMMAND_COMPLETE << 8;
- } else {
- scsicmd->result = DID_NO_CONNECT << 16 |
- COMMAND_COMPLETE << 8;
- }
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break;
}
default:
@@ -2089,8 +2042,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
*/
scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@@ -2142,10 +2095,10 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
- if (!(cmd_fibcontext = fib_alloc(dev))) {
+ if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
return -1;
}
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
@@ -2179,7 +2132,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ScsiPortCommand64, cmd_fibcontext,
+ status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext,
fibsize, FsaNormal, 0, 1,
(fib_callback) aac_srb_callback,
(void *) scsicmd);
@@ -2201,7 +2154,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
+ status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
(fib_callback) aac_srb_callback, (void *) scsicmd);
}
/*
@@ -2211,9 +2164,9 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
return 0;
}
- printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return -1;
}
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 66dbb6d2c506..2d430b7e8cf4 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1774,16 +1774,16 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
struct scsi_cmnd;
const char *aac_driverinfo(struct Scsi_Host *);
-struct fib *fib_alloc(struct aac_dev *dev);
-int fib_setup(struct aac_dev *dev);
-void fib_map_free(struct aac_dev *dev);
-void fib_free(struct fib * context);
-void fib_init(struct fib * context);
+struct fib *aac_fib_alloc(struct aac_dev *dev);
+int aac_fib_setup(struct aac_dev *dev);
+void aac_fib_map_free(struct aac_dev *dev);
+void aac_fib_free(struct fib * context);
+void aac_fib_init(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
-int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
+int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
-int fib_complete(struct fib * context);
+int aac_fib_complete(struct fib * context);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
int aac_get_config_status(struct aac_dev *dev);
@@ -1799,11 +1799,11 @@ unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
int aac_command_thread(struct aac_dev * dev);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
-int fib_adapter_complete(struct fib * fibptr, unsigned short size);
+int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
-int probe_container(struct aac_dev *dev, int cid);
+int aac_probe_container(struct aac_dev *dev, int cid);
extern int numacb;
extern int acbsize;
extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 4fe79cd7c957..47fefca72695 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
unsigned size;
int retval;
- fibptr = fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev);
if(fibptr == NULL) {
return -ENOMEM;
}
@@ -73,7 +73,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* First copy in the header so that we can check the size field.
*/
if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) {
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return -EFAULT;
}
/*
@@ -110,13 +110,13 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
*/
kfib->header.XferState = 0;
} else {
- retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
+ retval = aac_fib_send(le16_to_cpu(kfib->header.Command), fibptr,
le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL);
if (retval) {
goto cleanup;
}
- if (fib_complete(fibptr) != 0) {
+ if (aac_fib_complete(fibptr) != 0) {
retval = -EINVAL;
goto cleanup;
}
@@ -138,7 +138,7 @@ cleanup:
fibptr->hw_fib_pa = hw_fib_pa;
fibptr->hw_fib = hw_fib;
}
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return retval;
}
@@ -464,10 +464,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
- if (!(srbfib = fib_alloc(dev))) {
+ if (!(srbfib = aac_fib_alloc(dev))) {
return -ENOMEM;
}
- fib_init(srbfib);
+ aac_fib_init(srbfib);
srbcmd = (struct aac_srb*) fib_data(srbfib);
@@ -601,7 +601,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
srbcmd->count = cpu_to_le32(byte_count);
psg->count = cpu_to_le32(sg_indx+1);
- status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
+ status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
} else {
struct user_sgmap* upsg = &user_srbcmd->sg;
struct sgmap* psg = &srbcmd->sg;
@@ -649,7 +649,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
srbcmd->count = cpu_to_le32(byte_count);
psg->count = cpu_to_le32(sg_indx+1);
- status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
+ status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
}
if (status != 0){
@@ -684,8 +684,8 @@ cleanup:
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
- fib_complete(srbfib);
- fib_free(srbfib);
+ aac_fib_complete(srbfib);
+ aac_fib_free(srbfib);
return rcode;
}
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 82821d331c07..1628d094943d 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -185,17 +185,17 @@ int aac_send_shutdown(struct aac_dev * dev)
struct aac_close *cmd;
int status;
- fibctx = fib_alloc(dev);
+ fibctx = aac_fib_alloc(dev);
if (!fibctx)
return -ENOMEM;
- fib_init(fibctx);
+ aac_fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx);
cmd->command = cpu_to_le32(VM_CloseAll);
cmd->cid = cpu_to_le32(0xffffffff);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibctx,
sizeof(struct aac_close),
FsaNormal,
@@ -203,8 +203,8 @@ int aac_send_shutdown(struct aac_dev * dev)
NULL, NULL);
if (status == 0)
- fib_complete(fibctx);
- fib_free(fibctx);
+ aac_fib_complete(fibctx);
+ aac_fib_free(fibctx);
return status;
}
@@ -427,7 +427,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
/*
* Initialize the list of fibs
*/
- if(fib_setup(dev)<0){
+ if (aac_fib_setup(dev) < 0) {
kfree(dev->queues);
return NULL;
}
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 38d6d00fb0fc..609fd19b1844 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -38,10 +38,10 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
+#include <linux/delay.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <asm/semaphore.h>
-#include <asm/delay.h>
#include "aacraid.h"
@@ -67,27 +67,27 @@ static int fib_map_alloc(struct aac_dev *dev)
}
/**
- * fib_map_free - free the fib objects
+ * aac_fib_map_free - free the fib objects
* @dev: Adapter to free
*
* Free the PCI mappings and the memory allocated for FIB blocks
* on this adapter.
*/
-void fib_map_free(struct aac_dev *dev)
+void aac_fib_map_free(struct aac_dev *dev)
{
pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
}
/**
- * fib_setup - setup the fibs
+ * aac_fib_setup - setup the fibs
* @dev: Adapter to set up
*
* Allocate the PCI space for the fibs, map it and then intialise the
* fib area, the unmapped fib data and also the free list
*/
-int fib_setup(struct aac_dev * dev)
+int aac_fib_setup(struct aac_dev * dev)
{
struct fib *fibptr;
struct hw_fib *hw_fib_va;
@@ -134,14 +134,14 @@ int fib_setup(struct aac_dev * dev)
}
/**
- * fib_alloc - allocate a fib
+ * aac_fib_alloc - allocate a fib
* @dev: Adapter to allocate the fib for
*
* Allocate a fib from the adapter fib pool. If the pool is empty we
* return NULL.
*/
-struct fib * fib_alloc(struct aac_dev *dev)
+struct fib *aac_fib_alloc(struct aac_dev *dev)
{
struct fib * fibptr;
unsigned long flags;
@@ -170,14 +170,14 @@ struct fib * fib_alloc(struct aac_dev *dev)
}
/**
- * fib_free - free a fib
+ * aac_fib_free - free a fib
* @fibptr: fib to free up
*
* Frees up a fib and places it on the appropriate queue
* (either free or timed out)
*/
-void fib_free(struct fib * fibptr)
+void aac_fib_free(struct fib *fibptr)
{
unsigned long flags;
@@ -188,7 +188,7 @@ void fib_free(struct fib * fibptr)
fibptr->dev->timeout_fib = fibptr;
} else {
if (fibptr->hw_fib->header.XferState != 0) {
- printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
+ printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
(void*)fibptr,
le32_to_cpu(fibptr->hw_fib->header.XferState));
}
@@ -199,13 +199,13 @@ void fib_free(struct fib * fibptr)
}
/**
- * fib_init - initialise a fib
+ * aac_fib_init - initialise a fib
* @fibptr: The fib to initialize
*
* Set up the generic fib fields ready for use
*/
-void fib_init(struct fib *fibptr)
+void aac_fib_init(struct fib *fibptr)
{
struct hw_fib *hw_fib = fibptr->hw_fib;
@@ -362,7 +362,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
*/
/**
- * fib_send - send a fib to the adapter
+ * aac_fib_send - send a fib to the adapter
* @command: Command to send
* @fibptr: The fib
* @size: Size of fib data area
@@ -378,7 +378,9 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
* response FIB is received from the adapter.
*/
-int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
+int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
+ int priority, int wait, int reply, fib_callback callback,
+ void *callback_data)
{
struct aac_dev * dev = fibptr->dev;
struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -493,7 +495,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
q->numpending++;
*(q->headers.producer) = cpu_to_le32(index + 1);
spin_unlock_irqrestore(q->lock, qflags);
- dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
+ dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index));
if (!(nointr & aac_config.irq_mod))
aac_adapter_notify(dev, AdapNormCmdQueue);
}
@@ -520,7 +522,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
list_del(&fibptr->queue);
spin_unlock_irqrestore(q->lock, qflags);
if (wait == -1) {
- printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n"
+ printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n"
"Usually a result of a PCI interrupt routing problem;\n"
"update mother board BIOS or consider utilizing one of\n"
"the SAFE mode kernel options (acpi, apic etc)\n");
@@ -624,7 +626,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
}
/**
- * fib_adapter_complete - complete adapter issued fib
+ * aac_fib_adapter_complete - complete adapter issued fib
* @fibptr: fib to complete
* @size: size of fib
*
@@ -632,7 +634,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
* the adapter.
*/
-int fib_adapter_complete(struct fib * fibptr, unsigned short size)
+int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_dev * dev = fibptr->dev;
@@ -683,20 +685,20 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
}
else
{
- printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n");
+ printk(KERN_WARNING "aac_fib_adapter_complete: Unknown xferstate detected.\n");
BUG();
}
return 0;
}
/**
- * fib_complete - fib completion handler
+ * aac_fib_complete - fib completion handler
* @fib: FIB to complete
*
* Will do all necessary work to complete a FIB.
*/
-int fib_complete(struct fib * fibptr)
+int aac_fib_complete(struct fib *fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -995,14 +997,14 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (!dev || !dev->scsi_host_ptr)
return;
/*
- * force reload of disk info via probe_container
+ * force reload of disk info via aac_probe_container
*/
if ((device_config_needed == CHANGE)
&& (dev->fsa_dev[container].valid == 1))
dev->fsa_dev[container].valid = 2;
if ((device_config_needed == CHANGE) ||
(device_config_needed == ADD))
- probe_container(dev, container);
+ aac_probe_container(dev, container);
device = scsi_device_lookup(dev->scsi_host_ptr,
CONTAINER_TO_CHANNEL(container),
CONTAINER_TO_ID(container),
@@ -1104,7 +1106,7 @@ int aac_command_thread(struct aac_dev * dev)
/* Handle Driver Notify Events */
aac_handle_aif(dev, fib);
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, (u16)sizeof(u32));
+ aac_fib_adapter_complete(fib, (u16)sizeof(u32));
} else {
struct list_head *entry;
/* The u32 here is important and intended. We are using
@@ -1241,7 +1243,7 @@ int aac_command_thread(struct aac_dev * dev)
* Set the status of this FIB
*/
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, sizeof(u32));
+ aac_fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
/* Free up the remaining resources */
hw_fib_p = hw_fib_pool;
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 439948ef8251..f6bcb9486f85 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -206,7 +206,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
* Set the status of this FIB
*/
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, sizeof(u32));
+ aac_fib_adapter_complete(fib, sizeof(u32));
spin_lock_irqsave(q->lock, flags);
}
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 0bf5f9a943e8..271617890562 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -385,17 +385,45 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
static int aac_slave_configure(struct scsi_device *sdev)
{
- struct Scsi_Host *host = sdev->host;
+ if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
+ sdev->skip_ms_page_8 = 1;
+ sdev->skip_ms_page_3f = 1;
+ }
+ if ((sdev->type == TYPE_DISK) &&
+ (sdev_channel(sdev) != CONTAINER_CHANNEL)) {
+ struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
+ if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
+ sdev->no_uld_attach = 1;
+ }
+ if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
+ (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+ struct scsi_device * dev;
+ struct Scsi_Host *host = sdev->host;
+ unsigned num_lsu = 0;
+ unsigned num_one = 0;
+ unsigned depth;
- if (sdev->tagged_supported)
- scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
- else
+ __shost_for_each_device(dev, host) {
+ if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
+ (sdev_channel(dev) == CONTAINER_CHANNEL))
+ ++num_lsu;
+ else
+ ++num_one;
+ }
+ if (num_lsu == 0)
+ ++num_lsu;
+ depth = (host->can_queue - num_one) / num_lsu;
+ if (depth > 256)
+ depth = 256;
+ else if (depth < 2)
+ depth = 2;
+ scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+ if (!(((struct aac_dev *)host->hostdata)->adapter_info.options &
+ AAC_OPT_NEW_COMM))
+ blk_queue_max_segment_size(sdev->request_queue, 65536);
+ } else
scsi_adjust_queue_depth(sdev, 0, 1);
- if (!(((struct aac_dev *)host->hostdata)->adapter_info.options
- & AAC_OPT_NEW_COMM))
- blk_queue_max_segment_size(sdev->request_queue, 65536);
-
return 0;
}
@@ -870,7 +898,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
/*
* max channel will be the physical channels plus 1 virtual channel
- * all containers are on the virtual channel 0
+ * all containers are on the virtual channel 0 (CONTAINER_CHANNEL)
* physical channels are address by their actual physical number+1
*/
if (aac->nondasd_support == 1)
@@ -913,7 +941,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_adapter_disable_int(aac);
free_irq(pdev->irq, aac);
out_unmap:
- fib_map_free(aac);
+ aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues);
iounmap(aac->regs.sa);
@@ -947,7 +975,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
aac_send_shutdown(aac);
aac_adapter_disable_int(aac);
- fib_map_free(aac);
+ aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
aac->comm_phys);
kfree(aac->queues);
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index cb2ee25f213f..531a1f9ceb51 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1260,16 +1260,15 @@ static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
* Reset the bus
*
*/
-static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
+static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
{
- struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags;
DO_LOCK(flags);
#if defined(AHA152X_DEBUG)
if(HOSTDATA(shpnt)->debug & debug_eh) {
- printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt);
+ printk(KERN_DEBUG "scsi%d: bus reset", shpnt->host_no);
show_queues(shpnt);
}
#endif
@@ -1277,14 +1276,14 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
free_hard_reset_SCs(shpnt, &ISSUE_SC);
free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
- DPRINTK(debug_eh, DEBUG_LEAD "resetting bus\n", CMDINFO(SCpnt));
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting bus\n", shpnt->host_no);
SETPORT(SCSISEQ, SCSIRSTO);
mdelay(256);
SETPORT(SCSISEQ, 0);
mdelay(DELAY);
- DPRINTK(debug_eh, DEBUG_LEAD "bus resetted\n", CMDINFO(SCpnt));
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: bus resetted\n", shpnt->host_no);
setup_expected_interrupts(shpnt);
if(HOSTDATA(shpnt)->commands==0)
@@ -1295,6 +1294,14 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
return SUCCESS;
}
+/*
+ * Reset the bus
+ *
+ */
+static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
+{
+ return aha152x_bus_reset_host(SCpnt->device->host);
+}
/*
* Restore default values to the AIC-6260 registers and reset the fifos
@@ -1337,23 +1344,28 @@ static void reset_ports(struct Scsi_Host *shpnt)
* Reset the host (bus and controller)
*
*/
-int aha152x_host_reset(Scsi_Cmnd * SCpnt)
+int aha152x_host_reset_host(struct Scsi_Host *shpnt)
{
-#if defined(AHA152X_DEBUG)
- struct Scsi_Host *shpnt = SCpnt->device->host;
-#endif
-
- DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt);
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: host reset\n", shpnt->host_no);
- aha152x_bus_reset(SCpnt);
+ aha152x_bus_reset_host(shpnt);
- DPRINTK(debug_eh, DEBUG_LEAD "resetting ports\n", CMDINFO(SCpnt));
- reset_ports(SCpnt->device->host);
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting ports\n", shpnt->host_no);
+ reset_ports(shpnt);
return SUCCESS;
}
/*
+ * Reset the host (bus and controller)
+ *
+ */
+static int aha152x_host_reset(Scsi_Cmnd *SCpnt)
+{
+ return aha152x_host_reset_host(SCpnt->device->host);
+}
+
+/*
* Return the "logical geometry"
*
*/
@@ -1431,22 +1443,18 @@ static void run(void)
{
int i;
for (i = 0; i<ARRAY_SIZE(aha152x_host); i++) {
- struct Scsi_Host *shpnt = aha152x_host[i];
- if (shpnt && HOSTDATA(shpnt)->service) {
- HOSTDATA(shpnt)->service=0;
- is_complete(shpnt);
- }
+ is_complete(aha152x_host[i]);
}
}
/*
- * Interrupts handler
+ * Interrupt handler
*
*/
-
static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
{
struct Scsi_Host *shpnt = lookup_irq(irqno);
+ unsigned long flags;
unsigned char rev, dmacntrl0;
if (!shpnt) {
@@ -1472,23 +1480,23 @@ static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
return IRQ_NONE;
+ if( TESTLO(DMASTAT, INTSTAT) )
+ return IRQ_NONE;
+
/* no more interrupts from the controller, while we're busy.
INTEN is restored by the BH handler */
CLRBITS(DMACNTRL0, INTEN);
-#if 0
- /* check if there is already something to be
- serviced; should not happen */
- if(HOSTDATA(shpnt)->service) {
- printk(KERN_ERR "aha152x%d: lost interrupt (%d)\n", HOSTNO, HOSTDATA(shpnt)->service);
- show_queues(shpnt);
+ DO_LOCK(flags);
+ if( HOSTDATA(shpnt)->service==0 ) {
+ HOSTDATA(shpnt)->service=1;
+
+ /* Poke the BH handler */
+ INIT_WORK(&aha152x_tq, (void *) run, NULL);
+ schedule_work(&aha152x_tq);
}
-#endif
-
- /* Poke the BH handler */
- HOSTDATA(shpnt)->service++;
- INIT_WORK(&aha152x_tq, (void *) run, NULL);
- schedule_work(&aha152x_tq);
+ DO_UNLOCK(flags);
+
return IRQ_HANDLED;
}
@@ -2527,7 +2535,18 @@ static void is_complete(struct Scsi_Host *shpnt)
unsigned long flags;
int pending;
+ if(!shpnt)
+ return;
+
DO_LOCK(flags);
+
+ if( HOSTDATA(shpnt)->service==0 ) {
+ DO_UNLOCK(flags);
+ return;
+ }
+
+ HOSTDATA(shpnt)->service = 0;
+
if(HOSTDATA(shpnt)->in_intr) {
DO_UNLOCK(flags);
/* aha152x_error never returns.. */
diff --git a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h
index d277613af29b..d2add24d02a3 100644
--- a/drivers/scsi/aha152x.h
+++ b/drivers/scsi/aha152x.h
@@ -332,6 +332,6 @@ struct aha152x_setup {
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *);
void aha152x_release(struct Scsi_Host *);
-int aha152x_host_reset(Scsi_Cmnd *);
+int aha152x_host_reset_host(struct Scsi_Host *);
#endif /* _AHA152X_H */
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index a800fb51168b..559ff7aae3f1 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -742,23 +742,17 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!ahci_host_intr(ap, qc))
- if (ata_ratelimit()) {
- struct pci_dev *pdev =
- to_pci_dev(ap->host_set->dev);
- dev_printk(KERN_WARNING, &pdev->dev,
+ if (ata_ratelimit())
+ dev_printk(KERN_WARNING, host_set->dev,
"unhandled interrupt on port %u\n",
i);
- }
VPRINTK("port %u\n", i);
} else {
VPRINTK("port %u (no irq)\n", i);
- if (ata_ratelimit()) {
- struct pci_dev *pdev =
- to_pci_dev(ap->host_set->dev);
- dev_printk(KERN_WARNING, &pdev->dev,
+ if (ata_ratelimit())
+ dev_printk(KERN_WARNING, host_set->dev,
"interrupt on disabled port %u\n", i);
- }
}
irq_ack |= (1 << i);
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index f6900538be90..87a8c3d2072c 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -2068,14 +2068,12 @@ static int esp_reset(struct scsi_cmnd *SCptr)
{
struct esp *esp = (struct esp *) SCptr->device->host->hostdata;
+ spin_lock_irq(esp->ehost->host_lock);
(void) esp_do_resetbus(esp);
-
spin_unlock_irq(esp->ehost->host_lock);
wait_event(esp->reset_queue, (esp->resetting_bus == 0));
- spin_lock_irq(esp->ehost->host_lock);
-
return SUCCESS;
}
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index bd3ffdf6c800..62e3cda859af 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2816,7 +2816,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
}
#endif
- } else {
+ } else if (scp->request_bufflen) {
scp->SCp.Status = GDTH_MAP_SINGLE;
scp->SCp.Message = (read_write == 1 ?
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 27acf78cf8d8..2bba5e55d7bc 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -4236,35 +4236,6 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
}
/**
- * ipr_save_ioafp_mode_select - Save adapters mode select data
- * @ioa_cfg: ioa config struct
- * @scsi_cmd: scsi command struct
- *
- * This function saves mode select data for the adapter to
- * use following an adapter reset.
- *
- * Return value:
- * 0 on success / SCSI_MLQUEUE_HOST_BUSY on failure
- **/
-static int ipr_save_ioafp_mode_select(struct ipr_ioa_cfg *ioa_cfg,
- struct scsi_cmnd *scsi_cmd)
-{
- if (!ioa_cfg->saved_mode_pages) {
- ioa_cfg->saved_mode_pages = kmalloc(sizeof(struct ipr_mode_pages),
- GFP_ATOMIC);
- if (!ioa_cfg->saved_mode_pages) {
- dev_err(&ioa_cfg->pdev->dev,
- "IOA mode select buffer allocation failed\n");
- return SCSI_MLQUEUE_HOST_BUSY;
- }
- }
-
- memcpy(ioa_cfg->saved_mode_pages, scsi_cmd->buffer, scsi_cmd->cmnd[4]);
- ioa_cfg->saved_mode_page_len = scsi_cmd->cmnd[4];
- return 0;
-}
-
-/**
* ipr_queuecommand - Queue a mid-layer request
* @scsi_cmd: scsi command struct
* @done: done function
@@ -4338,9 +4309,6 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
(!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE))
ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
- if (ipr_is_ioa_resource(res) && scsi_cmd->cmnd[0] == MODE_SELECT)
- rc = ipr_save_ioafp_mode_select(ioa_cfg, scsi_cmd);
-
if (likely(rc == 0))
rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
@@ -4829,17 +4797,11 @@ static int ipr_ioafp_mode_select_page28(struct ipr_cmnd *ipr_cmd)
int length;
ENTER;
- if (ioa_cfg->saved_mode_pages) {
- memcpy(mode_pages, ioa_cfg->saved_mode_pages,
- ioa_cfg->saved_mode_page_len);
- length = ioa_cfg->saved_mode_page_len;
- } else {
- ipr_scsi_bus_speed_limit(ioa_cfg);
- ipr_check_term_power(ioa_cfg, mode_pages);
- ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages);
- length = mode_pages->hdr.length + 1;
- mode_pages->hdr.length = 0;
- }
+ ipr_scsi_bus_speed_limit(ioa_cfg);
+ ipr_check_term_power(ioa_cfg, mode_pages);
+ ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages);
+ length = mode_pages->hdr.length + 1;
+ mode_pages->hdr.length = 0;
ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11,
ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages),
@@ -5969,7 +5931,6 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
}
ipr_free_dump(ioa_cfg);
- kfree(ioa_cfg->saved_mode_pages);
kfree(ioa_cfg->trace);
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index b639332131f1..fd360bfe56dd 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.1"
-#define IPR_DRIVER_DATE "(November 15, 2005)"
+#define IPR_DRIVER_VERSION "2.1.2"
+#define IPR_DRIVER_DATE "(February 8, 2006)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -1000,7 +1000,6 @@ struct ipr_ioa_cfg {
struct Scsi_Host *host;
struct pci_dev *pdev;
struct ipr_sglist *ucode_sglist;
- struct ipr_mode_pages *saved_mode_pages;
u8 saved_mode_page_len;
struct work_struct work_q;
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 780bfcc67096..ff79e68b347c 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -146,7 +146,7 @@ iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
spin_unlock_irqrestore(&session->lock, flags);
set_bit(SUSPEND_BIT, &conn->suspend_tx);
set_bit(SUSPEND_BIT, &conn->suspend_rx);
- iscsi_conn_error(iscsi_handle(conn), err);
+ iscsi_conn_error(conn->cls_conn, err);
}
static inline int
@@ -244,12 +244,10 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
if (sc->sc_data_direction == DMA_TO_DEVICE) {
struct iscsi_data_task *dtask, *n;
/* WRITE: cleanup Data-Out's if any */
- spin_lock(&conn->lock);
list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
list_del(&dtask->item);
mempool_free(dtask, ctask->datapool);
}
- spin_unlock(&conn->lock);
}
ctask->xmstate = XMSTATE_IDLE;
ctask->r2t = NULL;
@@ -689,7 +687,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
break;
if (!conn->in.datalen) {
- rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
+ rc = iscsi_recv_pdu(conn->cls_conn, hdr,
NULL, 0);
if (conn->login_mtask != mtask) {
spin_lock(&session->lock);
@@ -737,7 +735,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
if (!conn->in.datalen) {
struct iscsi_mgmt_task *mtask;
- rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
+ rc = iscsi_recv_pdu(conn->cls_conn, hdr,
NULL, 0);
mtask = (struct iscsi_mgmt_task *)
session->mgmt_cmds[conn->in.itt -
@@ -761,7 +759,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
- rc = iscsi_recv_pdu(iscsi_handle(conn),
+ rc = iscsi_recv_pdu(conn->cls_conn,
hdr, NULL, 0);
} else
rc = ISCSI_ERR_PROTO;
@@ -1044,7 +1042,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
goto exit;
}
- rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
+ rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
conn->data, conn->in.datalen);
if (!rc && conn->datadgst_en &&
@@ -2428,19 +2426,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
}
static struct iscsi_cls_conn *
-iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
+iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
struct iscsi_conn *conn;
struct iscsi_cls_conn *cls_conn;
- cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
- conn_idx);
+ cls_conn = iscsi_create_conn(cls_session, conn_idx);
if (!cls_conn)
return NULL;
conn = cls_conn->dd_data;
+ memset(conn, 0, sizeof(*conn));
- memset(conn, 0, sizeof(struct iscsi_conn));
+ conn->cls_conn = cls_conn;
conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
conn->id = conn_idx;
@@ -2452,8 +2451,6 @@ iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
- spin_lock_init(&conn->lock);
-
/* initialize general xmit PDU commands queue */
conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
GFP_KERNEL, NULL);
@@ -2625,11 +2622,13 @@ iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
}
static int
-iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
- uint32_t transport_fd, int is_leading)
+iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
+ int is_leading)
{
- struct iscsi_session *session = iscsi_ptr(sessionh);
- struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = iscsi_ptr(connh);
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
struct sock *sk;
struct socket *sock;
int err;
@@ -2703,9 +2702,9 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
}
static int
-iscsi_conn_start(iscsi_connh_t connh)
+iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
struct sock *sk;
@@ -2754,9 +2753,9 @@ iscsi_conn_start(iscsi_connh_t connh)
}
static void
-iscsi_conn_stop(iscsi_connh_t connh, int flag)
+iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
struct sock *sk;
unsigned long flags;
@@ -3253,9 +3252,9 @@ static struct scsi_host_template iscsi_sht = {
static struct iscsi_transport iscsi_tcp_transport;
-static struct Scsi_Host *
+static struct iscsi_cls_session *
iscsi_session_create(struct scsi_transport_template *scsit,
- uint32_t initial_cmdsn)
+ uint32_t initial_cmdsn, uint32_t *sid)
{
struct Scsi_Host *shost;
struct iscsi_session *session;
@@ -3268,13 +3267,14 @@ iscsi_session_create(struct scsi_transport_template *scsit,
session = iscsi_hostdata(shost->hostdata);
memset(session, 0, sizeof(struct iscsi_session));
session->host = shost;
- session->state = ISCSI_STATE_LOGGED_IN;
+ session->state = ISCSI_STATE_FREE;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = ISCSI_XMIT_CMDS_MAX;
session->cmdsn = initial_cmdsn;
session->exp_cmdsn = initial_cmdsn + 1;
session->max_cmdsn = initial_cmdsn + 1;
session->max_r2t = 1;
+ *sid = shost->host_no;
/* initialize SCSI PDU commands pool */
if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
@@ -3311,22 +3311,24 @@ iscsi_session_create(struct scsi_transport_template *scsit,
if (iscsi_r2tpool_alloc(session))
goto r2tpool_alloc_fail;
- return shost;
+ return hostdata_session(shost->hostdata);
r2tpool_alloc_fail:
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
kfree(session->mgmt_cmds[cmd_i]->data);
- iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
immdata_alloc_fail:
+ iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
mgmtpool_alloc_fail:
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
cmdpool_alloc_fail:
+ iscsi_transport_destroy_session(shost);
return NULL;
}
static void
-iscsi_session_destroy(struct Scsi_Host *shost)
+iscsi_session_destroy(struct iscsi_cls_session *cls_session)
{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
int cmd_i;
struct iscsi_data_task *dtask, *n;
@@ -3350,10 +3352,10 @@ iscsi_session_destroy(struct Scsi_Host *shost)
}
static int
-iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
+iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
uint32_t value)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
spin_lock_bh(&session->lock);
@@ -3495,9 +3497,10 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
}
static int
-iscsi_session_get_param(struct Scsi_Host *shost,
+iscsi_session_get_param(struct iscsi_cls_session *cls_session,
enum iscsi_param param, uint32_t *value)
{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
switch(param) {
@@ -3539,9 +3542,10 @@ iscsi_session_get_param(struct Scsi_Host *shost,
}
static int
-iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
+iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, uint32_t *value)
{
- struct iscsi_conn *conn = data;
+ struct iscsi_conn *conn = cls_conn->dd_data;
switch(param) {
case ISCSI_PARAM_MAX_RECV_DLENGTH:
@@ -3564,9 +3568,9 @@ iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
}
static void
-iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
+iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
stats->txdata_octets = conn->txdata_octets;
stats->rxdata_octets = conn->rxdata_octets;
@@ -3587,10 +3591,10 @@ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
}
static int
-iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
- uint32_t data_size)
+iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+ char *data, uint32_t data_size)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
int rc;
mutex_lock(&conn->xmitmutex);
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index f95e61b76f70..ba26741ac154 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -113,7 +113,10 @@ struct iscsi_tcp_recv {
int datadgst;
};
+struct iscsi_cls_conn;
+
struct iscsi_conn {
+ struct iscsi_cls_conn *cls_conn; /* ptr to class connection */
struct iscsi_hdr hdr; /* header placeholder */
char hdrext[4*sizeof(__u16) +
sizeof(__u32)];
@@ -143,7 +146,6 @@ struct iscsi_conn {
struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */
struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */
struct iscsi_cmd_task *ctask; /* xmit ctask in progress */
- spinlock_t lock; /* FIXME: to be removed */
/* old values for socket callbacks */
void (*old_data_ready)(struct sock *, int);
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 23728d1c980c..fcd304e11c26 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -65,27 +65,6 @@ static int jazz_esp_release(struct Scsi_Host *shost)
return 0;
}
-static struct scsi_host_template driver_template = {
- .proc_name = "jazz_esp",
- .proc_info = &esp_proc_info,
- .name = "ESP 100/100a/200",
- .detect = jazz_esp_detect,
- .slave_alloc = esp_slave_alloc,
- .slave_destroy = esp_slave_destroy,
- .release = jazz_esp_release,
- .info = esp_info,
- .queuecommand = esp_queue,
- .eh_abort_handler = esp_abort,
- .eh_bus_reset_handler = esp_reset,
- .can_queue = 7,
- .this_id = 7,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = DISABLE_CLUSTERING,
-};
-
-#include "scsi_module.c"
-
/***************************************************************** Detection */
static int jazz_esp_detect(struct scsi_host_template *tpnt)
{
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 46c4cdbaee86..4f91b0dc572b 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -82,6 +82,10 @@ int atapi_enabled = 0;
module_param(atapi_enabled, int, 0444);
MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+int libata_fua = 0;
+module_param_named(fua, libata_fua, int, 0444);
+MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
@@ -614,7 +618,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
} else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
/* Unable to use DMA due to host limitation */
tf->protocol = ATA_PROT_PIO;
- index = dev->multi_count ? 0 : 4;
+ index = dev->multi_count ? 0 : 8;
} else {
tf->protocol = ATA_PROT_DMA;
index = 16;
@@ -2514,7 +2518,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
assert(sg != NULL);
if (qc->flags & ATA_QCFLAG_SINGLE)
- assert(qc->n_elem == 1);
+ assert(qc->n_elem <= 1);
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
@@ -2537,7 +2541,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
kunmap_atomic(addr, KM_IRQ0);
}
} else {
- if (sg_dma_len(&sg[0]) > 0)
+ if (qc->n_elem)
dma_unmap_single(ap->host_set->dev,
sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
dir);
@@ -2570,7 +2574,7 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
unsigned int idx;
assert(qc->__sg != NULL);
- assert(qc->n_elem > 0);
+ assert(qc->n_elem > 0 || qc->pad_len > 0);
idx = 0;
ata_for_each_sg(sg, qc) {
@@ -2715,6 +2719,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
int dir = qc->dma_dir;
struct scatterlist *sg = qc->__sg;
dma_addr_t dma_address;
+ int trim_sg = 0;
/* we must lengthen transfers to end on a 32-bit boundary */
qc->pad_len = sg->length & 3;
@@ -2734,13 +2739,15 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg_dma_len(psg) = ATA_DMA_PAD_SZ;
/* trim sg */
sg->length -= qc->pad_len;
+ if (sg->length == 0)
+ trim_sg = 1;
DPRINTK("padding done, sg->length=%u pad_len=%u\n",
sg->length, qc->pad_len);
}
- if (!sg->length) {
- sg_dma_address(sg) = 0;
+ if (trim_sg) {
+ qc->n_elem--;
goto skip_map;
}
@@ -2753,9 +2760,9 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
}
sg_dma_address(sg) = dma_address;
-skip_map:
sg_dma_len(sg) = sg->length;
+skip_map:
DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
@@ -3357,11 +3364,12 @@ static void ata_pio_error(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
- printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
-
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
+ if (qc->tf.command != ATA_CMD_PACKET)
+ printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
+
/* make sure qc->err_mask is available to
* know what's wrong and recover
*/
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 07b1e7cc61df..59503c9ccac9 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1708,6 +1708,8 @@ static int ata_dev_supports_fua(u16 *id)
{
unsigned char model[41], fw[9];
+ if (!libata_fua)
+ return 0;
if (!ata_id_has_fua(id))
return 0;
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index e03ce48b7b4b..fddaf479a544 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -41,6 +41,7 @@ struct ata_scsi_args {
/* libata-core.c */
extern int atapi_enabled;
+extern int libata_fua;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 311a4122bd70..93edaa8696cf 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -537,9 +537,9 @@ static int mac53c94_remove(struct macio_dev *mdev)
free_irq(fp->intr, fp);
if (fp->regs)
- iounmap((void *) fp->regs);
+ iounmap(fp->regs);
if (fp->dma)
- iounmap((void *) fp->dma);
+ iounmap(fp->dma);
kfree(fp->dma_cmd_space);
scsi_host_put(host);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index d101a8a6f4e8..7144674bc8e6 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -5049,7 +5049,7 @@ static struct pci_device_id megaraid_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl);
static struct pci_driver megaraid_pci_driver = {
- .name = "megaraid",
+ .name = "megaraid_legacy",
.id_table = megaraid_pci_tbl,
.probe = megaraid_probe_one,
.remove = __devexit_p(megaraid_remove_one),
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 4b3e0d6e5afa..4b75fe619d9c 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -5,7 +5,7 @@
#include <linux/mutex.h>
#define MEGARAID_VERSION \
- "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
+ "v2.00.4 (Release Date: Thu Feb 9 08:51:30 EST 2006)\n"
/*
* Driver features - change the values to enable or disable features in the
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index a487f414960e..4f39dd01936d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.02.02
+ * Version : v00.00.02.04
*
* Authors:
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
@@ -60,6 +60,12 @@ static struct pci_device_id megasas_pci_table[] = {
PCI_ANY_ID,
},
{
+ PCI_VENDOR_ID_LSI_LOGIC,
+ PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ },
+ {
PCI_VENDOR_ID_DELL,
PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
PCI_ANY_ID,
@@ -199,6 +205,86 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
*/
/**
+* The following functions are defined for ppc (deviceid : 0x60)
+* controllers
+*/
+
+/**
+ * megasas_enable_intr_ppc - Enables interrupts
+ * @regs: MFI register set
+ */
+static inline void
+megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+ writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+
+ writel(~0x80000004, &(regs)->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_ppc - returns the current FW status value
+ * @regs: MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
+{
+ return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_ppc - Check & clear interrupt
+ * @regs: MFI register set
+ */
+static int
+megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+ u32 status;
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(&regs->outbound_intr_status);
+
+ if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
+ return 1;
+ }
+
+ /*
+ * Clear the interrupt by writing back the same value
+ */
+ writel(status, &regs->outbound_doorbell_clear);
+
+ return 0;
+}
+/**
+ * megasas_fire_cmd_ppc - Sends command to the FW
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
+ */
+static inline void
+megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
+{
+ writel((frame_phys_addr | (frame_count<<1))|1,
+ &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_ppc = {
+
+ .fire_cmd = megasas_fire_cmd_ppc,
+ .enable_intr = megasas_enable_intr_ppc,
+ .clear_intr = megasas_clear_intr_ppc,
+ .read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+};
+
+/**
+* This is the end of set of functions & definitions
+* specific to ppc (deviceid : 0x60) controllers
+*/
+
+/**
* megasas_disable_intr - Disables interrupts
* @regs: MFI register set
*/
@@ -707,6 +793,20 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
return 0;
}
+static int megasas_slave_configure(struct scsi_device *sdev)
+{
+ /*
+ * Don't export physical disk devices to the disk driver.
+ *
+ * FIXME: Currently we don't export them to the midlayer at all.
+ * That will be fixed once LSI engineers have audited the
+ * firmware for possible issues.
+ */
+ if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
+ return -ENXIO;
+ return 0;
+}
+
/**
* megasas_wait_for_outstanding - Wait for all outstanding cmds
* @instance: Adapter soft state
@@ -857,6 +957,7 @@ static struct scsi_host_template megasas_template = {
.module = THIS_MODULE,
.name = "LSI Logic SAS based MegaRAID driver",
.proc_name = "megaraid_sas",
+ .slave_configure = megasas_slave_configure,
.queuecommand = megasas_queue_command,
.eh_device_reset_handler = megasas_reset_device,
.eh_bus_reset_handler = megasas_reset_bus_host,
@@ -985,20 +1086,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
break;
}
- /*
- * Don't export physical disk devices to mid-layer.
- */
- if (!MEGASAS_IS_LOGICAL(cmd->scmd) &&
- (hdr->cmd_status == MFI_STAT_OK) &&
- (cmd->scmd->cmnd[0] == INQUIRY)) {
-
- if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) ==
- TYPE_DISK) {
- cmd->scmd->result = DID_BAD_TARGET << 16;
- exception = 1;
- }
- }
-
case MFI_CMD_LD_READ:
case MFI_CMD_LD_WRITE:
@@ -1607,7 +1694,17 @@ static int megasas_init_mfi(struct megasas_instance *instance)
reg_set = instance->reg_set;
- instance->instancet = &megasas_instance_template_xscale;
+ switch(instance->pdev->device)
+ {
+ case PCI_DEVICE_ID_LSI_SAS1078R:
+ instance->instancet = &megasas_instance_template_ppc;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS1064R:
+ case PCI_DEVICE_ID_DELL_PERC5:
+ default:
+ instance->instancet = &megasas_instance_template_xscale;
+ break;
+ }
/*
* We expect the FW state to be READY
@@ -1983,6 +2080,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
host->max_channel = MEGASAS_MAX_CHANNELS - 1;
host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
host->max_lun = MEGASAS_MAX_LUN;
+ host->max_cmd_len = 16;
/*
* Notify the mid-layer about the new controller
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index d6d166c0663f..89639f0c38ef 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,9 +18,9 @@
/**
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.02.02"
-#define MEGASAS_RELDATE "Jan 23, 2006"
-#define MEGASAS_EXT_VERSION "Mon Jan 23 14:09:01 PST 2006"
+#define MEGASAS_VERSION "00.00.02.04"
+#define MEGASAS_RELDATE "Feb 03, 2006"
+#define MEGASAS_EXT_VERSION "Fri Feb 03 14:31:44 PST 2006"
/*
* =====================================
* MegaRAID SAS MFI firmware definitions
@@ -553,31 +553,46 @@ struct megasas_ctrl_info {
#define MFI_OB_INTR_STATUS_MASK 0x00000002
#define MFI_POLL_TIMEOUT_SECS 10
+#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
+#define PCI_DEVICE_ID_LSI_SAS1078R 0x00000060
+
struct megasas_register_set {
+ u32 reserved_0[4]; /*0000h*/
- u32 reserved_0[4]; /*0000h */
+ u32 inbound_msg_0; /*0010h*/
+ u32 inbound_msg_1; /*0014h*/
+ u32 outbound_msg_0; /*0018h*/
+ u32 outbound_msg_1; /*001Ch*/
- u32 inbound_msg_0; /*0010h */
- u32 inbound_msg_1; /*0014h */
- u32 outbound_msg_0; /*0018h */
- u32 outbound_msg_1; /*001Ch */
+ u32 inbound_doorbell; /*0020h*/
+ u32 inbound_intr_status; /*0024h*/
+ u32 inbound_intr_mask; /*0028h*/
- u32 inbound_doorbell; /*0020h */
- u32 inbound_intr_status; /*0024h */
- u32 inbound_intr_mask; /*0028h */
+ u32 outbound_doorbell; /*002Ch*/
+ u32 outbound_intr_status; /*0030h*/
+ u32 outbound_intr_mask; /*0034h*/
- u32 outbound_doorbell; /*002Ch */
- u32 outbound_intr_status; /*0030h */
- u32 outbound_intr_mask; /*0034h */
+ u32 reserved_1[2]; /*0038h*/
- u32 reserved_1[2]; /*0038h */
+ u32 inbound_queue_port; /*0040h*/
+ u32 outbound_queue_port; /*0044h*/
- u32 inbound_queue_port; /*0040h */
- u32 outbound_queue_port; /*0044h */
+ u32 reserved_2[22]; /*0048h*/
- u32 reserved_2; /*004Ch */
+ u32 outbound_doorbell_clear; /*00A0h*/
- u32 index_registers[1004]; /*0050h */
+ u32 reserved_3[3]; /*00A4h*/
+
+ u32 outbound_scratch_pad ; /*00B0h*/
+
+ u32 reserved_4[3]; /*00B4h*/
+
+ u32 inbound_low_queue_port ; /*00C0h*/
+
+ u32 inbound_high_queue_port ; /*00C4h*/
+
+ u32 reserved_5; /*00C8h*/
+ u32 index_registers[820]; /*00CCh*/
} __attribute__ ((packed));
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index df52190f4d94..eac8e179cfff 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -8,6 +8,7 @@ menu "PCMCIA SCSI adapter support"
config PCMCIA_AHA152X
tristate "Adaptec AHA152X PCMCIA support"
depends on m && !64BIT
+ select SCSI_SPI_ATTRS
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
adapter to your computer.
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 0c9edb7051f4..5609847e254a 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -275,10 +275,8 @@ static int aha152x_resume(struct pcmcia_device *dev)
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
- Scsi_Cmnd tmp;
pcmcia_request_configuration(link->handle, &link->conf);
- tmp.device->host = info->host;
- aha152x_host_reset(&tmp);
+ aha152x_host_reset_host(info->host);
}
return 0;
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index b17ee62dd1a9..92b3e13e9061 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -7,7 +7,6 @@
#include "qla_def.h"
#include <linux/vmalloc.h>
-#include <scsi/scsi_transport_fc.h>
/* SYSFS attributes --------------------------------------------------------- */
@@ -114,7 +113,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
struct device, kobj)));
unsigned long flags;
- if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
+ if (!capable(CAP_SYS_ADMIN) || off != 0)
return 0;
/* Read NVRAM. */
@@ -123,7 +122,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
ha->nvram_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- return (count);
+ return ha->nvram_size;
}
static ssize_t
@@ -175,19 +174,150 @@ static struct bin_attribute sysfs_nvram_attr = {
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
- .size = 0,
+ .size = 512,
.read = qla2x00_sysfs_read_nvram,
.write = qla2x00_sysfs_write_nvram,
};
+static ssize_t
+qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+
+ if (ha->optrom_state != QLA_SREADING)
+ return 0;
+ if (off > ha->optrom_size)
+ return 0;
+ if (off + count > ha->optrom_size)
+ count = ha->optrom_size - off;
+
+ memcpy(buf, &ha->optrom_buffer[off], count);
+
+ return count;
+}
+
+static ssize_t
+qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+
+ if (ha->optrom_state != QLA_SWRITING)
+ return -EINVAL;
+ if (off > ha->optrom_size)
+ return -ERANGE;
+ if (off + count > ha->optrom_size)
+ count = ha->optrom_size - off;
+
+ memcpy(&ha->optrom_buffer[off], buf, count);
+
+ return count;
+}
+
+static struct bin_attribute sysfs_optrom_attr = {
+ .attr = {
+ .name = "optrom",
+ .mode = S_IRUSR | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = OPTROM_SIZE_24XX,
+ .read = qla2x00_sysfs_read_optrom,
+ .write = qla2x00_sysfs_write_optrom,
+};
+
+static ssize_t
+qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ int val;
+
+ if (off)
+ return 0;
+
+ if (sscanf(buf, "%d", &val) != 1)
+ return -EINVAL;
+
+ switch (val) {
+ case 0:
+ if (ha->optrom_state != QLA_SREADING &&
+ ha->optrom_state != QLA_SWRITING)
+ break;
+
+ ha->optrom_state = QLA_SWAITING;
+ vfree(ha->optrom_buffer);
+ ha->optrom_buffer = NULL;
+ break;
+ case 1:
+ if (ha->optrom_state != QLA_SWAITING)
+ break;
+
+ ha->optrom_state = QLA_SREADING;
+ ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
+ if (ha->optrom_buffer == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to allocate memory for optrom retrieval "
+ "(%x).\n", ha->optrom_size);
+
+ ha->optrom_state = QLA_SWAITING;
+ return count;
+ }
+
+ memset(ha->optrom_buffer, 0, ha->optrom_size);
+ ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0,
+ ha->optrom_size);
+ break;
+ case 2:
+ if (ha->optrom_state != QLA_SWAITING)
+ break;
+
+ ha->optrom_state = QLA_SWRITING;
+ ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
+ if (ha->optrom_buffer == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to allocate memory for optrom update "
+ "(%x).\n", ha->optrom_size);
+
+ ha->optrom_state = QLA_SWAITING;
+ return count;
+ }
+ memset(ha->optrom_buffer, 0, ha->optrom_size);
+ break;
+ case 3:
+ if (ha->optrom_state != QLA_SWRITING)
+ break;
+
+ ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0,
+ ha->optrom_size);
+ break;
+ }
+ return count;
+}
+
+static struct bin_attribute sysfs_optrom_ctl_attr = {
+ .attr = {
+ .name = "optrom_ctl",
+ .mode = S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = 0,
+ .write = qla2x00_sysfs_write_optrom_ctl,
+};
+
void
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
{
struct Scsi_Host *host = ha->host;
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
- sysfs_nvram_attr.size = ha->nvram_size;
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
+ sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
+ sysfs_create_bin_file(&host->shost_gendev.kobj,
+ &sysfs_optrom_ctl_attr);
}
void
@@ -197,6 +327,12 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
+ sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
+ sysfs_remove_bin_file(&host->shost_gendev.kobj,
+ &sysfs_optrom_ctl_attr);
+
+ if (ha->beacon_blink_led == 1)
+ ha->isp_ops.beacon_off(ha);
}
/* Scsi_Host attributes. */
@@ -384,6 +520,50 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
return strlen(buf);
}
+static ssize_t
+qla2x00_beacon_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ int len = 0;
+
+ if (ha->beacon_blink_led)
+ len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
+ else
+ len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
+ return len;
+}
+
+static ssize_t
+qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ int val = 0;
+ int rval;
+
+ if (IS_QLA2100(ha) || IS_QLA2200(ha))
+ return -EPERM;
+
+ if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) {
+ qla_printk(KERN_WARNING, ha,
+ "Abort ISP active -- ignoring beacon request.\n");
+ return -EBUSY;
+ }
+
+ if (sscanf(buf, "%d", &val) != 1)
+ return -EINVAL;
+
+ if (val)
+ rval = ha->isp_ops.beacon_on(ha);
+ else
+ rval = ha->isp_ops.beacon_off(ha);
+
+ if (rval != QLA_SUCCESS)
+ count = 0;
+
+ return count;
+}
+
static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
NULL);
static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@@ -398,6 +578,8 @@ static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
qla2x00_zio_store);
static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
qla2x00_zio_timer_store);
+static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
+ qla2x00_beacon_store);
struct class_device_attribute *qla2x00_host_attrs[] = {
&class_device_attr_driver_version,
@@ -411,6 +593,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
&class_device_attr_state,
&class_device_attr_zio,
&class_device_attr_zio_timer,
+ &class_device_attr_beacon,
NULL,
};
@@ -426,6 +609,49 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost)
}
static void
+qla2x00_get_host_speed(struct Scsi_Host *shost)
+{
+ scsi_qla_host_t *ha = to_qla_host(shost);
+ uint32_t speed = 0;
+
+ switch (ha->link_data_rate) {
+ case LDR_1GB:
+ speed = 1;
+ break;
+ case LDR_2GB:
+ speed = 2;
+ break;
+ case LDR_4GB:
+ speed = 4;
+ break;
+ }
+ fc_host_speed(shost) = speed;
+}
+
+static void
+qla2x00_get_host_port_type(struct Scsi_Host *shost)
+{
+ scsi_qla_host_t *ha = to_qla_host(shost);
+ uint32_t port_type = FC_PORTTYPE_UNKNOWN;
+
+ switch (ha->current_topology) {
+ case ISP_CFG_NL:
+ port_type = FC_PORTTYPE_LPORT;
+ break;
+ case ISP_CFG_FL:
+ port_type = FC_PORTTYPE_NLPORT;
+ break;
+ case ISP_CFG_N:
+ port_type = FC_PORTTYPE_PTP;
+ break;
+ case ISP_CFG_F:
+ port_type = FC_PORTTYPE_NPORT;
+ break;
+ }
+ fc_host_port_type(shost) = port_type;
+}
+
+static void
qla2x00_get_starget_node_name(struct scsi_target *starget)
{
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
@@ -512,6 +738,41 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
return 0;
}
+static struct fc_host_statistics *
+qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
+{
+ scsi_qla_host_t *ha = to_qla_host(shost);
+ int rval;
+ uint16_t mb_stat[1];
+ link_stat_t stat_buf;
+ struct fc_host_statistics *pfc_host_stat;
+
+ pfc_host_stat = &ha->fc_host_stat;
+ memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
+
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
+ sizeof(stat_buf) / 4, mb_stat);
+ } else {
+ rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf,
+ mb_stat);
+ }
+ if (rval != 0) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to retrieve host statistics (%d).\n", mb_stat[0]);
+ return pfc_host_stat;
+ }
+
+ pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt;
+ pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt;
+ pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt;
+ pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt;
+ pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt;
+ pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt;
+
+ return pfc_host_stat;
+}
+
struct fc_function_template qla2xxx_transport_functions = {
.show_host_node_name = 1,
@@ -520,6 +781,10 @@ struct fc_function_template qla2xxx_transport_functions = {
.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,
+ .get_host_speed = qla2x00_get_host_speed,
+ .show_host_speed = 1,
+ .get_host_port_type = qla2x00_get_host_port_type,
+ .show_host_port_type = 1,
.dd_fcrport_size = sizeof(struct fc_port *),
.show_rport_supported_classes = 1,
@@ -536,6 +801,7 @@ struct fc_function_template qla2xxx_transport_functions = {
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
+ .get_fc_host_stats = qla2x00_get_fc_host_stats,
};
void
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index bad066e5772a..b31a03bbd14f 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -29,6 +29,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_transport_fc.h>
#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
@@ -181,6 +182,13 @@
#define WRT_REG_DWORD(addr, data) writel(data,addr)
/*
+ * The ISP2312 v2 chip cannot access the FLASH/GPIO registers via MMIO in an
+ * 133Mhz slot.
+ */
+#define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr))
+#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr))
+
+/*
* Fibre Channel device definitions.
*/
#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */
@@ -432,6 +440,9 @@ struct device_reg_2xxx {
#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040
#define GPIO_LED_GREEN_OFF_AMBER_ON 0x0080
#define GPIO_LED_GREEN_ON_AMBER_ON 0x00C0
+#define GPIO_LED_ALL_OFF 0x0000
+#define GPIO_LED_RED_ON_OTHER_OFF 0x0001 /* isp2322 */
+#define GPIO_LED_RGA_ON 0x00C1 /* isp2322: red green amber */
union {
struct {
@@ -2199,6 +2210,15 @@ struct isp_operations {
void (*fw_dump) (struct scsi_qla_host *, int);
void (*ascii_fw_dump) (struct scsi_qla_host *);
+
+ int (*beacon_on) (struct scsi_qla_host *);
+ int (*beacon_off) (struct scsi_qla_host *);
+ void (*beacon_blink) (struct scsi_qla_host *);
+
+ uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+ int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t,
+ uint32_t);
};
/*
@@ -2331,6 +2351,10 @@ typedef struct scsi_qla_host {
uint16_t min_external_loopid; /* First external loop Id */
uint16_t link_data_rate; /* F/W operating speed */
+#define LDR_1GB 0
+#define LDR_2GB 1
+#define LDR_4GB 3
+#define LDR_UNKNOWN 0xFFFF
uint8_t current_topology;
uint8_t prev_topology;
@@ -2486,12 +2510,26 @@ typedef struct scsi_qla_host {
uint8_t *port_name;
uint32_t isp_abort_cnt;
+ /* Option ROM information. */
+ char *optrom_buffer;
+ uint32_t optrom_size;
+ int optrom_state;
+#define QLA_SWAITING 0
+#define QLA_SREADING 1
+#define QLA_SWRITING 2
+
/* Needed for BEACON */
uint16_t beacon_blink_led;
- uint16_t beacon_green_on;
+ uint8_t beacon_color_state;
+#define QLA_LED_GRN_ON 0x01
+#define QLA_LED_YLW_ON 0x02
+#define QLA_LED_ABR_ON 0x04
+#define QLA_LED_ALL_ON 0x07 /* yellow, green, amber. */
+ /* ISP2322: red, green, amber. */
uint16_t zio_mode;
uint16_t zio_timer;
+ struct fc_host_statistics fc_host_stat;
} scsi_qla_host_t;
@@ -2557,7 +2595,9 @@ struct _qla2x00stats {
/*
* Flash support definitions
*/
-#define FLASH_IMAGE_SIZE 131072
+#define OPTROM_SIZE_2300 0x20000
+#define OPTROM_SIZE_2322 0x100000
+#define OPTROM_SIZE_24XX 0x100000
#include "qla_gbl.h"
#include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 35266bd5d538..ffdc2680f049 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -75,12 +75,12 @@ extern void qla2x00_cmd_timeout(srb_t *);
extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
-extern void qla2x00_blink_led(scsi_qla_host_t *);
-
extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
+extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
+
/*
* Global Function Prototypes in qla_iocb.c source file.
*/
@@ -185,6 +185,13 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
extern int
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
+extern int
+qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, link_stat_t *,
+ uint16_t *);
+
+extern int
+qla24xx_get_isp_stats(scsi_qla_host_t *, uint32_t *, uint32_t, uint16_t *);
+
extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
extern int qla24xx_abort_target(fc_port_t *);
@@ -228,6 +235,22 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
+extern int qla2x00_beacon_on(struct scsi_qla_host *);
+extern int qla2x00_beacon_off(struct scsi_qla_host *);
+extern void qla2x00_beacon_blink(struct scsi_qla_host *);
+extern int qla24xx_beacon_on(struct scsi_qla_host *);
+extern int qla24xx_beacon_off(struct scsi_qla_host *);
+extern void qla24xx_beacon_blink(struct scsi_qla_host *);
+
+extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+
/*
* Global Function Prototypes in qla_dbg.c source file.
*/
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e67bb0997818..634ee174bff2 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
-#include <scsi/scsi_transport_fc.h>
#include "qla_devtbl.h"
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 7ec0b8d6f07b..6544b6d0891d 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -814,6 +814,7 @@ qla24xx_start_scsi(srb_t *sp)
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+ host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
/* Load SCSI command packet. */
memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 71a46fcee8cc..42aa7a7c1a73 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -402,9 +402,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_LOOP_UP: /* Loop Up Event */
- ha->link_data_rate = 0;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
link_speed = link_speeds[0];
+ ha->link_data_rate = LDR_1GB;
} else {
link_speed = link_speeds[LS_UNKNOWN];
if (mb[1] < 5)
@@ -436,7 +436,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
}
ha->flags.management_server_logged_in = 0;
- ha->link_data_rate = 0;
+ ha->link_data_rate = LDR_UNKNOWN;
if (ql2xfdmienable)
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 3099b379de9d..363dfdd042b0 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -7,7 +7,6 @@
#include "qla_def.h"
#include <linux/delay.h>
-#include <scsi/scsi_transport_fc.h>
static void
qla2x00_mbx_sem_timeout(unsigned long data)
@@ -1874,7 +1873,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
mcp->mb[3] = LSW(id_list_dma);
mcp->mb[6] = MSW(MSD(id_list_dma));
mcp->mb[7] = LSW(MSD(id_list_dma));
- mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2;
+ mcp->mb[8] = 0;
+ mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
} else {
mcp->mb[1] = MSW(id_list_dma);
mcp->mb[2] = LSW(id_list_dma);
@@ -2017,8 +2017,109 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map)
return rval;
}
+#endif
+
+/*
+ * qla2x00_get_link_status
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * loop_id = device loop ID.
+ * ret_buf = pointer to link status return buffer.
+ *
+ * Returns:
+ * 0 = success.
+ * BIT_0 = mem alloc error.
+ * BIT_1 = mailbox error.
+ */
+int
+qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
+ link_stat_t *ret_buf, uint16_t *status)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ link_stat_t *stat_buf;
+ dma_addr_t stat_buf_dma;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+
+ stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma);
+ if (stat_buf == NULL) {
+ DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
+ __func__, ha->host_no));
+ return BIT_0;
+ }
+ memset(stat_buf, 0, sizeof(link_stat_t));
+
+ mcp->mb[0] = MBC_GET_LINK_STATUS;
+ mcp->mb[2] = MSW(stat_buf_dma);
+ mcp->mb[3] = LSW(stat_buf_dma);
+ mcp->mb[6] = MSW(MSD(stat_buf_dma));
+ mcp->mb[7] = LSW(MSD(stat_buf_dma));
+ mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+ mcp->in_mb = MBX_0;
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ mcp->mb[1] = loop_id;
+ mcp->mb[4] = 0;
+ mcp->mb[10] = 0;
+ mcp->out_mb |= MBX_10|MBX_4|MBX_1;
+ mcp->in_mb |= MBX_1;
+ } else if (HAS_EXTENDED_IDS(ha)) {
+ mcp->mb[1] = loop_id;
+ mcp->mb[10] = 0;
+ mcp->out_mb |= MBX_10|MBX_1;
+ } else {
+ mcp->mb[1] = loop_id << 8;
+ mcp->out_mb |= MBX_1;
+ }
+ mcp->tov = 30;
+ mcp->flags = IOCTL_CMD;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ if (rval == QLA_SUCCESS) {
+ if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
+ DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
+ __func__, ha->host_no, mcp->mb[0]);)
+ status[0] = mcp->mb[0];
+ rval = BIT_1;
+ } else {
+ /* copy over data -- firmware data is LE. */
+ ret_buf->link_fail_cnt =
+ le32_to_cpu(stat_buf->link_fail_cnt);
+ ret_buf->loss_sync_cnt =
+ le32_to_cpu(stat_buf->loss_sync_cnt);
+ ret_buf->loss_sig_cnt =
+ le32_to_cpu(stat_buf->loss_sig_cnt);
+ ret_buf->prim_seq_err_cnt =
+ le32_to_cpu(stat_buf->prim_seq_err_cnt);
+ ret_buf->inval_xmit_word_cnt =
+ le32_to_cpu(stat_buf->inval_xmit_word_cnt);
+ ret_buf->inval_crc_cnt =
+ le32_to_cpu(stat_buf->inval_crc_cnt);
+
+ DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d "
+ "loss_sync=%d loss_sig=%d seq_err=%d "
+ "inval_xmt_word=%d inval_crc=%d.\n", __func__,
+ ha->host_no, stat_buf->link_fail_cnt,
+ stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt,
+ stat_buf->prim_seq_err_cnt,
+ stat_buf->inval_xmit_word_cnt,
+ stat_buf->inval_crc_cnt);)
+ }
+ } else {
+ /* Failed. */
+ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ ha->host_no, rval);)
+ rval = BIT_1;
+ }
+
+ dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma);
-uint8_t
+ return rval;
+}
+
+int
qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
uint16_t *status)
{
@@ -2080,7 +2181,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
return rval;
}
-#endif
int
qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 5866a7c706a8..9f91f1a20542 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -366,6 +366,12 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
goto qc_fail_command;
}
+ /* Close window on fcport/rport state-transitioning. */
+ if (!*(fc_port_t **)rport->dd_data) {
+ cmd->result = DID_IMM_RETRY << 16;
+ goto qc_fail_command;
+ }
+
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
@@ -421,6 +427,12 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
goto qc24_fail_command;
}
+ /* Close window on fcport/rport state-transitioning. */
+ if (!*(fc_port_t **)rport->dd_data) {
+ cmd->result = DID_IMM_RETRY << 16;
+ goto qc24_fail_command;
+ }
+
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
@@ -513,7 +525,7 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
* Success (Adapter is online) : 0
* Failed (Adapter is offline/disabled) : 1
*/
-static int
+int
qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
{
int return_status;
@@ -1312,6 +1324,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->ports = MAX_BUSES;
ha->init_cb_size = sizeof(init_cb_t);
ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
+ ha->link_data_rate = LDR_UNKNOWN;
+ ha->optrom_size = OPTROM_SIZE_2300;
/* Assign ISP specific operations. */
ha->isp_ops.pci_config = qla2100_pci_config;
@@ -1339,6 +1353,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
ha->isp_ops.fw_dump = qla2100_fw_dump;
ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump;
+ ha->isp_ops.read_optrom = qla2x00_read_optrom_data;
+ ha->isp_ops.write_optrom = qla2x00_write_optrom_data;
if (IS_QLA2100(ha)) {
host->max_id = MAX_TARGETS_2100;
ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
@@ -1364,7 +1380,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.intr_handler = qla2300_intr_handler;
ha->isp_ops.fw_dump = qla2300_fw_dump;
ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
+ ha->isp_ops.beacon_on = qla2x00_beacon_on;
+ ha->isp_ops.beacon_off = qla2x00_beacon_off;
+ ha->isp_ops.beacon_blink = qla2x00_beacon_blink;
ha->gid_list_info_size = 6;
+ if (IS_QLA2322(ha) || IS_QLA6322(ha))
+ ha->optrom_size = OPTROM_SIZE_2322;
} else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
@@ -1400,7 +1421,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
ha->isp_ops.fw_dump = qla24xx_fw_dump;
ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
+ ha->isp_ops.read_optrom = qla24xx_read_optrom_data;
+ ha->isp_ops.write_optrom = qla24xx_write_optrom_data;
+ ha->isp_ops.beacon_on = qla24xx_beacon_on;
+ ha->isp_ops.beacon_off = qla24xx_beacon_off;
+ ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
ha->gid_list_info_size = 8;
+ ha->optrom_size = OPTROM_SIZE_24XX;
}
host->can_queue = ha->request_q_length + 128;
@@ -1657,11 +1684,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
spin_lock_irqsave(&fcport->rport_lock, flags);
fcport->drport = rport;
fcport->rport = NULL;
+ *(fc_port_t **)rport->dd_data = NULL;
spin_unlock_irqrestore(&fcport->rport_lock, flags);
set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
} else {
spin_lock_irqsave(&fcport->rport_lock, flags);
fcport->rport = NULL;
+ *(fc_port_t **)rport->dd_data = NULL;
spin_unlock_irqrestore(&fcport->rport_lock, flags);
fc_remote_port_delete(rport);
}
@@ -2066,6 +2095,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
ha->fw_dumped = 0;
ha->fw_dump_reading = 0;
ha->fw_dump_buffer = NULL;
+
+ vfree(ha->optrom_buffer);
}
/*
@@ -2314,6 +2345,9 @@ qla2x00_do_dpc(void *data)
if (!ha->interrupts_on)
ha->isp_ops.enable_intrs(ha);
+ if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags))
+ ha->isp_ops.beacon_blink(ha);
+
ha->dpc_active = 0;
} /* End of while(1) */
@@ -2491,6 +2525,12 @@ qla2x00_timer(scsi_qla_host_t *ha)
atomic_read(&ha->loop_down_timer)));
}
+ /* Check if beacon LED needs to be blinked */
+ if (ha->beacon_blink_led == 1) {
+ set_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags);
+ start_dpc++;
+ }
+
/* Schedule the DPC routine if needed */
if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
@@ -2499,6 +2539,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
start_dpc ||
test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
+ test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&
ha->dpc_wait && !ha->dpc_active) {
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index 2c3342108dd8..b70bebe18c01 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -6,8 +6,6 @@
*/
#include "qla_def.h"
-#include <scsi/scsi_transport_fc.h>
-
/**
* IO descriptor handle definitions.
*
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index f4d755a643e4..3866a5760f15 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -695,3 +695,966 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
return ret;
}
+
+
+static inline void
+qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
+{
+ if (IS_QLA2322(ha)) {
+ /* Flip all colors. */
+ if (ha->beacon_color_state == QLA_LED_ALL_ON) {
+ /* Turn off. */
+ ha->beacon_color_state = 0;
+ *pflags = GPIO_LED_ALL_OFF;
+ } else {
+ /* Turn on. */
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+ *pflags = GPIO_LED_RGA_ON;
+ }
+ } else {
+ /* Flip green led only. */
+ if (ha->beacon_color_state == QLA_LED_GRN_ON) {
+ /* Turn off. */
+ ha->beacon_color_state = 0;
+ *pflags = GPIO_LED_GREEN_OFF_AMBER_OFF;
+ } else {
+ /* Turn on. */
+ ha->beacon_color_state = QLA_LED_GRN_ON;
+ *pflags = GPIO_LED_GREEN_ON_AMBER_OFF;
+ }
+ }
+}
+
+void
+qla2x00_beacon_blink(struct scsi_qla_host *ha)
+{
+ uint16_t gpio_enable;
+ uint16_t gpio_data;
+ uint16_t led_color = 0;
+ unsigned long flags;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ if (ha->pio_address)
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ /* Save the Original GPIOE. */
+ if (ha->pio_address) {
+ gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
+ gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
+ } else {
+ gpio_enable = RD_REG_WORD(&reg->gpioe);
+ gpio_data = RD_REG_WORD(&reg->gpiod);
+ }
+
+ /* Set the modified gpio_enable values */
+ gpio_enable |= GPIO_LED_MASK;
+
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
+ } else {
+ WRT_REG_WORD(&reg->gpioe, gpio_enable);
+ RD_REG_WORD(&reg->gpioe);
+ }
+
+ qla2x00_flip_colors(ha, &led_color);
+
+ /* Clear out any previously set LED color. */
+ gpio_data &= ~GPIO_LED_MASK;
+
+ /* Set the new input LED color to GPIOD. */
+ gpio_data |= led_color;
+
+ /* Set the modified gpio_data values */
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
+ } else {
+ WRT_REG_WORD(&reg->gpiod, gpio_data);
+ RD_REG_WORD(&reg->gpiod);
+ }
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+int
+qla2x00_beacon_on(struct scsi_qla_host *ha)
+{
+ uint16_t gpio_enable;
+ uint16_t gpio_data;
+ unsigned long flags;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
+ ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
+
+ if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon on).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ if (ha->pio_address)
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+
+ /* Turn off LEDs. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ if (ha->pio_address) {
+ gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
+ gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
+ } else {
+ gpio_enable = RD_REG_WORD(&reg->gpioe);
+ gpio_data = RD_REG_WORD(&reg->gpiod);
+ }
+ gpio_enable |= GPIO_LED_MASK;
+
+ /* Set the modified gpio_enable values. */
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
+ } else {
+ WRT_REG_WORD(&reg->gpioe, gpio_enable);
+ RD_REG_WORD(&reg->gpioe);
+ }
+
+ /* Clear out previously set LED colour. */
+ gpio_data &= ~GPIO_LED_MASK;
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
+ } else {
+ WRT_REG_WORD(&reg->gpiod, gpio_data);
+ RD_REG_WORD(&reg->gpiod);
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /*
+ * Let the per HBA timer kick off the blinking process based on
+ * the following flags. No need to do anything else now.
+ */
+ ha->beacon_blink_led = 1;
+ ha->beacon_color_state = 0;
+
+ return QLA_SUCCESS;
+}
+
+int
+qla2x00_beacon_off(struct scsi_qla_host *ha)
+{
+ int rval = QLA_SUCCESS;
+
+ ha->beacon_blink_led = 0;
+
+ /* Set the on flag so when it gets flipped it will be off. */
+ if (IS_QLA2322(ha))
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+ else
+ ha->beacon_color_state = QLA_LED_GRN_ON;
+
+ ha->isp_ops.beacon_blink(ha); /* This turns green LED off */
+
+ ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
+ ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7;
+
+ rval = qla2x00_set_fw_options(ha, ha->fw_options);
+ if (rval != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon off).\n");
+ return rval;
+}
+
+
+static inline void
+qla24xx_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
+{
+ /* Flip all colors. */
+ if (ha->beacon_color_state == QLA_LED_ALL_ON) {
+ /* Turn off. */
+ ha->beacon_color_state = 0;
+ *pflags = 0;
+ } else {
+ /* Turn on. */
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+ *pflags = GPDX_LED_YELLOW_ON | GPDX_LED_AMBER_ON;
+ }
+}
+
+void
+qla24xx_beacon_blink(struct scsi_qla_host *ha)
+{
+ uint16_t led_color = 0;
+ uint32_t gpio_data;
+ unsigned long flags;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ /* Save the Original GPIOD. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Enable the gpio_data reg for update. */
+ gpio_data |= GPDX_LED_UPDATE_MASK;
+
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Set the color bits. */
+ qla24xx_flip_colors(ha, &led_color);
+
+ /* Clear out any previously set LED color. */
+ gpio_data &= ~GPDX_LED_COLOR_MASK;
+
+ /* Set the new input LED color to GPIOD. */
+ gpio_data |= led_color;
+
+ /* Set the modified gpio_data values. */
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+int
+qla24xx_beacon_on(struct scsi_qla_host *ha)
+{
+ uint32_t gpio_data;
+ unsigned long flags;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ if (ha->beacon_blink_led == 0) {
+ /* Enable firmware for update */
+ ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
+
+ if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS)
+ return QLA_FUNCTION_FAILED;
+
+ if (qla2x00_get_fw_options(ha, ha->fw_options) !=
+ QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon on).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Enable the gpio_data reg for update. */
+ gpio_data |= GPDX_LED_UPDATE_MASK;
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ RD_REG_DWORD(&reg->gpiod);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ }
+
+ /* So all colors blink together. */
+ ha->beacon_color_state = 0;
+
+ /* Let the per HBA timer kick off the blinking process. */
+ ha->beacon_blink_led = 1;
+
+ return QLA_SUCCESS;
+}
+
+int
+qla24xx_beacon_off(struct scsi_qla_host *ha)
+{
+ uint32_t gpio_data;
+ unsigned long flags;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ ha->beacon_blink_led = 0;
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+
+ ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */
+
+ /* Give control back to firmware. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Disable the gpio_data reg for update. */
+ gpio_data &= ~GPDX_LED_UPDATE_MASK;
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ RD_REG_DWORD(&reg->gpiod);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
+
+ if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon off).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ if (qla2x00_get_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to get fw options (beacon off).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ return QLA_SUCCESS;
+}
+
+
+/*
+ * Flash support routines
+ */
+
+/**
+ * qla2x00_flash_enable() - Setup flash for reading and writing.
+ * @ha: HA context
+ */
+static void
+qla2x00_flash_enable(scsi_qla_host_t *ha)
+{
+ uint16_t data;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ data = RD_REG_WORD(&reg->ctrl_status);
+ data |= CSR_FLASH_ENABLE;
+ WRT_REG_WORD(&reg->ctrl_status, data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+}
+
+/**
+ * qla2x00_flash_disable() - Disable flash and allow RISC to run.
+ * @ha: HA context
+ */
+static void
+qla2x00_flash_disable(scsi_qla_host_t *ha)
+{
+ uint16_t data;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ data = RD_REG_WORD(&reg->ctrl_status);
+ data &= ~(CSR_FLASH_ENABLE);
+ WRT_REG_WORD(&reg->ctrl_status, data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+}
+
+/**
+ * qla2x00_read_flash_byte() - Reads a byte from flash
+ * @ha: HA context
+ * @addr: Address in flash to read
+ *
+ * A word is read from the chip, but, only the lower byte is valid.
+ *
+ * Returns the byte read from flash @addr.
+ */
+static uint8_t
+qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr)
+{
+ uint16_t data;
+ uint16_t bank_select;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ bank_select = RD_REG_WORD(&reg->ctrl_status);
+
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ /* Specify 64K address range: */
+ /* clear out Module Select and Flash Address bits [19:16]. */
+ bank_select &= ~0xf8;
+ bank_select |= addr >> 12 & 0xf0;
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ data = RD_REG_WORD(&reg->flash_data);
+
+ return (uint8_t)data;
+ }
+
+ /* Setup bit 16 of flash address. */
+ if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ } else if (((addr & BIT_16) == 0) &&
+ (bank_select & CSR_FLASH_64K_BANK)) {
+ bank_select &= ~(CSR_FLASH_64K_BANK);
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ }
+
+ /* Always perform IO mapped accesses to the FLASH registers. */
+ if (ha->pio_address) {
+ uint16_t data2;
+
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+ WRT_REG_WORD_PIO(&reg->flash_address, (uint16_t)addr);
+ do {
+ data = RD_REG_WORD_PIO(&reg->flash_data);
+ barrier();
+ cpu_relax();
+ data2 = RD_REG_WORD_PIO(&reg->flash_data);
+ } while (data != data2);
+ } else {
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ data = qla2x00_debounce_register(&reg->flash_data);
+ }
+
+ return (uint8_t)data;
+}
+
+/**
+ * qla2x00_write_flash_byte() - Write a byte to flash
+ * @ha: HA context
+ * @addr: Address in flash to write
+ * @data: Data to write
+ */
+static void
+qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data)
+{
+ uint16_t bank_select;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ bank_select = RD_REG_WORD(&reg->ctrl_status);
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ /* Specify 64K address range: */
+ /* clear out Module Select and Flash Address bits [19:16]. */
+ bank_select &= ~0xf8;
+ bank_select |= addr >> 12 & 0xf0;
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ WRT_REG_WORD(&reg->flash_data, (uint16_t)data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+
+ return;
+ }
+
+ /* Setup bit 16 of flash address. */
+ if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ } else if (((addr & BIT_16) == 0) &&
+ (bank_select & CSR_FLASH_64K_BANK)) {
+ bank_select &= ~(CSR_FLASH_64K_BANK);
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ }
+
+ /* Always perform IO mapped accesses to the FLASH registers. */
+ if (ha->pio_address) {
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+ WRT_REG_WORD_PIO(&reg->flash_address, (uint16_t)addr);
+ WRT_REG_WORD_PIO(&reg->flash_data, (uint16_t)data);
+ } else {
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ WRT_REG_WORD(&reg->flash_data, (uint16_t)data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ }
+}
+
+/**
+ * qla2x00_poll_flash() - Polls flash for completion.
+ * @ha: HA context
+ * @addr: Address in flash to poll
+ * @poll_data: Data to be polled
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * This function polls the device until bit 7 of what is read matches data
+ * bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed
+ * out (a fatal error). The flash book recommeds reading bit 7 again after
+ * reading bit 5 as a 1.
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
+ uint8_t man_id, uint8_t flash_id)
+{
+ int status;
+ uint8_t flash_data;
+ uint32_t cnt;
+
+ status = 1;
+
+ /* Wait for 30 seconds for command to finish. */
+ poll_data &= BIT_7;
+ for (cnt = 3000000; cnt; cnt--) {
+ flash_data = qla2x00_read_flash_byte(ha, addr);
+ if ((flash_data & BIT_7) == poll_data) {
+ status = 0;
+ break;
+ }
+
+ if (man_id != 0x40 && man_id != 0xda) {
+ if ((flash_data & BIT_5) && cnt > 2)
+ cnt = 2;
+ }
+ udelay(10);
+ barrier();
+ }
+ return status;
+}
+
+#define IS_OEM_001(ha) \
+ ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322 && \
+ (ha)->pdev->subsystem_vendor == 0x1028 && \
+ (ha)->pdev->subsystem_device == 0x0170)
+
+/**
+ * qla2x00_program_flash_address() - Programs a flash address
+ * @ha: HA context
+ * @addr: Address in flash to program
+ * @data: Data to be written in flash
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_program_flash_address(scsi_qla_host_t *ha, uint32_t addr, uint8_t data,
+ uint8_t man_id, uint8_t flash_id)
+{
+ /* Write Program Command Sequence. */
+ if (IS_OEM_001(ha)) {
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x555, 0x55);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xa0);
+ qla2x00_write_flash_byte(ha, addr, data);
+ } else {
+ if (man_id == 0xda && flash_id == 0xc1) {
+ qla2x00_write_flash_byte(ha, addr, data);
+ if (addr & 0x7e)
+ return 0;
+ } else {
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xa0);
+ qla2x00_write_flash_byte(ha, addr, data);
+ }
+ }
+
+ udelay(150);
+
+ /* Wait for write to complete. */
+ return qla2x00_poll_flash(ha, addr, data, man_id, flash_id);
+}
+
+/**
+ * qla2x00_erase_flash() - Erase the flash.
+ * @ha: HA context
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_erase_flash(scsi_qla_host_t *ha, uint8_t man_id, uint8_t flash_id)
+{
+ /* Individual Sector Erase Command Sequence */
+ if (IS_OEM_001(ha)) {
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x555, 0x55);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0x80);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x555, 0x55);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0x10);
+ } else {
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x80);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x10);
+ }
+
+ udelay(150);
+
+ /* Wait for erase to complete. */
+ return qla2x00_poll_flash(ha, 0x00, 0x80, man_id, flash_id);
+}
+
+/**
+ * qla2x00_erase_flash_sector() - Erase a flash sector.
+ * @ha: HA context
+ * @addr: Flash sector to erase
+ * @sec_mask: Sector address mask
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_erase_flash_sector(scsi_qla_host_t *ha, uint32_t addr,
+ uint32_t sec_mask, uint8_t man_id, uint8_t flash_id)
+{
+ /* Individual Sector Erase Command Sequence */
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x80);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ if (man_id == 0x1f && flash_id == 0x13)
+ qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10);
+ else
+ qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30);
+
+ udelay(150);
+
+ /* Wait for erase to complete. */
+ return qla2x00_poll_flash(ha, addr, 0x80, man_id, flash_id);
+}
+
+/**
+ * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip.
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ */
+static void
+qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
+ uint8_t *flash_id)
+{
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x90);
+ *man_id = qla2x00_read_flash_byte(ha, 0x0000);
+ *flash_id = qla2x00_read_flash_byte(ha, 0x0001);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xf0);
+}
+
+
+static inline void
+qla2x00_suspend_hba(struct scsi_qla_host *ha)
+{
+ int cnt;
+ unsigned long flags;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ /* Suspend HBA. */
+ scsi_block_requests(ha->host);
+ ha->isp_ops.disable_intrs(ha);
+ set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+
+ /* Pause RISC. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
+ RD_REG_WORD(&reg->hccr);
+ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
+ for (cnt = 0; cnt < 30000; cnt++) {
+ if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) != 0)
+ break;
+ udelay(100);
+ }
+ } else {
+ udelay(10);
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+static inline void
+qla2x00_resume_hba(struct scsi_qla_host *ha)
+{
+ /* Resume HBA. */
+ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ up(ha->dpc_wait);
+ qla2x00_wait_for_hba_online(ha);
+ scsi_unblock_requests(ha->host);
+}
+
+uint8_t *
+qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+ unsigned long flags;
+ uint32_t addr, midpoint;
+ uint8_t *data;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ /* Suspend HBA. */
+ qla2x00_suspend_hba(ha);
+
+ /* Go with read. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ midpoint = ha->optrom_size / 2;
+
+ qla2x00_flash_enable(ha);
+ WRT_REG_WORD(&reg->nvram, 0);
+ RD_REG_WORD(&reg->nvram); /* PCI Posting. */
+ for (addr = offset, data = buf; addr < length; addr++, data++) {
+ if (addr == midpoint) {
+ WRT_REG_WORD(&reg->nvram, NVR_SELECT);
+ RD_REG_WORD(&reg->nvram); /* PCI Posting. */
+ }
+
+ *data = qla2x00_read_flash_byte(ha, addr);
+ }
+ qla2x00_flash_disable(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /* Resume HBA. */
+ qla2x00_resume_hba(ha);
+
+ return buf;
+}
+
+int
+qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+
+ int rval;
+ unsigned long flags;
+ uint8_t man_id, flash_id, sec_number, data;
+ uint16_t wd;
+ uint32_t addr, liter, sec_mask, rest_addr;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ /* Suspend HBA. */
+ qla2x00_suspend_hba(ha);
+
+ rval = QLA_SUCCESS;
+ sec_number = 0;
+
+ /* Reset ISP chip. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
+ pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
+
+ /* Go with write. */
+ qla2x00_flash_enable(ha);
+ do { /* Loop once to provide quick error exit */
+ /* Structure of flash memory based on manufacturer */
+ if (IS_OEM_001(ha)) {
+ /* OEM variant with special flash part. */
+ man_id = flash_id = 0;
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ goto update_flash;
+ }
+ qla2x00_get_flash_manufacturer(ha, &man_id, &flash_id);
+ switch (man_id) {
+ case 0x20: /* ST flash. */
+ if (flash_id == 0xd2 || flash_id == 0xe3) {
+ /*
+ * ST m29w008at part - 64kb sector size with
+ * 32kb,8kb,8kb,16kb sectors at memory address
+ * 0xf0000.
+ */
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ }
+ /*
+ * ST m29w010b part - 16kb sector size
+ * Default to 16kb sectors
+ */
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ break;
+ case 0x40: /* Mostel flash. */
+ /* Mostel v29c51001 part - 512 byte sector size. */
+ rest_addr = 0x1ff;
+ sec_mask = 0x1fe00;
+ break;
+ case 0xbf: /* SST flash. */
+ /* SST39sf10 part - 4kb sector size. */
+ rest_addr = 0xfff;
+ sec_mask = 0x1f000;
+ break;
+ case 0xda: /* Winbond flash. */
+ /* Winbond W29EE011 part - 256 byte sector size. */
+ rest_addr = 0x7f;
+ sec_mask = 0x1ff80;
+ break;
+ case 0xc2: /* Macronix flash. */
+ /* 64k sector size. */
+ if (flash_id == 0x38 || flash_id == 0x4f) {
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ }
+ /* Fall through... */
+
+ case 0x1f: /* Atmel flash. */
+ /* 512k sector size. */
+ if (flash_id == 0x13) {
+ rest_addr = 0x7fffffff;
+ sec_mask = 0x80000000;
+ break;
+ }
+ /* Fall through... */
+
+ case 0x01: /* AMD flash. */
+ if (flash_id == 0x38 || flash_id == 0x40 ||
+ flash_id == 0x4f) {
+ /* Am29LV081 part - 64kb sector size. */
+ /* Am29LV002BT part - 64kb sector size. */
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ } else if (flash_id == 0x3e) {
+ /*
+ * Am29LV008b part - 64kb sector size with
+ * 32kb,8kb,8kb,16kb sector at memory address
+ * h0xf0000.
+ */
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ } else if (flash_id == 0x20 || flash_id == 0x6e) {
+ /*
+ * Am29LV010 part or AM29f010 - 16kb sector
+ * size.
+ */
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ break;
+ } else if (flash_id == 0x6d) {
+ /* Am29LV001 part - 8kb sector size. */
+ rest_addr = 0x1fff;
+ sec_mask = 0x1e000;
+ break;
+ }
+ default:
+ /* Default to 16 kb sector size. */
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ break;
+ }
+
+update_flash:
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ if (qla2x00_erase_flash(ha, man_id, flash_id)) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ }
+
+ for (addr = offset, liter = 0; liter < length; liter++,
+ addr++) {
+ data = buf[liter];
+ /* Are we at the beginning of a sector? */
+ if ((addr & rest_addr) == 0) {
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ if (addr >= 0x10000UL) {
+ if (((addr >> 12) & 0xf0) &&
+ ((man_id == 0x01 &&
+ flash_id == 0x3e) ||
+ (man_id == 0x20 &&
+ flash_id == 0xd2))) {
+ sec_number++;
+ if (sec_number == 1) {
+ rest_addr =
+ 0x7fff;
+ sec_mask =
+ 0x18000;
+ } else if (
+ sec_number == 2 ||
+ sec_number == 3) {
+ rest_addr =
+ 0x1fff;
+ sec_mask =
+ 0x1e000;
+ } else if (
+ sec_number == 4) {
+ rest_addr =
+ 0x3fff;
+ sec_mask =
+ 0x1c000;
+ }
+ }
+ }
+ } else if (addr == ha->optrom_size / 2) {
+ WRT_REG_WORD(&reg->nvram, NVR_SELECT);
+ RD_REG_WORD(&reg->nvram);
+ }
+
+ if (flash_id == 0xda && man_id == 0xc1) {
+ qla2x00_write_flash_byte(ha, 0x5555,
+ 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa,
+ 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555,
+ 0xa0);
+ } else if (!IS_QLA2322(ha) && !IS_QLA6322(ha)) {
+ /* Then erase it */
+ if (qla2x00_erase_flash_sector(ha,
+ addr, sec_mask, man_id,
+ flash_id)) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ if (man_id == 0x01 && flash_id == 0x6d)
+ sec_number++;
+ }
+ }
+
+ if (man_id == 0x01 && flash_id == 0x6d) {
+ if (sec_number == 1 &&
+ addr == (rest_addr - 1)) {
+ rest_addr = 0x0fff;
+ sec_mask = 0x1f000;
+ } else if (sec_number == 3 && (addr & 0x7ffe)) {
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ }
+ }
+
+ if (qla2x00_program_flash_address(ha, addr, data,
+ man_id, flash_id)) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ }
+ } while (0);
+ qla2x00_flash_disable(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /* Resume HBA. */
+ qla2x00_resume_hba(ha);
+
+ return rval;
+}
+
+uint8_t *
+qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+ /* Suspend HBA. */
+ scsi_block_requests(ha->host);
+ ha->isp_ops.disable_intrs(ha);
+ set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+
+ /* Go with read. */
+ qla24xx_read_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2);
+
+ /* Resume HBA. */
+ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+ ha->isp_ops.enable_intrs(ha);
+ scsi_unblock_requests(ha->host);
+
+ return buf;
+}
+
+int
+qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+ int rval;
+
+ /* Suspend HBA. */
+ scsi_block_requests(ha->host);
+ ha->isp_ops.disable_intrs(ha);
+ set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+
+ /* Go with write. */
+ rval = qla24xx_write_flash_data(ha, (uint32_t *)buf, offset >> 2,
+ length >> 2);
+
+ /* Resume HBA -- RISC reset needed. */
+ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ up(ha->dpc_wait);
+ qla2x00_wait_for_hba_online(ha);
+ scsi_unblock_requests(ha->host);
+
+ return rval;
+}
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index cd54244058b5..2770005324b4 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -510,6 +510,12 @@ static const struct mv_hw_ops mv6xxx_ops = {
};
/*
+ * module options
+ */
+static int msi; /* Use PCI msi; either zero (off, default) or non-zero */
+
+
+/*
* Functions
*/
@@ -991,6 +997,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
case ATA_CMD_READ_EXT:
case ATA_CMD_WRITE:
case ATA_CMD_WRITE_EXT:
+ case ATA_CMD_WRITE_FUA_EXT:
mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
break;
#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */
@@ -2191,7 +2198,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Enable interrupts */
- if (pci_enable_msi(pdev) == 0) {
+ if (msi && pci_enable_msi(pdev) == 0) {
hpriv->hp_flags |= MV_HP_FLAG_MSI;
} else {
pci_intx(pdev, 1);
@@ -2246,5 +2253,8 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+module_param(msi, int, 0444);
+MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+
module_init(mv_init);
module_exit(mv_exit);
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index de05e2883f9c..80480f0fb2b8 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -277,7 +277,7 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
u8 *prd = pp->pkt + QS_CPB_BYTES;
assert(qc->__sg != NULL);
- assert(qc->n_elem > 0);
+ assert(qc->n_elem > 0 || qc->pad_len > 0);
nelem = 0;
ata_for_each_sg(sg, qc) {
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index b017f85e6d6a..9face3c6aa21 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -49,11 +49,13 @@
#define DRV_VERSION "0.9"
enum {
+ SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
SIL_FLAG_MOD15WRITE = (1 << 30),
sil_3112 = 0,
sil_3112_m15w = 1,
- sil_3114 = 2,
+ sil_3512 = 2,
+ sil_3114 = 3,
SIL_FIFO_R0 = 0x40,
SIL_FIFO_W0 = 0x41,
@@ -90,7 +92,7 @@ static void sil_post_set_mode (struct ata_port *ap);
static const struct pci_device_id sil_pci_tbl[] = {
{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
- { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
@@ -185,7 +187,8 @@ static const struct ata_port_info sil_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
- }, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+ },
+ /* sil_3112_15w - keep it sync'd w/ sil_3112 */
{
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -195,11 +198,24 @@ static const struct ata_port_info sil_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
- }, /* sil_3114 */
+ },
+ /* sil_3512 */
{
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SRST | ATA_FLAG_MMIO,
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ SIL_FLAG_RERR_ON_DMA_ACT,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil_ops,
+ },
+ /* sil_3114 */
+ {
+ .sht = &sil_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
@@ -216,12 +232,13 @@ static const struct {
unsigned long scr; /* SATA control register block */
unsigned long sien; /* SATA Interrupt Enable register */
unsigned long xfer_mode;/* data transfer mode register */
+ unsigned long sfis_cfg; /* SATA FIS reception config register */
} sil_port[] = {
/* port 0 ... */
- { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4 },
- { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4 },
- { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4 },
- { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4 },
+ { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c },
+ { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc },
+ { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c },
+ { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc },
/* ... port 3 */
};
@@ -231,6 +248,10 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+static int slow_down = 0;
+module_param(slow_down, int, 0444);
+MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
+
static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
{
@@ -354,8 +375,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
}
/* limit requests to 15 sectors */
- if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
- printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
+ if (slow_down ||
+ ((ap->flags & SIL_FLAG_MOD15WRITE) &&
+ (quirks & SIL_QUIRK_MOD15WRITE))) {
+ printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
ap->id, dev->devno);
ap->host->max_sectors = 15;
ap->host->hostt->max_sectors = 15;
@@ -465,6 +488,23 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev_printk(KERN_WARNING, &pdev->dev,
"cache line size not set. Driver may not function\n");
+ /* Apply R_ERR on DMA activate FIS errata workaround */
+ if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
+ int cnt;
+
+ for (i = 0, cnt = 0; i < probe_ent->n_ports; i++) {
+ tmp = readl(mmio_base + sil_port[i].sfis_cfg);
+ if ((tmp & 0x3) != 0x01)
+ continue;
+ if (!cnt)
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Applying R_ERR on DMA activate "
+ "FIS errata fix\n");
+ writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
+ cnt++;
+ }
+ }
+
if (ent->driver_data == sil_3114) {
irq_mask = SIL_MASK_4PORT;
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 2e2c3b7acb0c..e484e8db6810 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -81,6 +81,19 @@
/* Port stride */
#define VSC_SATA_PORT_OFFSET 0x200
+/* Error interrupt status bit offsets */
+#define VSC_SATA_INT_ERROR_E_OFFSET 2
+#define VSC_SATA_INT_ERROR_P_OFFSET 4
+#define VSC_SATA_INT_ERROR_T_OFFSET 5
+#define VSC_SATA_INT_ERROR_M_OFFSET 1
+#define is_vsc_sata_int_err(port_idx, int_status) \
+ (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \
+ (1 << (VSC_SATA_INT_ERROR_P_OFFSET + (8 * port_idx))) | \
+ (1 << (VSC_SATA_INT_ERROR_T_OFFSET + (8 * port_idx))) | \
+ (1 << (VSC_SATA_INT_ERROR_M_OFFSET + (8 * port_idx))) \
+ )\
+ )
+
static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
@@ -201,13 +214,28 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
struct ata_port *ap;
ap = host_set->ports[i];
+
+ if (is_vsc_sata_int_err(i, int_status)) {
+ u32 err_status;
+ printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+ err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
+ vsc_sata_scr_write(ap, SCR_ERROR, err_status);
+ handled++;
+ }
+
if (ap && !(ap->flags &
(ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
handled += ata_host_intr(ap, qc);
+ } else {
+ printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+ ata_chk_status(ap);
+ handled++;
+ }
+
}
}
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 245ca99a641e..c551bb84dbfb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1245,7 +1245,7 @@ static int __init init_scsi(void)
if (error)
goto cleanup_sysctl;
- for (i = 0; i < NR_CPUS; i++)
+ for_each_cpu(i)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
devfs_mk_dir("scsi");
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index f01ec0a7c506..84c3937ae8fb 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -126,6 +126,7 @@ static struct {
{"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN},
{"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
{"BELKIN", "USB 2 HS-CF", "1.95", BLIST_FORCELUN | BLIST_INQUIRY_36},
+ {"BROWNIE", "1600U3P", NULL, BLIST_NOREPORTLUN},
{"CANON", "IPUBJD", NULL, BLIST_SPARSELUN},
{"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN | BLIST_INQUIRY_36},
{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 5cc97b721661..ff82ccfbb106 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1308,7 +1308,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
* the request was not marked fast fail. Note that above,
* even if the request is marked fast fail, we still requeue
* for queue congestion conditions (QUEUE_FULL or BUSY) */
- if ((++scmd->retries) < scmd->allowed
+ if ((++scmd->retries) <= scmd->allowed
&& !blk_noretry_request(scmd->request)) {
return NEEDS_RETRY;
} else {
@@ -1433,7 +1433,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q)
list_del_init(&scmd->eh_entry);
if (scsi_device_online(scmd->device) &&
!blk_noretry_request(scmd->request) &&
- (++scmd->retries < scmd->allowed)) {
+ (++scmd->retries <= scmd->allowed)) {
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush"
" retry cmd: %p\n",
current->comm,
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4a602853a98e..701a328f7beb 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/hardirq.h>
#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
@@ -1497,7 +1498,7 @@ static void scsi_kill_request(struct request *req, request_queue_t *q)
static void scsi_softirq_done(struct request *rq)
{
struct scsi_cmnd *cmd = rq->completion_data;
- unsigned long wait_for = cmd->allowed * cmd->timeout_per_command;
+ unsigned long wait_for = (cmd->allowed + 1) * cmd->timeout_per_command;
int disposition;
INIT_LIST_HEAD(&cmd->eh_entry);
@@ -2248,3 +2249,61 @@ scsi_target_unblock(struct device *dev)
device_for_each_child(dev, NULL, target_unblock);
}
EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+
+struct work_queue_work {
+ struct work_struct work;
+ void (*fn)(void *);
+ void *data;
+};
+
+static void execute_in_process_context_work(void *data)
+{
+ void (*fn)(void *data);
+ struct work_queue_work *wqw = data;
+
+ fn = wqw->fn;
+ data = wqw->data;
+
+ kfree(wqw);
+
+ fn(data);
+}
+
+/**
+ * scsi_execute_in_process_context - reliably execute the routine with user context
+ * @fn: the function to execute
+ * @data: data to pass to the function
+ *
+ * Executes the function immediately if process context is available,
+ * otherwise schedules the function for delayed execution.
+ *
+ * Returns: 0 - function was executed
+ * 1 - function was scheduled for execution
+ * <0 - error
+ */
+int scsi_execute_in_process_context(void (*fn)(void *data), void *data)
+{
+ struct work_queue_work *wqw;
+
+ if (!in_interrupt()) {
+ fn(data);
+ return 0;
+ }
+
+ wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC);
+
+ if (unlikely(!wqw)) {
+ printk(KERN_ERR "Failed to allocate memory\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&wqw->work, execute_in_process_context_work, wqw);
+ wqw->fn = fn;
+ wqw->data = data;
+ schedule_work(&wqw->work);
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(scsi_execute_in_process_context);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 752fb5da3de4..f9ecc3dea7df 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -387,19 +387,12 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
return found_target;
}
-struct work_queue_wrapper {
- struct work_struct work;
- struct scsi_target *starget;
-};
-
-static void scsi_target_reap_work(void *data) {
- struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
- struct scsi_target *starget = wqw->starget;
+static void scsi_target_reap_usercontext(void *data)
+{
+ struct scsi_target *starget = data;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
- kfree(wqw);
-
spin_lock_irqsave(shost->host_lock, flags);
if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
@@ -428,18 +421,7 @@ static void scsi_target_reap_work(void *data) {
*/
void scsi_target_reap(struct scsi_target *starget)
{
- struct work_queue_wrapper *wqw =
- kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
-
- if (!wqw) {
- starget_printk(KERN_ERR, starget,
- "Failed to allocate memory in scsi_reap_target()\n");
- return;
- }
-
- INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
- wqw->starget = starget;
- schedule_work(&wqw->work);
+ scsi_execute_in_process_context(scsi_target_reap_usercontext, starget);
}
/**
@@ -770,8 +752,20 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
transport_configure_device(&sdev->sdev_gendev);
- if (sdev->host->hostt->slave_configure)
- sdev->host->hostt->slave_configure(sdev);
+ if (sdev->host->hostt->slave_configure) {
+ int ret = sdev->host->hostt->slave_configure(sdev);
+ if (ret) {
+ /*
+ * if LLDD reports slave not present, don't clutter
+ * console with alloc failure messages
+ */
+ if (ret != -ENXIO) {
+ sdev_printk(KERN_ERR, sdev,
+ "failed to configure device\n");
+ }
+ return SCSI_SCAN_NO_RESPONSE;
+ }
+ }
/*
* Ok, the device is now all set up, we can
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index a77b32deaf8f..902a5def8e62 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -217,8 +217,9 @@ static void scsi_device_cls_release(struct class_device *class_dev)
put_device(&sdev->sdev_gendev);
}
-static void scsi_device_dev_release(struct device *dev)
+static void scsi_device_dev_release_usercontext(void *data)
{
+ struct device *dev = data;
struct scsi_device *sdev;
struct device *parent;
struct scsi_target *starget;
@@ -237,6 +238,7 @@ static void scsi_device_dev_release(struct device *dev)
if (sdev->request_queue) {
sdev->request_queue->queuedata = NULL;
+ /* user context needed to free queue */
scsi_free_queue(sdev->request_queue);
/* temporary expedient, try to catch use of queue lock
* after free of sdev */
@@ -252,6 +254,11 @@ static void scsi_device_dev_release(struct device *dev)
put_device(parent);
}
+static void scsi_device_dev_release(struct device *dev)
+{
+ scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev);
+}
+
static struct class sdev_class = {
.name = "scsi_device",
.release = scsi_device_cls_release,
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index f2c9acf11bd0..13ea64119b73 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -223,7 +223,7 @@ static void fc_rport_terminate(struct fc_rport *rport);
*/
#define FC_STARGET_NUM_ATTRS 3
#define FC_RPORT_NUM_ATTRS 9
-#define FC_HOST_NUM_ATTRS 16
+#define FC_HOST_NUM_ATTRS 17
struct fc_internal {
struct scsi_transport_template t;
@@ -1498,8 +1498,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
}
/* Search the bindings array */
- if (likely((ids->roles & FC_RPORT_ROLE_FCP_TARGET) &&
- (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE))) {
+ if (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE) {
/* search for a matching consistent binding */
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 59a1c9d9d3bd..71e54a64adca 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -39,10 +39,6 @@ struct iscsi_internal {
struct iscsi_transport *iscsi_transport;
struct list_head list;
/*
- * List of sessions for this transport
- */
- struct list_head sessions;
- /*
* based on transport capabilities, at register time we set these
* bits to tell the transport class it wants attributes displayed
* in sysfs or that it can support different iSCSI Data-Path
@@ -164,9 +160,43 @@ static struct mempool_zone *z_reply;
#define Z_MAX_ERROR 16
#define Z_HIWAT_ERROR 12
+static LIST_HEAD(sesslist);
+static DEFINE_SPINLOCK(sesslock);
static LIST_HEAD(connlist);
static DEFINE_SPINLOCK(connlock);
+static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
+{
+ unsigned long flags;
+ struct iscsi_cls_session *sess;
+
+ spin_lock_irqsave(&sesslock, flags);
+ list_for_each_entry(sess, &sesslist, sess_list) {
+ if (sess == iscsi_ptr(handle)) {
+ spin_unlock_irqrestore(&sesslock, flags);
+ return sess;
+ }
+ }
+ spin_unlock_irqrestore(&sesslock, flags);
+ return NULL;
+}
+
+static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
+{
+ unsigned long flags;
+ struct iscsi_cls_conn *conn;
+
+ spin_lock_irqsave(&connlock, flags);
+ list_for_each_entry(conn, &connlist, conn_list) {
+ if (conn == iscsi_ptr(handle)) {
+ spin_unlock_irqrestore(&connlock, flags);
+ return conn;
+ }
+ }
+ spin_unlock_irqrestore(&connlock, flags);
+ return NULL;
+}
+
/*
* The following functions can be used by LLDs that allocate
* their own scsi_hosts or by software iscsi LLDs
@@ -365,6 +395,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
{
struct iscsi_cls_session *session;
struct Scsi_Host *shost;
+ unsigned long flags;
shost = scsi_host_alloc(transport->host_template,
hostdata_privsize(transport));
@@ -389,6 +420,9 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
goto remove_host;
*(unsigned long*)shost->hostdata = (unsigned long)session;
+ spin_lock_irqsave(&sesslock, flags);
+ list_add(&session->sess_list, &sesslist);
+ spin_unlock_irqrestore(&sesslock, flags);
return shost;
remove_host:
@@ -410,9 +444,13 @@ EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
int iscsi_transport_destroy_session(struct Scsi_Host *shost)
{
struct iscsi_cls_session *session;
+ unsigned long flags;
scsi_remove_host(shost);
session = hostdata_session(shost->hostdata);
+ spin_lock_irqsave(&sesslock, flags);
+ list_del(&session->sess_list);
+ spin_unlock_irqrestore(&sesslock, flags);
iscsi_destroy_session(session);
/* ref from host alloc */
scsi_host_put(shost);
@@ -424,22 +462,6 @@ EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
/*
* iscsi interface functions
*/
-static struct iscsi_cls_conn*
-iscsi_if_find_conn(uint64_t key)
-{
- unsigned long flags;
- struct iscsi_cls_conn *conn;
-
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry(conn, &connlist, conn_list)
- if (conn->connh == key) {
- spin_unlock_irqrestore(&connlock, flags);
- return conn;
- }
- spin_unlock_irqrestore(&connlock, flags);
- return NULL;
-}
-
static struct iscsi_internal *
iscsi_if_transport_lookup(struct iscsi_transport *tt)
{
@@ -463,7 +485,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
}
static void*
-mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
{
struct mempool_zone *zone = pool_data;
@@ -504,6 +526,12 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
if (!zp)
return NULL;
+ zp->size = size;
+ zp->hiwat = hiwat;
+ INIT_LIST_HEAD(&zp->freequeue);
+ spin_lock_init(&zp->freelock);
+ atomic_set(&zp->allocated, 0);
+
zp->pool = mempool_create(max, mempool_zone_alloc_skb,
mempool_zone_free_skb, zp);
if (!zp->pool) {
@@ -511,13 +539,6 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
return NULL;
}
- zp->size = size;
- zp->hiwat = hiwat;
-
- INIT_LIST_HEAD(&zp->freequeue);
- spin_lock_init(&zp->freelock);
- atomic_set(&zp->allocated, 0);
-
return zp;
}
@@ -559,25 +580,21 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
return 0;
}
-int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
char *data, uint32_t data_size)
{
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_cls_conn *conn;
char *pdu;
int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
data_size);
- conn = iscsi_if_find_conn(connh);
- BUG_ON(!conn);
-
mempool_zone_complete(conn->z_pdu);
skb = mempool_zone_get_skb(conn->z_pdu);
if (!skb) {
- iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
"control PDU: OOM\n");
return -ENOMEM;
@@ -590,7 +607,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
ev->type = ISCSI_KEVENT_RECV_PDU;
if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
ev->iferror = -ENOMEM;
- ev->r.recv_req.conn_handle = connh;
+ ev->r.recv_req.conn_handle = iscsi_handle(conn);
pdu = (char*)ev + sizeof(*ev);
memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
@@ -599,17 +616,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
}
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
-void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
+void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
{
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_cls_conn *conn;
int len = NLMSG_SPACE(sizeof(*ev));
- conn = iscsi_if_find_conn(connh);
- BUG_ON(!conn);
-
mempool_zone_complete(conn->z_error);
skb = mempool_zone_get_skb(conn->z_error);
@@ -626,7 +639,7 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
ev->iferror = -ENOMEM;
ev->r.connerror.error = error;
- ev->r.connerror.conn_handle = connh;
+ ev->r.connerror.conn_handle = iscsi_handle(conn);
iscsi_unicast_skb(conn->z_error, skb);
@@ -662,8 +675,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
}
static int
-iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
- struct nlmsghdr *nlh)
+iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
{
struct iscsi_uevent *ev = NLMSG_DATA(nlh);
struct iscsi_stats *stats;
@@ -677,7 +689,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
ISCSI_STATS_CUSTOM_MAX);
int err = 0;
- conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
+ conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
if (!conn)
return -EEXIST;
@@ -707,14 +719,14 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
((char*)evstat + sizeof(*evstat));
memset(stats, 0, sizeof(*stats));
- transport->get_stats(ev->u.get_stats.conn_handle, stats);
+ transport->get_stats(conn, stats);
actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
sizeof(struct iscsi_stats) +
sizeof(struct iscsi_stats_custom) *
stats->custom_length);
actual_size -= sizeof(*nlhstat);
actual_size = NLMSG_LENGTH(actual_size);
- skb_trim(skb, NLMSG_ALIGN(actual_size));
+ skb_trim(skbstat, NLMSG_ALIGN(actual_size));
nlhstat->nlmsg_len = actual_size;
err = iscsi_unicast_skb(conn->z_pdu, skbstat);
@@ -727,58 +739,34 @@ static int
iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
{
struct iscsi_transport *transport = priv->iscsi_transport;
- struct Scsi_Host *shost;
-
- if (!transport->create_session)
- return -EINVAL;
+ struct iscsi_cls_session *session;
+ uint32_t sid;
- shost = transport->create_session(&priv->t,
- ev->u.c_session.initial_cmdsn);
- if (!shost)
+ session = transport->create_session(&priv->t,
+ ev->u.c_session.initial_cmdsn,
+ &sid);
+ if (!session)
return -ENOMEM;
- ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
- ev->r.c_session_ret.sid = shost->host_no;
+ ev->r.c_session_ret.session_handle = iscsi_handle(session);
+ ev->r.c_session_ret.sid = sid;
return 0;
}
static int
-iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
{
- struct iscsi_transport *transport = priv->iscsi_transport;
-
- struct Scsi_Host *shost;
-
- if (!transport->destroy_session)
- return -EINVAL;
-
- shost = scsi_host_lookup(ev->u.d_session.sid);
- if (shost == ERR_PTR(-ENXIO))
- return -EEXIST;
-
- if (transport->destroy_session)
- transport->destroy_session(shost);
- /* ref from host lookup */
- scsi_host_put(shost);
- return 0;
-}
-
-static int
-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
- struct Scsi_Host *shost;
struct iscsi_cls_conn *conn;
+ struct iscsi_cls_session *session;
unsigned long flags;
- if (!transport->create_conn)
+ session = iscsi_session_lookup(ev->u.c_conn.session_handle);
+ if (!session)
return -EINVAL;
- shost = scsi_host_lookup(ev->u.c_conn.sid);
- if (shost == ERR_PTR(-ENXIO))
- return -EEXIST;
-
- conn = transport->create_conn(shost, ev->u.c_conn.cid);
+ conn = transport->create_conn(session, ev->u.c_conn.cid);
if (!conn)
- goto release_ref;
+ return -ENOMEM;
conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
NLMSG_SPACE(sizeof(struct iscsi_uevent) +
@@ -800,14 +788,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
goto free_pdu_pool;
}
- ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
+ ev->r.handle = iscsi_handle(conn);
spin_lock_irqsave(&connlock, flags);
list_add(&conn->conn_list, &connlist);
conn->active = 1;
spin_unlock_irqrestore(&connlock, flags);
- scsi_host_put(shost);
return 0;
free_pdu_pool:
@@ -815,8 +802,6 @@ free_pdu_pool:
destroy_conn:
if (transport->destroy_conn)
transport->destroy_conn(conn->dd_data);
-release_ref:
- scsi_host_put(shost);
return -ENOMEM;
}
@@ -827,13 +812,9 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
struct iscsi_cls_conn *conn;
struct mempool_zone *z_error, *z_pdu;
- conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
+ conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
if (!conn)
- return -EEXIST;
-
- if (!transport->destroy_conn)
return -EINVAL;
-
spin_lock_irqsave(&connlock, flags);
conn->active = 0;
list_del(&conn->conn_list);
@@ -858,23 +839,27 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct iscsi_uevent *ev = NLMSG_DATA(nlh);
struct iscsi_transport *transport = NULL;
struct iscsi_internal *priv;
-
- if (NETLINK_CREDS(skb)->uid)
- return -EPERM;
+ struct iscsi_cls_session *session;
+ struct iscsi_cls_conn *conn;
priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
if (!priv)
return -EINVAL;
transport = priv->iscsi_transport;
- daemon_pid = NETLINK_CREDS(skb)->pid;
+ if (!try_module_get(transport->owner))
+ return -EINVAL;
switch (nlh->nlmsg_type) {
case ISCSI_UEVENT_CREATE_SESSION:
err = iscsi_if_create_session(priv, ev);
break;
case ISCSI_UEVENT_DESTROY_SESSION:
- err = iscsi_if_destroy_session(priv, ev);
+ session = iscsi_session_lookup(ev->u.d_session.session_handle);
+ if (session)
+ transport->destroy_session(session);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_CREATE_CONN:
err = iscsi_if_create_conn(transport, ev);
@@ -883,56 +868,64 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
err = iscsi_if_destroy_conn(transport, ev);
break;
case ISCSI_UEVENT_BIND_CONN:
- if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->bind_conn(
- ev->u.b_conn.session_handle,
- ev->u.b_conn.conn_handle,
- ev->u.b_conn.transport_fd,
- ev->u.b_conn.is_leading);
+ session = iscsi_session_lookup(ev->u.b_conn.session_handle);
+ conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
+
+ if (session && conn)
+ ev->r.retcode = transport->bind_conn(session, conn,
+ ev->u.b_conn.transport_fd,
+ ev->u.b_conn.is_leading);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_SET_PARAM:
- if (!iscsi_if_find_conn(ev->u.set_param.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->set_param(
- ev->u.set_param.conn_handle,
- ev->u.set_param.param, ev->u.set_param.value);
+ conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
+ if (conn)
+ ev->r.retcode = transport->set_param(conn,
+ ev->u.set_param.param, ev->u.set_param.value);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_START_CONN:
- if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->start_conn(
- ev->u.start_conn.conn_handle);
+ conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
+ if (conn)
+ ev->r.retcode = transport->start_conn(conn);
+ else
+ err = -EINVAL;
+
break;
case ISCSI_UEVENT_STOP_CONN:
- if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle))
- return -EEXIST;
- transport->stop_conn(ev->u.stop_conn.conn_handle,
- ev->u.stop_conn.flag);
+ conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
+ if (conn)
+ transport->stop_conn(conn, ev->u.stop_conn.flag);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_SEND_PDU:
- if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->send_pdu(
- ev->u.send_pdu.conn_handle,
- (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
- (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
- ev->u.send_pdu.data_size);
+ conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
+ if (conn)
+ ev->r.retcode = transport->send_pdu(conn,
+ (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
+ (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
+ ev->u.send_pdu.data_size);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_GET_STATS:
- err = iscsi_if_get_stats(transport, skb, nlh);
+ err = iscsi_if_get_stats(transport, nlh);
break;
default:
err = -EINVAL;
break;
}
+ module_put(transport->owner);
return err;
}
/* Get message from skb (based on rtnetlink_rcv_skb). Each message is
* processed by iscsi_if_recv_msg. Malformed skbs with wrong length are
- * discarded silently. */
+ * or invalid creds discarded silently. */
static void
iscsi_if_rx(struct sock *sk, int len)
{
@@ -940,6 +933,12 @@ iscsi_if_rx(struct sock *sk, int len)
mutex_lock(&rx_queue_mutex);
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (NETLINK_CREDS(skb)->uid) {
+ skb_pull(skb, skb->len);
+ goto free_skb;
+ }
+ daemon_pid = NETLINK_CREDS(skb)->pid;
+
while (skb->len >= NLMSG_SPACE(0)) {
int err;
uint32_t rlen;
@@ -951,10 +950,12 @@ iscsi_if_rx(struct sock *sk, int len)
skb->len < nlh->nlmsg_len) {
break;
}
+
ev = NLMSG_DATA(nlh);
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
rlen = skb->len;
+
err = iscsi_if_recv_msg(skb, nlh);
if (err) {
ev->type = ISCSI_KEVENT_IF_ERROR;
@@ -978,6 +979,7 @@ iscsi_if_rx(struct sock *sk, int len)
} while (err < 0 && err != -ECONNREFUSED);
skb_pull(skb, rlen);
}
+free_skb:
kfree_skb(skb);
}
mutex_unlock(&rx_queue_mutex);
@@ -997,7 +999,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \
struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
struct iscsi_transport *t = conn->transport; \
\
- t->get_conn_param(conn->dd_data, param, &value); \
+ t->get_conn_param(conn, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -1024,10 +1026,9 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \
{ \
uint32_t value = 0; \
struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
- struct Scsi_Host *shost = iscsi_session_to_shost(session); \
struct iscsi_transport *t = session->transport; \
\
- t->get_session_param(shost, param, &value); \
+ t->get_session_param(session, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -1121,7 +1122,6 @@ iscsi_register_transport(struct iscsi_transport *tt)
return NULL;
memset(priv, 0, sizeof(*priv));
INIT_LIST_HEAD(&priv->list);
- INIT_LIST_HEAD(&priv->sessions);
priv->iscsi_transport = tt;
priv->cdev.class = &iscsi_transport_class;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 930db398d107..9d9872347f56 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -89,6 +89,11 @@
#define SD_MAX_RETRIES 5
#define SD_PASSTHROUGH_RETRIES 1
+/*
+ * Size of the initial data buffer for mode and read capacity data
+ */
+#define SD_BUF_SIZE 512
+
static void scsi_disk_release(struct kref *kref);
struct scsi_disk {
@@ -1239,7 +1244,7 @@ sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
/*
* read write protect setting, if possible - called only in sd_revalidate_disk()
- * called with buffer of length 512
+ * called with buffer of length SD_BUF_SIZE
*/
static void
sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
@@ -1297,7 +1302,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
/*
* sd_read_cache_type - called only from sd_revalidate_disk()
- * called with buffer of length 512
+ * called with buffer of length SD_BUF_SIZE
*/
static void
sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
@@ -1342,6 +1347,8 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
/* Take headers and block descriptors into account */
len += data.header_length + data.block_descriptor_length;
+ if (len > SD_BUF_SIZE)
+ goto bad_sense;
/* Get the data */
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
@@ -1354,6 +1361,12 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
int ct = 0;
int offset = data.header_length + data.block_descriptor_length;
+ if (offset >= SD_BUF_SIZE - 2) {
+ printk(KERN_ERR "%s: malformed MODE SENSE response",
+ diskname);
+ goto defaults;
+ }
+
if ((buffer[offset] & 0x3f) != modepage) {
printk(KERN_ERR "%s: got wrong page\n", diskname);
goto defaults;
@@ -1398,6 +1411,7 @@ defaults:
diskname);
sdkp->WCE = 0;
sdkp->RCD = 0;
+ sdkp->DPOFUA = 0;
}
/**
@@ -1421,7 +1435,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
if (!scsi_device_online(sdp))
goto out;
- buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA);
+ buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
if (!buffer) {
printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
"failure.\n");
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7d0700091f3d..5a0a19322d01 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1679,7 +1679,7 @@ static int
sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
{
int sg_bufflen = tablesize * sizeof(struct scatterlist);
- unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
+ gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
/*
* TODO: test without low_dma, we should not need it since
@@ -2162,7 +2162,7 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
srp->res_used = 1;
SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
- rem = size = (size + 1) & (~1); /* round to even for aha1542 */
+ rem = size;
for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
num = sg->length;
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 5d02ff4db6cc..b65462f76484 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -192,7 +192,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
SDev = cd->device;
if (!sense) {
- sense = kmalloc(sizeof(*sense), GFP_KERNEL);
+ sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
if (!sense) {
err = -ENOMEM;
goto out;
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 8260f040d39c..2627000ca653 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -919,6 +919,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
tp->usrtags = SYM_SETUP_MAX_TAG;
+ tp->usr_width = np->maxwide;
+ tp->usr_period = 9;
sym_nvram_setup_target(tp, i, nvram);
@@ -3588,7 +3590,7 @@ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int
if (pm) {
dp_scr = scr_to_cpu(pm->ret);
- dp_ofs -= scr_to_cpu(pm->sg.size);
+ dp_ofs -= scr_to_cpu(pm->sg.size) & 0x00ffffff;
}
/*
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 7aef7518b0d1..8c5c276c5577 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -362,7 +362,7 @@ static struct uart_ops serial21285_ops = {
static struct uart_port serial21285_port = {
.mapbase = 0x42000160,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = NO_IRQ,
.fifosize = 16,
.ops = &serial21285_ops,
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 8cbf0fc5a225..7f0f35a05dca 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -332,7 +332,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
* Make sure that we do not overflow the buffer
*/
if (tty_request_buffer_room(tty, 1) == 0) {
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
return;
}
@@ -353,7 +353,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
} while((rx = uart->urx.w) & URX_DATA_READY);
#endif
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
clear_and_exit:
return;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 60f5a5dc17f1..9843ae3d420e 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -509,7 +509,7 @@ static _INLINE_ void receive_chars(ser_info_t *info)
info->rx_cur = (QUICC_BD *)bdp;
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
static _INLINE_ void receive_break(ser_info_t *info)
@@ -521,7 +521,7 @@ static _INLINE_ void receive_break(ser_info_t *info)
* the break. If not, we exit now, losing the break. FIXME
*/
tty_insert_flip_char(tty, 0, TTY_BREAK);
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
static _INLINE_ void transmit_chars(ser_info_t *info)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 179c1f065e60..7aca22c9976d 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2198,7 +2198,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
touch_nmi_watchdog();
/*
- * First save the UER then disable the interrupts
+ * First save the IER then disable the interrupts
*/
ier = serial_in(up, UART_IER);
@@ -2229,6 +2229,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
+ up->ier |= UART_IER_THRI;
serial_out(up, UART_IER, ier | UART_IER_THRI);
}
@@ -2325,6 +2326,12 @@ static struct uart_driver serial8250_reg = {
.cons = SERIAL8250_CONSOLE,
};
+/*
+ * early_serial_setup - early registration for 8250 ports
+ *
+ * Setup an 8250 port structure prior to console initialisation. Use
+ * after console initialisation will cause undefined behaviour.
+ */
int __init early_serial_setup(struct uart_port *port)
{
if (port->line >= ARRAY_SIZE(serial8250_ports))
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 06ae8fbcc947..8d8d7a70d03e 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -56,7 +56,6 @@ static struct plat_serial8250_port au1x00_data[] = {
#elif defined(CONFIG_SOC_AU1550)
PORT(UART0_ADDR, AU1550_UART0_INT),
PORT(UART1_ADDR, AU1550_UART1_INT),
- PORT(UART2_ADDR, AU1550_UART2_INT),
PORT(UART3_ADDR, AU1550_UART3_INT),
#elif defined(CONFIG_SOC_AU1200)
PORT(UART0_ADDR, AU1200_UART0_INT),
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 2a912153321e..94886c000d2a 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -439,6 +439,20 @@ static int pci_siig_init(struct pci_dev *dev)
return -ENODEV;
}
+static int pci_siig_setup(struct serial_private *priv,
+ struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
+
+ if (idx > 3) {
+ bar = 4;
+ offset = (idx - 4) * 8;
+ }
+
+ return setup_port(priv, port, bar, offset, 0);
+}
+
/*
* Timedia has an explosion of boards, and to avoid the PCI table from
* growing *huge*, we use this function to collapse some 70 entries
@@ -748,7 +762,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_siig_init,
- .setup = pci_default_setup,
+ .setup = pci_siig_setup,
},
/*
* Titan cards
@@ -1868,6 +1882,10 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
pbn_b0_4_1843200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_VENDOR_ID_AFAVLAB,
+ PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
+ pbn_b0_4_1152000 },
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
@@ -2141,6 +2159,15 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
/*
* Computone devices submitted by Doug McNash dmcnash@computone.com
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ee4265d7a8c9..b3c561abe3f6 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -98,6 +98,7 @@ config SERIAL_8250_NR_UARTS
config SERIAL_8250_RUNTIME_UARTS
int "Number of 8250/16550 serial ports to register at runtime"
depends on SERIAL_8250
+ range 0 SERIAL_8250_NR_UARTS
default "4"
help
Set this to the maximum number of serial ports you want
@@ -901,8 +902,8 @@ config SERIAL_JSM
something like this to connect more than two modems to your Linux
box, for instance in order to become a dial-in server. This driver
supports PCI boards only.
- If you have a card like this, say Y here and read the file
- <file:Documentation/jsm.txt>.
+
+ If you have a card like this, say Y here, otherwise say N.
To compile this driver as a module, choose M here: the
module will be called jsm.
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 429de2723a1c..321a3b3a5728 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -561,7 +561,7 @@ static struct uart_amba_port amba_ports[UART_NR] = {
.port = {
.membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
.mapbase = INTEGRATOR_UART0_BASE,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UARTINT0,
.uartclk = 14745600,
.fifosize = 16,
@@ -576,7 +576,7 @@ static struct uart_amba_port amba_ports[UART_NR] = {
.port = {
.membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
.mapbase = INTEGRATOR_UART1_BASE,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UARTINT1,
.uartclk = 14745600,
.fifosize = 16,
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index ceb5d7f37bbd..344022fe53ef 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -892,7 +892,7 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res
int ret = 0;
switch (up->port.iotype) {
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
if (up->port.mapbase) {
*res = request_mem_region(up->port.mapbase, size, "serial");
if (!*res)
@@ -900,8 +900,8 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res
}
break;
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
+ case UPIO_HUB6:
+ case UPIO_PORT:
*res = request_region(up->port.iobase, size, "serial");
if (!*res)
ret = -EBUSY;
@@ -919,7 +919,7 @@ static void serial8250_release_port(struct uart_port *port)
size <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
if (up->port.mapbase) {
/*
* Unmap the area.
@@ -935,8 +935,8 @@ static void serial8250_release_port(struct uart_port *port)
}
break;
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
+ case UPIO_HUB6:
+ case UPIO_PORT:
start = up->port.iobase;
if (size)
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 16af5626c243..b7bf4c698a47 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -252,12 +252,9 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
/* If we have not enough room in tty flip buffer, then we try
* later, which will be the next rx-interrupt or a timeout
*/
- if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
- tty->flip.work.func((void *)tty);
- if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
- printk(KERN_WARNING "TTY_DONT_FLIP set\n");
- return;
- }
+ if(tty_buffer_request_room(tty, i) < i) {
+ printk(KERN_WARNING "No room in flip buffer\n");
+ return;
}
/* get pointer */
@@ -276,9 +273,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
continue;
error_return:
- *tty->flip.char_buf_ptr++ = ch;
- *tty->flip.flag_buf_ptr++ = flg;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flg);
} /* End while (i--) */
@@ -908,7 +903,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SMC1_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.flags = FLAG_SMC,
@@ -922,7 +917,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SMC2_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.flags = FLAG_SMC,
@@ -939,7 +934,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC1_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
@@ -953,7 +948,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC2_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
@@ -967,7 +962,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC3_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
@@ -981,7 +976,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC4_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index a64ba26a94e8..ba5541de673b 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -262,6 +262,7 @@ static inline void dz_receive_chars(struct dz_port *dport)
}
tty_insert_flip_char(tty, ch, flag);
ignore_char:
+ ;
} while (status & DZ_DVAL);
if (tty)
@@ -650,7 +651,7 @@ static void __init dz_init_ports(void)
for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
spin_lock_init(&dport->port.lock);
dport->port.membase = (char *) base;
- dport->port.iotype = SERIAL_IO_PORT;
+ dport->port.iotype = UPIO_PORT;
dport->port.irq = dec_interrupt[DEC_IRQ_DZ11];
dport->port.line = i;
dport->port.fifosize = 1;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 858048efe1ed..4d53fb5ca87b 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -668,7 +668,7 @@ static struct imx_port imx_ports[] = {
.rtsirq = UART1_MINT_RTS,
.port = {
.type = PORT_IMX,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.membase = (void *)IMX_UART1_BASE,
.mapbase = IMX_UART1_BASE, /* FIXME */
.irq = UART1_MINT_RX,
@@ -684,7 +684,7 @@ static struct imx_port imx_ports[] = {
.rtsirq = UART2_MINT_RTS,
.port = {
.type = PORT_IMX,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.membase = (void *)IMX_UART2_BASE,
.mapbase = IMX_UART2_BASE, /* FIXME */
.irq = UART2_MINT_RX,
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 1d85533d46d2..a37579ce6d76 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -1717,11 +1717,9 @@ ioc4_change_speed(struct uart_port *the_port,
}
if (cflag & CRTSCTS) {
- info->flags |= ASYNC_CTS_FLOW;
port->ip_sscr |= IOC4_SSCR_HFC_EN;
}
else {
- info->flags &= ~ASYNC_CTS_FLOW;
port->ip_sscr &= ~IOC4_SSCR_HFC_EN;
}
writel(port->ip_sscr, &port->ip_serial_regs->sscr);
@@ -1760,18 +1758,6 @@ static inline int ic4_startup_local(struct uart_port *the_port)
info = the_port->info;
- if (info->tty) {
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- }
local_open(port);
/* set the speed of the serial port */
@@ -2315,7 +2301,6 @@ static void receive_chars(struct uart_port *the_port)
int read_count, request_count = IOC4_MAX_CHARS;
struct uart_icount *icount;
struct uart_info *info = the_port->info;
- int flip = 0;
unsigned long pflags;
/* Make sure all the pointers are "good" ones */
@@ -2327,7 +2312,7 @@ static void receive_chars(struct uart_port *the_port)
spin_lock_irqsave(&the_port->lock, pflags);
tty = info->tty;
- request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2);
+ request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS);
if (request_count > 0) {
icount = &the_port->icount;
@@ -2340,8 +2325,7 @@ static void receive_chars(struct uart_port *the_port)
spin_unlock_irqrestore(&the_port->lock, pflags);
- if (flip)
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(tty);
}
/**
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index 66f117d15065..193722d680cf 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -215,7 +215,7 @@ static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs)
/* Lower and upper byte of baud rate generator divisor. */
write_zsreg(channel, R12, regs[R12]);
write_zsreg(channel, R13, regs[R13]);
-
+
/* Now rewrite R14, with BRENAB (if set). */
write_zsreg(channel, R14, regs[R14]);
@@ -420,10 +420,8 @@ static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up,
if (up->port.info == NULL)
goto ack_tx_int;
xmit = &up->port.info->xmit;
- if (uart_circ_empty(xmit)) {
- uart_write_wakeup(&up->port);
+ if (uart_circ_empty(xmit))
goto ack_tx_int;
- }
if (uart_tx_stopped(&up->port))
goto ack_tx_int;
@@ -571,7 +569,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
else
clear_bits |= DTR;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
up->curregs[R5] |= set_bits;
up->curregs[R5] &= ~clear_bits;
write_zsreg(channel, R5, up->curregs[R5]);
@@ -654,7 +652,7 @@ static void ip22zilog_enable_ms(struct uart_port *port)
if (new_reg != up->curregs[R15]) {
up->curregs[R15] = new_reg;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(channel, R15, up->curregs[R15]);
}
}
@@ -680,7 +678,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state)
if (new_reg != up->curregs[R5]) {
up->curregs[R5] = new_reg;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(channel, R5, up->curregs[R5]);
}
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b48066a64a7d..242a04104393 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -80,7 +80,7 @@
#include <asm/serial.h>
/* Standard COM flags */
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
/*
* SERIAL_PORT_DFNS tells us about built-in ports that have no
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
index 07d0dd80aa3d..7c3ec24f7e50 100644
--- a/drivers/serial/m32r_sio.h
+++ b/drivers/serial/m32r_sio.h
@@ -37,7 +37,7 @@ struct old_serial_port {
unsigned int irq;
unsigned int flags;
unsigned char io_type;
- unsigned char *iomem_base;
+ unsigned char __iomem *iomem_base;
unsigned short iomem_reg_shift;
};
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 0ef648fa4b2d..8cbbb954df2c 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -57,20 +57,16 @@ struct timer_list mcfrs_timer_struct;
* keep going. Perhaps one day the cflag settings for the
* console can be used instead.
*/
-#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
- defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
-#define CONSOLE_BAUD_RATE 19200
-#define DEFAULT_CBAUD B19200
-#endif
-
#if defined(CONFIG_HW_FEITH)
#define CONSOLE_BAUD_RATE 38400
#define DEFAULT_CBAUD B38400
-#endif
-
-#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
#define CONSOLE_BAUD_RATE 115200
#define DEFAULT_CBAUD B115200
+#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
+ defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+#define CONSOLE_BAUD_RATE 19200
+#define DEFAULT_CBAUD B19200
#endif
#ifndef CONSOLE_BAUD_RATE
@@ -350,7 +346,7 @@ static inline void receive_chars(struct mcf_serial *info)
}
tty_insert_flip_char(tty, ch, flag);
}
- tty_flip_buffer_push(tty);
+ tty_schedule_flip(tty);
return;
}
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 4e49168c3176..868eaf4a1a68 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -462,7 +462,7 @@ static int __init mux_probe(struct parisc_device *dev)
port->mapbase = dev->hpa.start + MUX_OFFSET +
(i * MUX_LINE_OFFSET);
port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
- port->iotype = SERIAL_IO_MEM;
+ port->iotype = UPIO_MEM;
port->type = PORT_MUX;
port->irq = NO_IRQ;
port->uartclk = 0;
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 4e03a87f3fb4..9b7ed58cb53b 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -1492,7 +1492,7 @@ no_dma:
/*
* Init remaining bits of "port" structure
*/
- uap->port.iotype = SERIAL_IO_MEM;
+ uap->port.iotype = UPIO_MEM;
uap->port.irq = np->intrs[0].line;
uap->port.uartclk = ZS_CLOCK;
uap->port.fifosize = 1;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 0a2dd6c5b95f..7410e093a6b9 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -161,7 +161,11 @@ s3c24xx_serial_dbg(const char *fmt, ...)
/* we can support 3 uarts, but not always use them */
+#ifdef CONFIG_CPU_S3C2400
+#define NR_PORTS (2)
+#else
#define NR_PORTS (3)
+#endif
/* port irq numbers */
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index ff7b60b4de37..2c00b8625852 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -628,7 +628,7 @@ static void __init sa1100_init_ports(void)
sa1100_ports[i].port.ops = &sa1100_pops;
sa1100_ports[i].port.fifosize = 8;
sa1100_ports[i].port.line = i;
- sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
+ sa1100_ports[i].port.iotype = UPIO_MEM;
init_timer(&sa1100_ports[i].timer);
sa1100_ports[i].timer.function = sa1100_timeout;
sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 0717abfdae06..cc1faa31d124 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -71,6 +71,11 @@ static void uart_change_pm(struct uart_state *state, int pm_state);
void uart_write_wakeup(struct uart_port *port)
{
struct uart_info *info = port->info;
+ /*
+ * This means you called this function _after_ the port was
+ * closed. No cookie for you.
+ */
+ BUG_ON(!info);
tasklet_schedule(&info->tlet);
}
@@ -471,14 +476,26 @@ static void uart_flush_chars(struct tty_struct *tty)
}
static int
-uart_write(struct tty_struct *tty, const unsigned char * buf, int count)
+uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->port;
- struct circ_buf *circ = &state->info->xmit;
+ struct uart_port *port;
+ struct circ_buf *circ;
unsigned long flags;
int c, ret = 0;
+ /*
+ * This means you called this function _after_ the port was
+ * closed. No cookie for you.
+ */
+ if (!state || !state->info) {
+ WARN_ON(1);
+ return -EL3HLT;
+ }
+
+ port = state->port;
+ circ = &state->info->xmit;
+
if (!circ->buf)
return 0;
@@ -521,6 +538,15 @@ static void uart_flush_buffer(struct tty_struct *tty)
struct uart_port *port = state->port;
unsigned long flags;
+ /*
+ * This means you called this function _after_ the port was
+ * closed. No cookie for you.
+ */
+ if (!state || !state->info) {
+ WARN_ON(1);
+ return;
+ }
+
DPRINTK("uart_flush_buffer(%d) called\n", tty->index);
spin_lock_irqsave(&port->lock, flags);
@@ -2237,7 +2263,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
* If this port is a console, then the spinlock is already
* initialised.
*/
- if (!uart_console(port))
+ if (!(uart_console(port) && (port->cons->flags & CON_ENABLED)))
spin_lock_init(&port->lock);
uart_configure_port(drv, state, port);
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index d0490f67f597..04186eaae227 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -501,7 +501,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
.port = {
.membase = (void*) io_p2v (UART1_PHYS),
.mapbase = UART1_PHYS,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UART1INTR,
.uartclk = 14745600/2,
.fifosize = 16,
@@ -514,7 +514,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
.port = {
.membase = (void*) io_p2v (UART2_PHYS),
.mapbase = UART2_PHYS,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UART2INTR,
.uartclk = 14745600/2,
.fifosize = 16,
@@ -527,7 +527,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
.port = {
.membase = (void*) io_p2v (UART3_PHYS),
.mapbase = UART3_PHYS,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UART3INTR,
.uartclk = 14745600/2,
.fifosize = 16,
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 80737c131ce7..44f6bf79bbe1 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -1468,10 +1468,10 @@ static struct sci_port sci_ports[] = {
.port = {
.membase = (void *)0xff923000,
.mapbase = 0xff923000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 61,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1482,10 +1482,10 @@ static struct sci_port sci_ports[] = {
.port = {
.membase = (void *)0xff924000,
.mapbase = 0xff924000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 62,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
@@ -1496,10 +1496,10 @@ static struct sci_port sci_ports[] = {
.port = {
.membase = (void *)0xff925000,
.mapbase = 0xff925000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 63,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 2,
},
.type = PORT_SCIF,
@@ -1511,10 +1511,10 @@ static struct sci_port sci_ports[] = {
.port = {
.membase = (void *)0xffe00000,
.mapbase = 0xffe00000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 43,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1525,10 +1525,10 @@ static struct sci_port sci_ports[] = {
.port = {
.membase = (void *)0xffe10000,
.mapbase = 0xffe10000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 79,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 43e67d6c29d4..60ea4a3f0713 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -820,7 +820,7 @@ static int __init sn_sal_module_init(void)
int retval;
if (!ia64_platform_is("sn2"))
- return -ENODEV;
+ return 0;
printk(KERN_INFO "sn_console: Console driver init\n");
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 8bcaebcc0ad7..85664228a0b6 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -1036,7 +1036,7 @@ static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg
up->port.irq = edev->irqs[0];
up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
up->port.mapbase = (unsigned long)up->regs;
- up->port.iotype = SERIAL_IO_MEM;
+ up->port.iotype = UPIO_MEM;
writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index bc67442c6b4c..4e453fa966ae 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -109,11 +109,11 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset)
offset <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_HUB6:
+ case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
return inb(up->port.iobase + 1);
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
return readb(up->port.membase + offset);
default:
@@ -139,12 +139,12 @@ serial_out(struct uart_sunsu_port *up, int offset, int value)
offset <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_HUB6:
+ case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
outb(value, up->port.iobase + 1);
break;
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
writeb(value, up->port.membase + offset);
break;
@@ -299,13 +299,10 @@ static void sunsu_start_tx(struct uart_port *port)
static void sunsu_stop_rx(struct uart_port *port)
{
struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- unsigned long flags;
- spin_lock_irqsave(&up->port.lock, flags);
up->ier &= ~UART_IER_RLSI;
up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
- spin_unlock_irqrestore(&up->port.lock, flags);
}
static void sunsu_enable_ms(struct uart_port *port)
@@ -1052,7 +1049,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
return;
up->type_probed = PORT_UNKNOWN;
- up->port.iotype = SERIAL_IO_MEM;
+ up->port.iotype = UPIO_MEM;
/*
* First we look for Ebus-bases su's
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 3c72484adea7..5cc4d4c2935c 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1487,7 +1487,7 @@ static void __init sunzilog_prepare(void)
up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB;
/* Channel A */
- up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM;
+ up[(chip * 2) + 0].port.iotype = UPIO_MEM;
up[(chip * 2) + 0].port.irq = zilog_irq;
up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
up[(chip * 2) + 0].port.fifosize = 1;
@@ -1498,7 +1498,7 @@ static void __init sunzilog_prepare(void)
up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
/* Channel B */
- up[(chip * 2) + 1].port.iotype = SERIAL_IO_MEM;
+ up[(chip * 2) + 1].port.iotype = UPIO_MEM;
up[(chip * 2) + 1].port.irq = zilog_irq;
up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
up[(chip * 2) + 1].port.fifosize = 1;
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index 9378895a8d56..df705fda4243 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -496,7 +496,7 @@ static int __init v850e_uart_init (void)
port->ops = &v850e_uart_ops;
port->line = chan;
- port->iotype = SERIAL_IO_MEM;
+ port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
/* We actually use multiple IRQs, but the serial
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
index d95265b187a3..a34731625877 100644
--- a/drivers/sn/Kconfig
+++ b/drivers/sn/Kconfig
@@ -3,10 +3,11 @@
#
menu "SN Devices"
+ depends on SGI_SN
config SGI_IOC4
tristate "SGI IOC4 Base IO support"
- depends on (IA64_GENERIC || IA64_SGI_SN2) && MMTIMER
+ depends on MMTIMER
default m
---help---
This option enables basic support for the SGI IOC4-based Base IO
@@ -19,7 +20,6 @@ config SGI_IOC4
config SGI_IOC3
tristate "SGI IOC3 Base IO support"
- depends on (IA64_GENERIC || IA64_SGI_SN2)
default m
---help---
This option enables basic support for the SGI IOC3-based Base IO
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index c70ae81b5d98..93449a1a0065 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -38,10 +38,10 @@ static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
static int nic_wait(struct ioc3_driver_data *idd)
{
- volatile unsigned mcr;
+ unsigned mcr;
do {
- mcr = (volatile unsigned)idd->vma->mcr;
+ mcr = readl(&idd->vma->mcr);
} while (!(mcr & 2));
return mcr & 1;
@@ -53,7 +53,7 @@ static int nic_reset(struct ioc3_driver_data *idd)
unsigned long flags;
local_irq_save(flags);
- idd->vma->mcr = mcr_pack(500, 65);
+ writel(mcr_pack(500, 65), &idd->vma->mcr);
presence = nic_wait(idd);
local_irq_restore(flags);
@@ -62,13 +62,13 @@ static int nic_reset(struct ioc3_driver_data *idd)
return presence;
}
-static inline int nic_read_bit(struct ioc3_driver_data *idd)
+static int nic_read_bit(struct ioc3_driver_data *idd)
{
int result;
unsigned long flags;
local_irq_save(flags);
- idd->vma->mcr = mcr_pack(6, 13);
+ writel(mcr_pack(6, 13), &idd->vma->mcr);
result = nic_wait(idd);
local_irq_restore(flags);
@@ -77,12 +77,12 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd)
return result;
}
-static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
+static void nic_write_bit(struct ioc3_driver_data *idd, int bit)
{
if (bit)
- idd->vma->mcr = mcr_pack(6, 110);
+ writel(mcr_pack(6, 110), &idd->vma->mcr);
else
- idd->vma->mcr = mcr_pack(80, 30);
+ writel(mcr_pack(80, 30), &idd->vma->mcr);
nic_wait(idd);
}
@@ -337,7 +337,7 @@ static void probe_nic(struct ioc3_driver_data *idd)
int save = 0, loops = 3;
unsigned long first, addr;
- idd->vma->gpcr_s = GPCR_MLAN_EN;
+ writel(GPCR_MLAN_EN, &idd->vma->gpcr_s);
while(loops>0) {
idd->nic_part[0] = 0;
@@ -371,8 +371,7 @@ static void probe_nic(struct ioc3_driver_data *idd)
/* Interrupts */
-static inline void
-write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
+static void write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
{
unsigned long flags;
@@ -408,7 +407,7 @@ static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs)
read_lock_irqsave(&ioc3_submodules_lock, flags);
- if(idd->dual_irq && idd->vma->eisr) {
+ if(idd->dual_irq && readb(&idd->vma->eisr)) {
/* send Ethernet IRQ to the driver */
if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
ioc3_ethernet->intr) {
@@ -682,7 +681,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
idd->id = ioc3_counter++;
up_write(&ioc3_devices_rwsem);
- idd->gpdr_shadow = idd->vma->gpdr;
+ idd->gpdr_shadow = readl(&idd->vma->gpdr);
/* Read IOC3 NIC contents */
probe_nic(idd);
@@ -735,14 +734,12 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
}
/* Add this IOC3 to all submodules */
- read_lock(&ioc3_submodules_lock);
for(id=0;id<IOC3_MAX_SUBMODULES;id++)
if(ioc3_submodules[id] && ioc3_submodules[id]->probe) {
idd->active[id] = 1;
idd->active[id] = !ioc3_submodules[id]->probe
(ioc3_submodules[id], idd);
}
- read_unlock(&ioc3_submodules_lock);
printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev));
@@ -767,7 +764,6 @@ static void ioc3_remove(struct pci_dev *pdev)
idd = pci_get_drvdata(pdev);
/* Remove this IOC3 from all submodules */
- read_lock(&ioc3_submodules_lock);
for(id=0;id<IOC3_MAX_SUBMODULES;id++)
if(idd->active[id]) {
if(ioc3_submodules[id] && ioc3_submodules[id]->remove)
@@ -781,7 +777,6 @@ static void ioc3_remove(struct pci_dev *pdev)
pci_name(pdev));
idd->active[id] = 0;
}
- read_unlock(&ioc3_submodules_lock);
/* Clear and disable all IRQs */
write_ireg(idd, ~0, IOC3_W_IEC);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b77dbd63e596..7a75faeb0526 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,16 +75,6 @@ config SPI_BUTTERFLY
inexpensive battery powered microcontroller evaluation board.
This same cable can be used to flash new firmware.
-config SPI_BUTTERFLY
- tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
- depends on SPI_MASTER && PARPORT && EXPERIMENTAL
- select SPI_BITBANG
- help
- This uses a custom parallel port cable to connect to an AVR
- Butterfly <http://www.atmel.com/products/avr/butterfly>, an
- inexpensive battery powered microcontroller evaluation board.
- This same cable can be used to flash new firmware.
-
#
# Add new SPI master controllers in alphabetical order above this line
#
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 791c4dc550ae..94f5e8ed83a7 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -90,7 +90,7 @@ static int spi_suspend(struct device *dev, pm_message_t message)
int value;
struct spi_driver *drv = to_spi_driver(dev->driver);
- if (!drv->suspend)
+ if (!drv || !drv->suspend)
return 0;
/* suspend will stop irqs and dma; no more i/o */
@@ -105,7 +105,7 @@ static int spi_resume(struct device *dev)
int value;
struct spi_driver *drv = to_spi_driver(dev->driver);
- if (!drv->resume)
+ if (!drv || !drv->resume)
return 0;
/* resume may restart the i/o queue */
@@ -449,7 +449,6 @@ void spi_unregister_master(struct spi_master *master)
{
(void) device_for_each_child(master->cdev.dev, NULL, __unregister);
class_device_unregister(&master->cdev);
- master->cdev.dev = NULL;
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index 79a3c59615ab..ff9e5faa4dc9 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -163,21 +163,20 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
struct butterfly *pp = spidev_to_pp(spi);
/* set default clock polarity */
- if (value)
+ if (value != BITBANG_CS_INACTIVE)
setsck(spi, spi->mode & SPI_CPOL);
/* no chipselect on this USI link config */
if (is_usidev(spi))
return;
- /* here, value == "activate or not" */
-
- /* most PARPORT_CONTROL_* bits are negated */
+ /* here, value == "activate or not";
+ * most PARPORT_CONTROL_* bits are negated, so we must
+ * morph it to value == "bit value to write in control register"
+ */
if (spi_cs_bit == PARPORT_CONTROL_INIT)
value = !value;
- /* here, value == "bit value to write in control register" */
-
parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
}
@@ -202,7 +201,9 @@ butterfly_txrx_word_mode0(struct spi_device *spi,
/* override default partitioning with cmdlinepart */
static struct mtd_partition partitions[] = { {
- /* JFFS2 wants partitions of 4*N blocks for this device ... */
+ /* JFFS2 wants partitions of 4*N blocks for this device,
+ * so sectors 0 and 1 can't be partitions by themselves.
+ */
/* sector 0 = 8 pages * 264 bytes/page (1 block)
* sector 1 = 248 pages * 264 bytes/page
@@ -316,8 +317,9 @@ static void butterfly_attach(struct parport *p)
if (status < 0)
goto clean2;
- /* Bus 1 lets us talk to at45db041b (firmware disables AVR)
- * or AVR (firmware resets at45, acts as spi slave)
+ /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
+ * (firmware resets at45, acts as spi slave) or neither (we ignore
+ * both, AVR uses AT45). Here we expect firmware for the first option.
*/
pp->info[0].max_speed_hz = 15 * 1000 * 1000;
strcpy(pp->info[0].modalias, "mtd_dataflash");
@@ -330,7 +332,9 @@ static void butterfly_attach(struct parport *p)
pp->dataflash->dev.bus_id);
#ifdef HAVE_USI
- /* even more custom AVR firmware */
+ /* Bus 2 is only for talking to the AVR, and it can work no
+ * matter who masters bus 1; needs appropriate AVR firmware.
+ */
pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
strcpy(pp->info[1].modalias, "butterfly");
// pp->info[1].platform_data = ... TBD ... ;
@@ -378,13 +382,8 @@ static void butterfly_detach(struct parport *p)
pp = butterfly;
butterfly = NULL;
-#ifdef HAVE_USI
- spi_unregister_device(pp->butterfly);
- pp->butterfly = NULL;
-#endif
- spi_unregister_device(pp->dataflash);
- pp->dataflash = NULL;
-
+ /* stop() unregisters child devices too */
+ pdev = to_platform_device(pp->bitbang.master->cdev.dev);
status = spi_bitbang_stop(&pp->bitbang);
/* turn off VCC */
@@ -394,8 +393,6 @@ static void butterfly_detach(struct parport *p)
parport_release(pp->pd);
parport_unregister_device(pp->pd);
- pdev = to_platform_device(pp->bitbang.master->cdev.dev);
-
(void) spi_master_put(pp->bitbang.master);
platform_device_unregister(pdev);
@@ -420,4 +417,5 @@ static void __exit butterfly_exit(void)
}
module_exit(butterfly_exit);
+MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
MODULE_LICENSE("GPL");
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index a0e5af638e0e..4a51e56f85b6 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -17,7 +17,6 @@
#include <linux/types.h>
#include <asm/addrspace.h>
-#include <asm/bug.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/paccess.h>
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 076462c8ba2a..dce9d987f0fc 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
return NULL;
}
-EXPORT_SYMBOL_GPL(usb_match_id);
+EXPORT_SYMBOL(usb_match_id);
int usb_device_match(struct device *dev, struct device_driver *drv)
{
@@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
return retval;
}
-EXPORT_SYMBOL_GPL(usb_register_driver);
+EXPORT_SYMBOL(usb_register_driver);
/**
* usb_deregister - unregister a USB driver
@@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver)
usbfs_update_special();
}
-EXPORT_SYMBOL_GPL(usb_deregister);
+EXPORT_SYMBOL(usb_deregister);
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index e02fea5a5433..1a362c5e7f3d 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -1062,11 +1062,11 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
ep->pio_irqs = 0;
ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+ spin_unlock_irqrestore(&ep->dev->lock, flags);
+
/* Reset halt state (does flush) */
lh7a40x_set_halt(_ep, 0);
- spin_unlock_irqrestore(&ep->dev->lock, flags);
-
DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
return 0;
}
@@ -1775,6 +1775,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
break;
qep = &dev->ep[ep_num];
+ spin_unlock(&dev->lock);
if (ctrl.bRequest == USB_REQ_SET_FEATURE) {
DEBUG_SETUP("SET_FEATURE (%d)\n",
ep_num);
@@ -1784,6 +1785,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
ep_num);
lh7a40x_set_halt(&qep->ep, 0);
}
+ spin_lock(&dev->lock);
usb_set_index(0);
/* Reply with a ZLP on next IN token */
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 9689efeb364c..6d6eaad73968 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -853,11 +853,14 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
- /*
- * we need more memory:
- * oid_supported_list is the largest answer
+ /*
+ * we need more memory:
+ * gen_ndis_query_resp expects enough space for
+ * rndis_query_cmplt_type followed by data.
+ * oid_supported_list is the largest data reply
*/
- r = rndis_add_response (configNr, sizeof (oid_supported_list));
+ r = rndis_add_response (configNr,
+ sizeof (oid_supported_list) + sizeof(rndis_query_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_query_cmplt_type *) r->buf;
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index e9e5bc178cef..9e81c26313f9 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -191,8 +191,9 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
}
if (wait_time <= 0)
printk(KERN_WARNING "%s %s: BIOS handoff "
- "failed (BIOS bug ?)\n",
- pdev->dev.bus_id, "OHCI");
+ "failed (BIOS bug ?) %08x\n",
+ pdev->dev.bus_id, "OHCI",
+ readl(base + OHCI_CONTROL));
/* reset controller, preserving RWC */
writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
@@ -243,6 +244,12 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
pr_debug("%s %s: BIOS handoff\n",
pdev->dev.bus_id, "EHCI");
+#if 0
+/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
+ * but that seems dubious in general (the BIOS left it off intentionally)
+ * and is known to prevent some systems from booting. so we won't do this
+ * unless maybe we can determine when we're on a system that needs SMI forced.
+ */
/* BIOS workaround (?): be sure the
* pre-Linux code receives the SMI
*/
@@ -252,12 +259,14 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
pci_write_config_dword(pdev,
offset + EHCI_USBLEGCTLSTS,
val | EHCI_USBLEGCTLSTS_SOOE);
- }
+#endif
- /* always say Linux will own the hardware
- * by setting EHCI_USBLEGSUP_OS.
- */
- pci_write_config_byte(pdev, offset + 3, 1);
+ /* some systems get upset if this semaphore is
+ * set for any other reason than forcing a BIOS
+ * handoff..
+ */
+ pci_write_config_byte(pdev, offset + 3, 1);
+ }
/* if boot firmware now owns EHCI, spin till
* it hands it over.
@@ -274,8 +283,8 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
* it down, and hope nothing goes too wrong
*/
printk(KERN_WARNING "%s %s: BIOS handoff "
- "failed (BIOS bug ?)\n",
- pdev->dev.bus_id, "EHCI");
+ "failed (BIOS bug ?) %08x\n",
+ pdev->dev.bus_id, "EHCI", cap);
pci_write_config_byte(pdev, offset + 2, 0);
}
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 466384d7c79f..134d2000128a 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -101,7 +101,7 @@ static struct resource resources[] = {
},
};
-extern struct device_driver sl811h_driver;
+extern struct platform_driver sl811h_driver;
static struct platform_device platform_dev = {
.id = -1,
@@ -132,7 +132,7 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
* initialized already because of the link order dependency created
* by referencing "sl811h_driver".
*/
- platform_dev.name = sl811h_driver.name;
+ platform_dev.name = sl811h_driver.driver.name;
return platform_device_register(&platform_dev);
}
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 6f7a684c3e07..07a012f88772 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1407,6 +1407,7 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_WISEGROUP 0x0925
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
+#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866
#define USB_VENDOR_ID_CODEMERCS 0x07c0
#define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500
@@ -1435,17 +1436,20 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
#define USB_VENDOR_ID_LD 0x0f11
-#define USB_DEVICE_ID_CASSY 0x1000
-#define USB_DEVICE_ID_POCKETCASSY 0x1010
-#define USB_DEVICE_ID_MOBILECASSY 0x1020
-#define USB_DEVICE_ID_JWM 0x1080
-#define USB_DEVICE_ID_DMMP 0x1081
-#define USB_DEVICE_ID_UMIP 0x1090
-#define USB_DEVICE_ID_VIDEOCOM 0x1200
-#define USB_DEVICE_ID_COM3LAB 0x2000
-#define USB_DEVICE_ID_TELEPORT 0x2010
-#define USB_DEVICE_ID_NETWORKANALYSER 0x2020
-#define USB_DEVICE_ID_POWERCONTROL 0x2030
+#define USB_DEVICE_ID_LD_CASSY 0x1000
+#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010
+#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020
+#define USB_DEVICE_ID_LD_JWM 0x1080
+#define USB_DEVICE_ID_LD_DMMP 0x1081
+#define USB_DEVICE_ID_LD_UMIP 0x1090
+#define USB_DEVICE_ID_LD_XRAY1 0x1100
+#define USB_DEVICE_ID_LD_XRAY2 0x1101
+#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200
+#define USB_DEVICE_ID_LD_COM3LAB 0x2000
+#define USB_DEVICE_ID_LD_TELEPORT 0x2010
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
+#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030
+#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
@@ -1491,17 +1495,20 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
@@ -1571,6 +1578,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
{ 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 6649531fa824..8ba6a701e9c1 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -141,7 +141,7 @@ source "drivers/usb/misc/sisusbvga/Kconfig"
config USB_LD
tristate "USB LD driver"
- depends on USB && EXPERIMENTAL
+ depends on USB
help
This driver is for generic USB devices that use interrupt transfers,
like LD Didactic's USB devices.
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 331d4ae949ed..e2d1198623eb 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -24,6 +24,7 @@
* V0.1 (mh) Initial version
* V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint)
* V0.12 (mh) Added kmalloc check for string buffer
+ * V0.13 (mh) Added support for LD X-Ray and Machine Test System
*/
#include <linux/config.h>
@@ -40,17 +41,20 @@
/* Define these values to match your devices */
#define USB_VENDOR_ID_LD 0x0f11 /* USB Vendor ID of LD Didactic GmbH */
-#define USB_DEVICE_ID_CASSY 0x1000 /* USB Product ID for all CASSY-S modules */
-#define USB_DEVICE_ID_POCKETCASSY 0x1010 /* USB Product ID for Pocket-CASSY */
-#define USB_DEVICE_ID_MOBILECASSY 0x1020 /* USB Product ID for Mobile-CASSY */
-#define USB_DEVICE_ID_JWM 0x1080 /* USB Product ID for Joule and Wattmeter */
-#define USB_DEVICE_ID_DMMP 0x1081 /* USB Product ID for Digital Multimeter P (reserved) */
-#define USB_DEVICE_ID_UMIP 0x1090 /* USB Product ID for UMI P */
-#define USB_DEVICE_ID_VIDEOCOM 0x1200 /* USB Product ID for VideoCom */
-#define USB_DEVICE_ID_COM3LAB 0x2000 /* USB Product ID for COM3LAB */
-#define USB_DEVICE_ID_TELEPORT 0x2010 /* USB Product ID for Terminal Adapter */
-#define USB_DEVICE_ID_NETWORKANALYSER 0x2020 /* USB Product ID for Network Analyser */
-#define USB_DEVICE_ID_POWERCONTROL 0x2030 /* USB Product ID for Controlling device for Power Electronics */
+#define USB_DEVICE_ID_LD_CASSY 0x1000 /* USB Product ID of CASSY-S */
+#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 /* USB Product ID of Pocket-CASSY */
+#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 /* USB Product ID of Mobile-CASSY */
+#define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */
+#define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */
+#define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */
+#define USB_DEVICE_ID_LD_XRAY1 0x1100 /* USB Product ID of X-Ray Apparatus */
+#define USB_DEVICE_ID_LD_XRAY2 0x1101 /* USB Product ID of X-Ray Apparatus */
+#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 /* USB Product ID of VideoCom */
+#define USB_DEVICE_ID_LD_COM3LAB 0x2000 /* USB Product ID of COM3LAB */
+#define USB_DEVICE_ID_LD_TELEPORT 0x2010 /* USB Product ID of Terminal Adapter */
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 /* USB Product ID of Network Analyser */
+#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 /* USB Product ID of Converter Control Unit */
+#define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */
#define USB_VENDOR_ID_VERNIER 0x08f7
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
@@ -67,17 +71,20 @@
/* table of devices that work with this driver */
static struct usb_device_id ld_usb_table [] = {
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
@@ -85,7 +92,7 @@ static struct usb_device_id ld_usb_table [] = {
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ld_usb_table);
-MODULE_VERSION("V0.12");
+MODULE_VERSION("V0.13");
MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
MODULE_DESCRIPTION("LD USB Driver");
MODULE_LICENSE("GPL");
@@ -632,8 +639,8 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
/* workaround for early firmware versions on fast computers */
if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VENDOR_ID_LD) &&
- ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_CASSY) ||
- (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) &&
+ ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_CASSY) ||
+ (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_COM3LAB)) &&
(le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) {
buffer = kmalloc(256, GFP_KERNEL);
if (buffer == NULL) {
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f2b4ca8692d8..c145e1ed8429 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -469,8 +469,14 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MHAM_YS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MHAM_IC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MHAM_DB9_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MHAM_RS232_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y9_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index ca40f16370f1..bdef3b8c731f 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -333,10 +333,18 @@
/*
* microHAM product IDs (http://www.microham.com).
- * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>.
+ * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>
+ * and Mike Studer (K6EEP) <k6eep@hamsoftware.org>.
+ * Ian Abbott <abbotti@mev.co.uk> added a few more from the driver INF file.
*/
+#define FTDI_MHAM_KW_PID 0xEEE8 /* USB-KW interface */
+#define FTDI_MHAM_YS_PID 0xEEE9 /* USB-YS interface */
#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */
#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */
+#define FTDI_MHAM_IC_PID 0xEEEC /* USB-IC interface */
+#define FTDI_MHAM_DB9_PID 0xEEED /* USB-DB9 interface */
+#define FTDI_MHAM_RS232_PID 0xEEEE /* USB-RS232 interface */
+#define FTDI_MHAM_Y9_PID 0xEEEF /* USB-Y9 interface */
/*
* Active Robots product ids.
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index e8e575e037c1..37c81c08faad 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -73,9 +73,10 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
- { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
- { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID ) },
+ { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
+ { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
+ { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 1807087a76e3..9bc4755162ad 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -71,3 +71,7 @@
#define SAGEM_VENDOR_ID 0x079b
#define SAGEM_PRODUCT_ID 0x0027
+
+/* Leadtek GPS 9531 (ID 0413:2101) */
+#define LEADTEK_VENDOR_ID 0x0413
+#define LEADTEK_9531_PRODUCT_ID 0x2101
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 4dd6865d32b0..b5c96e74a903 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -242,8 +242,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
down(&port->sem);
- if (port->open_count == 0)
- goto out;
+ if (port->open_count == 0) {
+ up(&port->sem);
+ return;
+ }
--port->open_count;
if (port->open_count == 0) {
@@ -260,10 +262,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
module_put(port->serial->type->driver.owner);
}
- kref_put(&port->serial->kref, destroy_serial);
-
-out:
up(&port->sem);
+ kref_put(&port->serial->kref, destroy_serial);
}
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index bce3d55affd8..11a48d874752 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -69,6 +69,8 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+ { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID),
+ .driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID),
@@ -139,6 +141,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) },
+ { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index b84d1cb4c693..765118d83fb6 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -36,6 +36,9 @@
#define PALM_ZIRE_ID 0x0070
#define PALM_M100_ID 0x0080
+#define GSPDA_VENDOR_ID 0x115e
+#define GSPDA_XPLORE_M68_ID 0xf100
+
#define SONY_VENDOR_ID 0x054C
#define SONY_CLIE_3_5_ID 0x0038
#define SONY_CLIE_4_0_ID 0x0066
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index ee958f986eb8..31ca92056c27 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -106,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Christian Leber <christian@leber.de> */
+UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100,
+ "TrekStor",
+ "i.Beat 115 2.0",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ),
+
/* Reported by Stefan Werner <dustbln@gmx.de> */
UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100,
"TrekStor",
@@ -127,6 +134,14 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
+ "Neuros Audio",
+ "USB 2.0 HD 2.5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ US_FL_NEED_OVERRIDE ),
+
/*
* Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
* The key does not actually break, but it returns zero sense which
@@ -137,13 +152,16 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
"USB Mass Storage Device",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
-/* Patch submitted by Daniel Drake <dsd@gentoo.org>
- * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
-UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
- "Neuros Audio",
- "USB 2.0 HD 2.5",
- US_SC_DEVICE, US_PR_BULK, NULL,
- US_FL_NEED_OVERRIDE ),
+/*
+* Bohdan Linda <bohdan.linda@gmail.com>
+* 1GB USB sticks MyFlash High Speed. I have restricted
+* the revision to my model only
+*/
+UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100,
+ "USB 2.0",
+ "Flash Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NOT_LOCKABLE ),
UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101,
"Rio",
@@ -735,6 +753,13 @@ UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100,
"Flashgate",
US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+/* Reported by David Hamilton <niftimusmaximus@lycos.com> */
+UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001,
+ "Thomson Multimedia Inc.",
+ "RCA RD1080 MP3 Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
"Sandisk",
"ImageMate SDDR-05a",
@@ -946,6 +971,12 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK32),
+/* Submitted by Jan De Luyck <lkml@kcore.org> */
+UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
+ "CITIZEN",
+ "X1DE-USB",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN),
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
@@ -1085,6 +1116,13 @@ UNUSUAL_DEV( 0x0dda, 0x0301, 0x0012, 0x0012,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Jim McCloskey <mcclosk@ucsc.edu> */
+UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100,
+ "Cowon Systems",
+ "iAUDIO M5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ 0 ),
+
/* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
"USB",
@@ -1162,6 +1200,13 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
US_FL_SINGLE_LUN),
#endif
+/* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
+UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
+ "DataStor",
+ "USB4500 FW1.04",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3e153d313bb0..f5079c78ba4e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -520,16 +520,11 @@ config FB_GBE
config FB_GBE_MEM
int "Video memory size in MB"
depends on FB_GBE
- default 8
+ default 4
help
This is the amount of memory reserved for the framebuffer,
which can be any value between 1MB and 8MB.
-config BUS_I2C
- bool
- depends on (FB = y) && VISWS
- default y
-
config FB_SUN3
bool "Sun3 framebuffer support"
depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index df8e5667b348..466042808daf 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -253,7 +253,7 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
{
unsigned char *src;
unsigned int xindex, yindex, chipindex, linesize;
- int i, count;
+ int i;
unsigned char val;
unsigned char bitmask, rightshift;
@@ -282,7 +282,6 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
}
ks108_writeb_data(par, chipindex, val);
left++;
- count++;
if (bitmask == 0x80) {
bitmask = 1;
src++;
@@ -460,11 +459,11 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
inode = file->f_dentry->d_inode;
fbidx = iminor(inode);
info = registered_fb[fbidx];
- par = info->par;
if (!info || !info->screen_base)
return -ENODEV;
+ par = info->par;
xres = info->var.xres;
fbmemlength = (xres * info->var.yres)/8;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index 69f75547865d..c924d81f7978 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -322,32 +322,29 @@ static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
writeb(green, mmio_base + 0x791);
writeb(blue, mmio_base + 0x791);
- switch(p->var.bits_per_pixel) {
- case 15:
- if (regno < 16) {
+ if (regno < 16) {
+ switch(p->var.red.offset) {
+ case 10: /* RGB 555 */
((u32 *)(p->pseudo_palette))[regno] =
((red & 0xf8) << 7) |
((green & 0xf8) << 2) |
((blue & 0xf8) >> 3);
- }
- break;
- case 16:
- if (regno < 16) {
+ break;
+ case 11: /* RGB 565 */
((u32 *)(p->pseudo_palette))[regno] =
((red & 0xf8) << 8) |
((green & 0xfc) << 3) |
((blue & 0xf8) >> 3);
- }
- break;
- case 24:
- if (regno < 24) {
+ break;
+ case 16: /* RGB 888 */
((u32 *)(p->pseudo_palette))[regno] =
(red << 16) |
(green << 8) |
(blue);
+ break;
}
- break;
}
+
return 0;
}
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index bfc8a93b2c73..620c9a934e0e 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1326,7 +1326,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
unsigned char post_dividers[] = {1,2,4,8,3,6,12};
u32 output_freq;
u32 vclk; /* in .01 MHz */
- int i;
+ int i = 0;
u32 n, d;
vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */
@@ -1340,15 +1340,16 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
/* now, find an acceptable divider */
for (i = 0; i < sizeof(post_dividers); i++) {
output_freq = post_dividers[i] * vclk;
- if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)
+ if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
+ pll->post_divider = post_dividers[i];
break;
+ }
}
/* calculate feedback divider */
n = c.ref_divider * output_freq;
d = c.ref_clk;
- pll->post_divider = post_dividers[i];
pll->feedback_divider = round_div(n, d);
pll->vclk = vclk;
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 7f9838dceab5..98c05bc0de44 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -396,6 +396,10 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
s1[i] = *s;
i++;
}
+
+ if (i > 4)
+ i = 4;
+
} while (*s++);
if (second)
s2[i] = 0;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 556895e99645..1f8d805c61e5 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -1321,8 +1321,6 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
mdelay( 15);
}
-#ifdef CONFIG_PPC_OF
-
static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
{
u32 tmp, tmp2;
@@ -1836,6 +1834,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
}
+#ifdef CONFIG_PPC_OF
+
static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
{
OUTREG(MC_CNTL, rinfo->save_regs[46]);
@@ -2728,13 +2728,23 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
printk("radeonfb: Dynamic Clock Power Management disabled\n");
}
+#if defined(CONFIG_PM)
/* Check if we can power manage on suspend/resume. We can do
* D2 on M6, M7 and M9, and we can resume from D3 cold a few other
* "Mac" cards, but that's all. We need more infos about what the
* BIOS does tho. Right now, all this PM stuff is pmac-only for that
* reason. --BenH
*/
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
+ /* Special case for Samsung P35 laptops
+ */
+ if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
+ (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
+ (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
+ (rinfo->pdev->subsystem_device == 0xc00c)) {
+ rinfo->reinit_func = radeon_reinitialize_M10;
+ rinfo->pm_mode |= radeon_pm_off;
+ }
+#if defined(CONFIG_PPC_PMAC)
if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
@@ -2778,7 +2788,8 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
#endif
}
-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PM) */
}
void radeonfb_pm_exit(struct radeonfb_info *rinfo)
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 2406899f1207..3d04b2def0f1 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -49,6 +49,7 @@
#include <linux/interrupt.h>
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
#include <asm/mach-au1x00/au1000.h>
@@ -406,7 +407,7 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
vma->vm_flags |= VM_IO;
- if (io_remap_page_range(vma, vma->vm_start, off,
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {
return -EAGAIN;
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 9d5015e99372..151fda8dded0 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -13,7 +13,6 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/fb.h>
-#include <asm/bug.h>
static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
{
@@ -173,7 +172,7 @@ struct backlight_device *backlight_device_register(const char *name, void *devda
new_bd = kmalloc(sizeof(struct backlight_device), GFP_KERNEL);
if (unlikely(!new_bd))
- return ERR_PTR(ENOMEM);
+ return ERR_PTR(-ENOMEM);
init_MUTEX(&new_bd->sem);
new_bd->props = bp;
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 68c690605aa7..86908a60c630 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -13,7 +13,6 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/fb.h>
-#include <asm/bug.h>
static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
{
@@ -172,7 +171,7 @@ struct lcd_device *lcd_device_register(const char *name, void *devdata,
new_ld = kmalloc(sizeof(struct lcd_device), GFP_KERNEL);
if (unlikely(!new_ld))
- return ERR_PTR(ENOMEM);
+ return ERR_PTR(-ENOMEM);
init_MUTEX(&new_ld->sem);
new_ld->props = lp;
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index a7bcd17112c0..0339f5640a78 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -30,10 +30,11 @@
#define STI_DRIVERVERSION "Version 0.9a"
-struct sti_struct *default_sti;
+struct sti_struct *default_sti __read_mostly;
-static int num_sti_roms; /* # of STI ROMS found */
-static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */
+/* number of STI ROMS found and their ptrs to each struct */
+static int num_sti_roms __read_mostly;
+static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly;
/* The colour indices used by STI are
@@ -266,7 +267,7 @@ sti_rom_copy(unsigned long base, unsigned long count, void *dest)
-static char default_sti_path[21];
+static char default_sti_path[21] __read_mostly;
#ifndef MODULE
static int __init sti_setup(char *str)
@@ -414,10 +415,10 @@ sti_init_glob_cfg(struct sti_struct *sti,
if (!sti->sti_mem_request)
sti->sti_mem_request = 256; /* STI default */
- glob_cfg = kmalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
- glob_cfg_ext = kmalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
- save_addr = kmalloc(save_addr_size, GFP_KERNEL);
- sti_mem_addr = kmalloc(sti->sti_mem_request, GFP_KERNEL);
+ glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
+ glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
+ save_addr = kzalloc(save_addr_size, GFP_KERNEL);
+ sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL);
if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) {
kfree(glob_cfg);
@@ -427,11 +428,6 @@ sti_init_glob_cfg(struct sti_struct *sti,
return -ENOMEM;
}
- memset(glob_cfg, 0, sizeof(*glob_cfg));
- memset(glob_cfg_ext, 0, sizeof(*glob_cfg_ext));
- memset(save_addr, 0, save_addr_size);
- memset(sti_mem_addr, 0, sti->sti_mem_request);
-
glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
glob_cfg->save_addr = STI_PTR(save_addr);
for (i=0; i<8; i++) {
@@ -502,9 +498,9 @@ sti_init_glob_cfg(struct sti_struct *sti,
#ifdef CONFIG_FB
struct sti_cooked_font * __init
-sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
{
- struct font_desc *fbfont;
+ const struct font_desc *fbfont;
unsigned int size, bpc;
void *dest;
struct sti_rom_font *nf;
@@ -525,10 +521,9 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
size = bpc * 256;
size += sizeof(struct sti_rom_font);
- nf = kmalloc(size, GFP_KERNEL);
+ nf = kzalloc(size, GFP_KERNEL);
if (!nf)
return NULL;
- memset(nf, 0, size);
nf->first_char = 0;
nf->last_char = 255;
@@ -544,7 +539,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
dest += sizeof(struct sti_rom_font);
memcpy(dest, fbfont->data, bpc*256);
- cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font) {
kfree(nf);
return NULL;
@@ -559,7 +554,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
}
#else
struct sti_cooked_font * __init
-sti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name)
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
{
return NULL;
}
@@ -617,7 +612,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
struct sti_rom_font *raw_font, *font_start;
struct sti_cooked_font *cooked_font;
- cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font)
return 0;
@@ -631,7 +626,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
while (raw_font->next_font) {
raw_font = ((void *)font_start) + (raw_font->next_font);
- cooked_font->next_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ cooked_font->next_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font->next_font)
return 1;
@@ -668,10 +663,9 @@ sti_bmode_font_raw(struct sti_cooked_font *f)
unsigned char *n, *p, *q;
int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
- n = kmalloc (4*size, GFP_KERNEL);
+ n = kzalloc (4*size, GFP_KERNEL);
if (!n)
return NULL;
- memset (n, 0, 4*size);
p = n + 3;
q = (unsigned char *)f->raw;
while (size--) {
@@ -816,13 +810,12 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd
return NULL;
}
- sti = kmalloc(sizeof(*sti), GFP_KERNEL);
+ sti = kzalloc(sizeof(*sti), GFP_KERNEL);
if (!sti) {
printk(KERN_ERR "Not enough memory !\n");
return NULL;
}
- memset(sti, 0, sizeof(*sti));
spin_lock_init(&sti->lock);
test_rom:
@@ -1035,7 +1028,7 @@ static struct parisc_driver pa_sti_driver = {
* sti_init_roms() - detects all STI ROMs and stores them in sti_roms[]
*/
-static int sticore_initialized;
+static int sticore_initialized __read_mostly;
static void __init sti_init_roms(void)
{
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 12d9329d1408..5a86978537d2 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -509,57 +509,60 @@ static int vgacon_doresize(struct vc_data *c,
{
unsigned long flags;
unsigned int scanlines = height * c->vc_font.height;
- u8 scanlines_lo, r7, vsync_end, mode, max_scan;
+ u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
spin_lock_irqsave(&vga_lock, flags);
- outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
- max_scan = inb_p(vga_video_port_val);
-
- if (max_scan & 0x80)
- scanlines <<= 1;
-
vgacon_xres = width * VGA_FONTWIDTH;
vgacon_yres = height * c->vc_font.height;
- outb_p(VGA_CRTC_MODE, vga_video_port_reg);
- mode = inb_p(vga_video_port_val);
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
+ max_scan = inb_p(vga_video_port_val);
- if (mode & 0x04)
- scanlines >>= 1;
+ if (max_scan & 0x80)
+ scanlines <<= 1;
- scanlines -= 1;
- scanlines_lo = scanlines & 0xff;
+ outb_p(VGA_CRTC_MODE, vga_video_port_reg);
+ mode = inb_p(vga_video_port_val);
- outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
- r7 = inb_p(vga_video_port_val) & ~0x42;
+ if (mode & 0x04)
+ scanlines >>= 1;
- if (scanlines & 0x100)
- r7 |= 0x02;
- if (scanlines & 0x200)
- r7 |= 0x40;
+ scanlines -= 1;
+ scanlines_lo = scanlines & 0xff;
- /* deprotect registers */
- outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
- vsync_end = inb_p(vga_video_port_val);
- outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
- outb_p(vsync_end & ~0x80, vga_video_port_val);
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ r7 = inb_p(vga_video_port_val) & ~0x42;
+
+ if (scanlines & 0x100)
+ r7 |= 0x02;
+ if (scanlines & 0x200)
+ r7 |= 0x40;
+
+ /* deprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ vsync_end = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end & ~0x80, vga_video_port_val);
+ }
outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
outb_p(width - 1, vga_video_port_val);
outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
outb_p(width >> 1, vga_video_port_val);
- outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
- outb_p(scanlines_lo, vga_video_port_val);
- outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
- outb_p(r7,vga_video_port_val);
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
+ outb_p(scanlines_lo, vga_video_port_val);
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ outb_p(r7,vga_video_port_val);
- /* reprotect registers */
- outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
- outb_p(vsync_end, vga_video_port_val);
+ /* reprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end, vga_video_port_val);
+ }
spin_unlock_irqrestore(&vga_lock, flags);
-
return 0;
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d2dede6ed3e5..996c7b58564e 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1550,6 +1550,7 @@ int fb_get_options(char *name, char **option)
return retval;
}
+#ifndef MODULE
/**
* video_setup - process command line options
* @options: string of options
@@ -1593,6 +1594,7 @@ static int __init video_setup(char *options)
return 0;
}
__setup("video=", video_setup);
+#endif
/*
* Visible symbols for modules
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 38d22729b129..5e25b9860196 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -656,12 +656,15 @@ static int gbefb_set_par(struct fb_info *info)
switch (bytesPerPixel) {
case 1:
SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 2:
SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
case 4:
SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
}
SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
@@ -1243,7 +1246,7 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)
(void *)gbe_tiles.cpu, gbe_tiles.dma);
release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
iounmap(gbe);
- gbefb_remove_sysfs(dev);
+ gbefb_remove_sysfs(&p_dev->dev);
framebuffer_release(info);
return 0;
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index ad416ae47596..7db42542eb19 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1510,6 +1510,8 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
default:
printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
"contact maintainer.\n", pdev->device);
+ release_mem_region(addr, size);
+ framebuffer_release(info);
return -ENODEV;
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 6b8bd3cdf9c0..995b47c165a7 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1333,33 +1333,35 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (regno > 255)
return 1;
- switch (dinfo->depth) {
- case 8:
- {
- red >>= 8;
- green >>= 8;
- blue >>= 8;
+ if (dinfo->depth == 8) {
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ intelfbhw_setcolreg(dinfo, regno, red, green, blue,
+ transp);
+ }
- intelfbhw_setcolreg(dinfo, regno, red, green, blue,
- transp);
+ if (regno < 16) {
+ switch (dinfo->depth) {
+ case 15:
+ dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
+ break;
+ case 16:
+ dinfo->pseudo_palette[regno] = (red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ break;
+ case 24:
+ dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+ (green & 0xff00) |
+ ((blue & 0xff00) >> 8);
+ break;
}
- break;
- case 15:
- dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
- ((green & 0xf800) >> 6) |
- ((blue & 0xf800) >> 11);
- break;
- case 16:
- dinfo->pseudo_palette[regno] = (red & 0xf800) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11);
- break;
- case 24:
- dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
- (green & 0xff00) |
- ((blue & 0xff00) >> 8);
- break;
}
+
return 0;
}
diff --git a/drivers/video/kyro/STG4000VTG.c b/drivers/video/kyro/STG4000VTG.c
index 3690b04190af..bd389709d234 100644
--- a/drivers/video/kyro/STG4000VTG.c
+++ b/drivers/video/kyro/STG4000VTG.c
@@ -17,7 +17,7 @@
void DisableVGA(volatile STG4000REG __iomem *pSTGReg)
{
u32 tmp;
- volatile u32 count, i;
+ volatile u32 count = 0, i;
/* Reset the VGA registers */
tmp = STG_READ_REG(SoftwareReset);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 747602aa5615..b961d5601bd9 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -486,10 +486,8 @@ static void vgaHWRestore(const struct fb_info *info,
static inline int neo2200_sync(struct fb_info *info)
{
struct neofb_par *par = info->par;
- int waitcycles;
- while (readl(&par->neo2200->bltStat) & 1)
- waitcycles++;
+ while (readl(&par->neo2200->bltStat) & 1);
return 0;
}
@@ -843,6 +841,9 @@ static int neofb_set_par(struct fb_info *info)
par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
+ /* Initialize: by default, we want display config register to be read */
+ par->PanelDispCntlRegRead = 1;
+
/* Enable any user specified display devices. */
par->PanelDispCntlReg1 = 0x00;
if (par->internal_display)
@@ -1334,6 +1335,18 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
struct neofb_par *par = info->par;
int seqflags, lcdflags, dpmsflags, reg;
+
+ /*
+ * Reload the value stored in the register, if sensible. It might have
+ * been changed via FN keystroke.
+ */
+ if (par->PanelDispCntlRegRead) {
+ neoUnlock();
+ par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
+ neoLock(&par->state);
+ }
+ par->PanelDispCntlRegRead = !blank_mode;
+
switch (blank_mode) {
case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */
seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
@@ -1366,7 +1379,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
case FB_BLANK_NORMAL: /* just blank screen (backlight stays on) */
seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
- dpmsflags = 0; /* no hsync/vsync suppression */
+ dpmsflags = 0x00; /* no hsync/vsync suppression */
break;
case FB_BLANK_UNBLANK: /* unblank */
seqflags = 0; /* Enable sequencer */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index dbcb8962e57d..a7c4e5e8ead6 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -138,6 +138,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f3927b6cda9d..f5361cd8ccce 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -30,7 +30,6 @@
#include <linux/module.h>
#include <linux/types.h>
-#include <asm/bug.h>
#include <asm/io.h>
#include <asm/system.h>
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 25148de5fe67..eeeac924b500 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/types.h>
-#include <asm/bug.h>
#include <asm/io.h>
#include <asm/system.h>
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index e5d0f92eeae3..feec47bdd479 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -588,6 +588,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
goto bail;
}
+ platform_set_drvdata(pdev, info);
default_par = info->par;
default_par->regs = ioremap_nocache(pdev->resource[1].start,
pdev->resource[1].end - pdev->resource[1].start +1);
@@ -638,8 +639,6 @@ s1d13xxxfb_probe(struct platform_device *pdev)
goto bail;
}
- platform_set_drvdata(pdev, info);
-
printk(KERN_INFO "fb%d: %s frame buffer device\n",
info->node, info->fix.id);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index d574dd3c9c8a..9451932fbaf2 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -82,7 +82,6 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
-#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index ab727eaa7f43..10e6b3aab9ea 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -2021,8 +2021,8 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
#if defined(CONFIG_FB_SAVAGE_I2C)
savagefb_create_i2c_busses(info);
savagefb_probe_i2c_connector(info, &par->edid);
- kfree(par->edid);
fb_edid_to_monspecs(par->edid, &info->monspecs);
+ kfree(par->edid);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
&info->modelist);
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 3e7baf4c9fa8..5e5328d682db 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -786,28 +786,32 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (regno >= info->cmap.len || regno > 255) return 1;
switch (info->fix.visual) {
- case FB_VISUAL_PSEUDOCOLOR:
- rgbcol =(((u32)red & 0xff00) << 8) |
- (((u32)green & 0xff00) << 0) |
- (((u32)blue & 0xff00) >> 8);
- do_setpalentry(par, regno, rgbcol);
- break;
- /* Truecolor has no hardware color palettes. */
- case FB_VISUAL_TRUECOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ rgbcol =(((u32)red & 0xff00) << 8) |
+ (((u32)green & 0xff00) << 0) |
+ (((u32)blue & 0xff00) >> 8);
+ do_setpalentry(par, regno, rgbcol);
+ break;
+ /* Truecolor has no hardware color palettes. */
+ case FB_VISUAL_TRUECOLOR:
+ if (regno < 16) {
rgbcol = (CNVT_TOHW( red, info->var.red.length) <<
info->var.red.offset) |
- (CNVT_TOHW( green, info->var.green.length) <<
- info->var.green.offset) |
- (CNVT_TOHW( blue, info->var.blue.length) <<
- info->var.blue.offset) |
- (CNVT_TOHW( transp, info->var.transp.length) <<
- info->var.transp.offset);
- par->palette[regno] = rgbcol;
- break;
- default:
- DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
- break;
+ (CNVT_TOHW( green, info->var.green.length) <<
+ info->var.green.offset) |
+ (CNVT_TOHW( blue, info->var.blue.length) <<
+ info->var.blue.offset) |
+ (CNVT_TOHW( transp, info->var.transp.length) <<
+ info->var.transp.offset);
+ par->palette[regno] = rgbcol;
+ }
+
+ break;
+ default:
+ DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
+ break;
}
+
return 0;
}